PyChart-1.39/0000755000175000017500000000000010352125056014453 5ustar santiagosantiago00000000000000PyChart-1.39/doc/0000755000175000017500000000000010371713025015220 5ustar santiagosantiago00000000000000PyChart-1.39/doc/pychart/0000755000175000017500000000000010352146643016677 5ustar santiagosantiago00000000000000PyChart-1.39/doc/pychart/drawing-graph-canvas.html0000644000175000017500000001656410352146644023605 0ustar santiagosantiago00000000000000 21.2 Drawing plots on canvas


21.2 Drawing plots on canvas

PyChart creates a new canvas object when "area.T.draw()" (see Section 6) is called for the first time, and no canvas is yet created at that moment. You can thus use you own canvas by creating a canvas before calling the first area.T.draw(), like below:

can = canvas.init("foo.pdf")
...
ar = area.T(...)
ar.draw()

You can also achieve the same effect by passing the canvas object to the area.T.draw() method explicitly:

can = canvas.init("foo.pdf")
...
ar = area.T(...)
ar.draw(can)

You can also pass a file object (or file-like object, such as StringIO) to canvas.init. In this case, you need to define the output format via the second argument.

fd = file("foo.pdf", "w")
can = canvas.init(fd, "pdf")
...
ar.draw(can)

Naturally, you can write to multiple files by passing multiple canvas objects to different area.T.draw(). For example, the below example draws the first chart to graph1.pdf and the next chart to graph2.pdf.

../demos/twographs.py

from pychart import *

can = canvas.init("graph1.pdf")
data = chart_data.read_csv("lines.csv")
ar = area.T(x_range = (0,100), y_range = (0,100),
            x_axis = axis.X(label="X", tic_interval=10),
            y_axis = axis.Y(label="Y", tic_interval=10))
eb = error_bar.error_bar2(tic_len=5, hline_style=line_style.gray50)
ar.add_plot(line_plot.T(label="foo", data=data, error_bar=eb, y_error_minus_col=3),
            line_plot.T(label="bar", data=data, ycol=2, error_bar=eb, y_error_minus_col=3))
ar.draw(can)
tb = text_box.T(loc=(40, 130), text="This is\nimportant!", line_style=None)
tb.add_arrow((ar.x_pos(data[6][0]), ar.y_pos(data[6][1])), "cb")
tb.draw(can)

can = canvas.init("graph2.pdf")
ar = area.T(loc=(200, 0), x_range=(0,100), y_range=(0,100),
            x_axis = axis.X(label="X", tic_interval=10),
            y_axis = axis.Y(label="Y", tic_interval=10))
ar.add_plot(line_plot.T(label="foo", data=data, data_label_format="/8{}%d"),
            line_plot.T(label="bar", data=data, ycol=2))
ar.draw(can)

# Note: can.close() is called automatically for every open canvas.

PyChart-1.39/doc/pychart/creating-canvas.html0000644000175000017500000001313210352146643022632 0ustar santiagosantiago00000000000000 21.1 Creating a canvas


21.1 Creating a canvas

A new canvas is created by calling the class static method canvas.init. It is closed by calling the close() method of the canvas object.

init( fname=None format=None)
This is a "factory" procedure that creates a new canvas.T object. Both parameters, fname and format, are optional. Parameter fname specifies either the output file name or a file object. Parameter format, if specified, defines the file's format. Its value must be one of "ps", "pdf", "svg", "x11", or "png".

When fname is omitted or is None, the output is sent to standard output. When format is omitted, it is guessed from the fname's suffix; failing that, "ps" is selected.

close( )
This method closes the canvas and writes contents to the associated file. Calling this procedure is optional, because Pychart calls this procedure for every open canvas on normal exit.

PyChart-1.39/doc/pychart/rangetest.png0000644000175000017500000001164410352146636021411 0ustar santiagosantiago00000000000000PNG  IHDR'uPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"!IDATx] +~[nAZ\迯΀@xx@xx@xAB << << << <@QJS xU)"+=̪*RaCaj6͒c]HE|^Sc;i H*X=aޅ 4y؇P;U!"z.9*vqfUڅ gaIoㇰ*H~'TЃф5ζ"*A[ 4vԱHA5=mrQ>]ڦ5 XPg  U݅/=Hhw,m =mB` ζ2E '8Fo>QڦzHhZo*鿔TU !.?T>;GQH/J8*=7_%Ql5!n6!>SzZz Aɍ(]!)x*\遴xF⾺ k*u3.PL.ҋE#0ߴE»b @0ؒJԵ@xrt#]`xh;ST:e)xK*Jt]x6<cZ_5)16t<`h^h*UÚ˽I`W3S@Ïz|SdWtS$`Ctj~eY>&e1}TrS4x6.jzR_ xU< o Mj?@@+F *2$o k5Ht˺B^gk[nE oaǖa1](U^)߱ T1&96g, 9uKnk> VXIBpO,yZ";9[ڼl4>~=KzT ӞAa4RG'\o":hrUSF(Kjm8άR #JC>*9u;4:32HL.zh7c=JƛYxAU\M`P0bI?PE*EbK6Y+a29z(a[:x_˪B{`j-Y-2n51QS"Æ~7Z>²~ }dy Y5'o_ebY,UG'7~ʝp5df CɤJXh*B"@V+C9iaeq(׵k*0\@XY {F9h$0C߄߇Rx\{y"8xn bR5Rznb7:P$"KS#Wo數]q{NU^q(:rOf3FRw]l>t p'}pJގܟ$_>}x1cIlRקk-m2^ smV< DrT'o<% #.2~pwXx:C\O/V%6IڵOy.?+/jjǫqW8D6kU㔯m}H'e4huw.x^ 3h`w7]帾$Dv- ^Yy*ܽfVn8vzNZ_E5なa⭒$@Fx S>^qIDy|T8;mT@`^TqU=3tȋ9 N|~ŹEY8y=N.|Qx |-+ߏKMx:l"b< N@nMx59{/z1'Pci%5?<}S`\YB9M Sf@q=f>Df@ii8eCt,'+{*@a+|?ӎ9N,p:p; S>:0¢-HC ك7M!g,,O۵bt:EpIrҬn%9a~6:}x^F=X3.ÖE5rƒ'sqct&rwq7cĖO@:z8YQs|{\=VY>A&IZ ClE}Y Ca,O`:tIr3 PW:PUe|Su=1+30>_>9vw'0=>| aL:!^`3 )|X>Bk' 8C7t  d+ΖÜp@YXlΝ^zrP('hL3?dx/<}ȼ0g`Gö&fÈ>WUs)x ge?>^McV8}sR9^P.8q}GMv-izh"0(%۷Cb5wwv<_F=wޕ3χ6^A!<Ƀk:<Jx(}PPqޜNpC)<Ox!B!a)<43;*Ʌ پ$@r^ }W;'M7]Y㏎"o80V쥰BIYU4?Zd!ǁOxJ87 }w|H*٥-xnf9'B8O2_/-t~;!Ry>x@xx@xx@xx@x0S=bøHFܝ_y @ڼ`Sꫂ?~>?zt#MCສσvV!~r'xx .inU?[7 ٣xh'.inloJ4\_w!ͭYAo Z4[\F)w}w|C3|ܿ8vbMY7$8 13 PyChart options


13 PyChart options

The behavior of PyChart can be changed in three ways, by setting variables in module theme, via command-line options, and via environment variable PYCHART_OPTIONS.



PyChart-1.39/doc/pychart/fonttest.png0000644000175000017500000004103010352146636021253 0ustar santiagosantiago00000000000000PNG  IHDRfRsvPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx : D{;HY ! y n$п WpA@@,` X A@@,` X A@@,` X A@@,` Xqo ZJmnF]ņvg|7RApmn-CMß &8bzm?1jףۂNb6'g8qھ=,R!Saz6E]^q9NǨ}Ήv= :Iō30ijæt:>p֛安iEsΒ}\8e&[%2.HzW/51G YWLRE7s%ZGx‰_}yeޫ,#A)n.q +`oIm6//wP }_"4W-'` X A@@,` X A@@,`D';/Y~l 6ŗz(ABq?^)xAen~G_|{/?9߲)mAO_ ƚCLLu,_qc*%6?WnX`[tc*/1Q7ƙz&)CFԤ~΢RxT̶)D|@'X `sT5L)Үl^_N=i9c'}N)"İ5]b%,}.%2N~pGXurhX7ۋ6ǃQ<[f@6,dJ~{[X;р3S",mؓ|?c,J}|~}CX ZLLu|a'}N@a:~zOQ5,}Z34zB hh$ŭ )%byHnsO:ܢ=0_5p`!R{5cic[UA;v`^R2ShDž>m×cԐzħ'X=_b<ANP$sx9 qT ^v >i!c`G͔F'MSj`9[Z۪wzppNLUl LձRKzNMD2`vueEO%7LRۥX nق5ʑM%' n_qvٓFL\Oz.hT6 ,szxC{ŰAz_s`i+&}Y`ոSFB.])Ywqc<Ί~oN0͏bS3i ث0k5Lom5gL>lwG[ԗCSqL13q<o2rtWScP[+Q ֓>(p*ؙA^pNخ'Neze\"F*=Sݕ.5fWy]z"ع1[F\O+RM&抶ŏs2{pNmtSe9܀U: 4_!73w8ce? *p{%oh"]'.ظrjJ8HZD~:N{LO;>7y4:lj={{NK6w+ȩA&'wE"ؒ8e46,<3&2"N.O f&?uslHGv0|fǤ0o'W}oxYN{u_">S#ݣ7òg3^/oel<@z沐!4fW#D X A@@,` X A@@,` X=._S;$>r)Ku"/SX*%iOϖΰH]FbצK@%8Vho ; ;ݙ Dϻ,Rǣu3R_[mVDe%0D?#XjcTa |wkGLz%~ҴNM#[ł?l񲤿|e#k+ձZmBqnN֝dt=af}Ff:E_{a|sZ1o&e[g`7u.o]?VI`ؙN۪\Z7 813+`y'-]SGfe:77M[ڮYEF̴tlL8+MBh6ܢI4Z'K.L_wZjs-]t*jQfZja=,:=0Թn|}|`ya,tʩ%Ug ބ^4b"mTs\3rӹ`okZ;Az%K)ᶦuLN~m,ZOLK(Lߘm.n-z%ᘼ'.g4dtkf6j"-9]LBU3KG̴X8}4fnjx?<|jMm2 &봸{q{u<|wޜ'X:[u2qޖrސ9_?%Hc8U,etV '@N,MWv>h/Qbkup>g Y5mu#| _jm2\8SCG[յ8i^8&ιlf5Ai SLZLpOװNs`yZuS˾CiꔾS+Vh p.ϏyVIljpH1?1қK.bOr\$$ω v9 8H=W>QRY§.j?Ab61{'lgn{8=`;_Sp{89L HR]ŵp{`5S^`6שO"L'i~L귪4Z  Z|Seks6}rz. qSAqǙ!]Q-\;җ2&yΝ!X.c"` 4Q/a4AސO5H۩\b a;:_l 5pmBFOXVk[޼&Ǘ<٠S }p/ ,~@{0:[sJv A@@,` X A@@,` X A@@,` X A@@,` X A@@,` X A@@,` X A@@,` X A@@,`bts(QK؏Ox'sAKQ. tg7n V>RU]fZ!J|{W$6x]Sӊ\t3 v&-SM+t4m|1/yhwۖQڥ4\ӎ5:_W[ |%nJLKo)Cv%[b=fXٕ?9*w[=_JkMO *l벑ձQl, eimeb]ZP],JZ/5kS뙊oYm|lɯ,Fܤi4p_eCQEԩ[(zt [Ÿ?O]`7BjҔj̷olT,ږc[&P @,`YtUu Jx+e]s.6 p[t'M}zb8䩁*:X^kvkκףa'X"˸ԧ k Mz}}(τc~#sOR 62vv%T6^k8aC`{ Vvgpްni$;o)Acr\[fv4a痤- v_qfc/iԖ_ڡ ǩM_>Y'Njum(i:elP V92;76iL p wWb{[n%imGv R.|=,eƽ,esᄄl"w-ㆀcxi2#FMwjغ n-C.SoF)X۲ +:NF 9j3Yft[Ato^>vS8!u}&6O ib )P0tV1κ+j[z=,XWg&)Tq]xցѰnm5ܘVMnCw՚qٙ`];몷u)”*(sFy^۝2I?ە/M}ƣwHNrz6ɴM>J 6Q61u W ֗oP,dc[.⣛2j@bUРŔ_I\q`[*-8ӂUдP*;te3H7Oc"#\)rdk'I-ofQu׽La XOƅ4s5u={ <-1\Znjl˄zlS~jXv,ӫUc 4%y=66{U(j/bԖ뇸\&~¾LZviw%q]?Ղaө>66Wgį$뇸Zu?K' kG_ؗ/?t-3Sv%q]?хVo:v1)vcsLJ~[ȤI0]k)͵ Go _+'ҰT>{uJ~܉'M~} X@e0 A@@,` X A@@,` X A@@,X-rRج y[ k4GO1o#T~kG{P>ܭ%^-OSW9@N16ߵuS@Ws4L{>\+J' ֕%RXS6tu {?uaoރ}%b ?eV-mSLrYČk[BKF^JaƂ*XS#I֤*6m_ׅ75/dm٪qs[V Exr+X' -鼅lhNq K6h̑FV_=ɾc i_†Lnq2ֵl`Yr`i0]] Z"`m&۴Yv6 viun*-T-6NnrMjKbŞ;.ƢFtQyiiT9!t᯹`9Ъ ͥ?dClp}C%9siZJW=ńjҏcXc8 SfcL pxڧ{i[ tѪA|.O=hrҥ<0Px =⼵Ye\IQ_хU;)WQe*VCƖtS֚A`,Xrώe(86Jΰ S겕 62-i{.lP._g+5j6n^|t#woyin`)؉u]]:y=ҍۂI`kJypԩ6KmXژTZ骃TzERGxV-idЫwثlW4 :&l,OqmX)hNn4l>Hf"%KKKp۰x6aҼ-2l|;,Nտ Y*=jj_OGyɺm!dN3F[3ueuAʭes`<1H `f6~A@@,` X A@@,` X A@@,` \+Xn'3V۟G?i+? .a·fz-Xu4>0osyb1x-rnghm(ǿ'|7`Q7u'?)JgxUz*OLk ;,}c0B쨨 :%J UZYc>f;' ףbK(8F"p+.Ga!۲U\R&싔w`ȯ!(UJygbcL:6b!ɦ7j0ZwuXiELG?x2 +՘W=kw7&i)6y.lUv6ub @مߏ]ٜu]a# <&xÓ`=th[F(IaòkaH:6u@r{`<ȭ`]=͍ڕRSȜu&$̨ 3fod\VY1~NH ׈AU"ykŸ%r/ ؎2^LTL%U]DDF-;=?&؝p +6]jmY "ğRRn[ىik 7n64OؖjOm!cog=n v,bVul5ЪW 6+4*׫r}lUЮլ϶wkN vr;=5 ]J;knpÃ(LWL2&Jr4vj1s`k[OY2xl`k.y0m]-E1\ ⤦Sk*3?EY_%.t \CQ.{ӌ6dsVts`k/2?&kHn;6ca{'v+{չ^R%b:OyDqmzH걘Rz#}W.,L}.E)XD;-t JM] lof6Rg]l-LLدz_-Xj2d>.s_\VX< tҨ~,X-̶[_(ZD3.fPPֱirr>mH$ّ9ijEk$&XLKe&TѠ܎}Z]ƽo`8>@3.J%l(q7˳U/n}ˇʶџ 6zsSfR O6-׺ǂ-E[l qӻ옢c/P3JhښSi{M8fcҰUl{%eEHvNI<1t$Yo-qvMOM&piR|!5Y$%}\yʧәp!Nކ]%MrQ…f "u&wN\=t &̷x›/߫|`Y]Կ?`3!X=QFx˚ .췁fF,` X A@@,` X A@@,rz|3|W ~?}q<0Q__l#\-}b.}*qz9>V4GavO.ߺiݍ%8bݗ*pgWN۶kJ88(v'@'~fZJƅ)b4=C.5"lh<ł́c0b@*WT=)CGo*jGD4$\6.-TiQLO,Ipꭧ[M9"1w3}opmy&X?Sm˂kj:B=6ũ Cݓhz'76C]שPMA,1y ֞)bt5 b좤PWMz]Smg$t•1d:6Nsz׮vYhYq*9}6hT,۵s.[`H-43k*6E6E'5 +ނ7{סvw?[JO1cuikm.͢oְ1|"C^`m=3>)lm(ceÓc]NM\Rr佦WkrUlJwE͎԰6\i!"sT%}z4 !,fUM.%O$AZvN`v *JB=-EH6Oxoނν4\lc$=YuQ:wN;¤j7^75q.PF| K&CsT` MFt{^ QkEFa˞MSUWxZm]5,O|  (aLxA@@,` X A@@,` X A@@,`M;|uZ+=(4}\!UGݍ?Xlףߥ%wXL{~|7lJgKSEw%߂&kQ){bW҉bo`[\>V*͊q1T딳*β*O3)k{knDyroAOo7<r79صQjkRD-k\_L y}X&qyTjC` %vF*շ")a!Ucx.RF6Ԑˏ[b88Gڻ&/vR֏rŮ P]TP !q6܄Wγl}gԀ->lccݎ;W/KDñW:FP@x1$}gڅS[>vϿcm}CY?^؋jA\!z Ujm|`e 1vsݜJ$#ƠzLmgb^Kt>g]aW۲mj#5Ǻj0O7S }R -!M]DmM8 6sQ:ŵn A%]fuQbWI5FJzRV$yhZNn2 +`+MI^m?(@Vm*ř~*3r~)N8$d|x -k|J%GbXc5˅e}쐻VQ'̟rSs8sS!2+QM's;A S57.rT1f2IO7.,>i/e >׍f~LV"R;A <\yJj)3lH),)i`Ժ[56V!&X?(Rvd4N땅\gO;]ع`Ya%CvEQ JׅKzq(E]u9T.q,QU'Ed/t0ܼ%%ͽcFV~aC65C3gwWvwLn; tiIqᘳ7 ;)]bAk}fF5<Ç X=rOl:!cM{%jGND; vfcw][\b-\}N0m{oh $8V%w%raDzT;`3(wDV/=Tkn}XkhkkZ$VvľG8_+R$3<@4:EG.NvN5q=px8"tLJw}ho1Zخo/va ^`G<z!xHO) \"ĉ=8?Yd%?|y0g"W:%οaV&DO}ebzAdy6>RNڰ\"էSY~|7Kbx6Ve״LtrJd_0N{4,Wܳq(o{;3riپ<n/DO,}Z"S܎Y(g):ۏQ@%_F_0Ywx. >ig7Xw(wVgl_J,ޕ)ȲVbYw)_,>7,q~gȡ:念!F(lG^ߗQdIdIJYYJ>K)+rYl"KcAdi ,~,qXǍ1 4D{pu@Y"KcAdi ,qXǍ1 4D{pu@Y"KcAdi ,qXǍ1 4$߽d%O8?Yd%O8?Yd%O8?ϋ,q"K' 2..YV5]Յ܉p?]gbZnxڈ{r)^oF&fe ]y_I]ͿΟҏ.?QO7E!\# Ο/NfCE!,KCC* %ˊi\wt5fU]=e;\W8r޸ ezW3_W CEW7v%K?Ta}>f_ar qDR_<>Z`0ԪB:.f>/5}Tu37*Ǫ.w0e?_qrc[n-ˮUB&u`uxUHM珦)n r[,q"K'ĉ,q"K'ĉ,q"K'ĉ,q"Koa9N>|;'-,!y4,+Q!|A $|AZ".Μ^M`Xۓ ,vv) E,fQyPxja;$ˢja 21.6 Shortcut functions for the default canvas


21.6 Shortcut functions for the default canvas

For the default canvas ( see Section 21.3), you can call the following functions provided in the canvas module directly:

line( linestyle, x1, y1, x2, y2)
Calls the method with the same name on the default canvas object.

polygon( linestyle, fillstyle, [(x1,y1), ..., (xn, yn)])
Calls the method with the same name on the default canvas object.

rectangle( linestyle, fillstyle, x1, y1, x2, y2, shadow=None)
Calls the method with the same name on the default canvas object. Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

ellipsis( linestyle, fillstyle, x, y, radius, y_elongation=1, start=0, end=360, shadow=None)
Calls the method with the same name on the default canvas object. Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

round_rectangle( linestyle, fillstyle, x1, y2, x2, y2,radius, shadow=None)
Calls the method with the same name on the default canvas object. Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

curve( linestyle, [(x1,y2), ..., (xn, yn)])
Calls the method with the same name on the default canvas object.

show( x, y, text)
Calls the method with the same name on the default canvas object.

verbatim( str)
Calls the method with the same name on the default canvas object.

default_canvas( )
Return the default canvas.

clip( x1, y1, x2, y2)
Calls the method with the same name on the default canvas object.

clip_ellipsis( x, y, radius, y_elongation)
Calls the method with the same name on the default canvas object.

clip_polygon( [(x1,y2),(x2,y2), ..., (xn, yn)])
Calls the method with the same name on the default canvas object.

endclip( )
Calls the method with the same name on the default canvas object.

PyChart-1.39/doc/pychart/blank.png0000644000175000017500000000200710352146643020473 0ustar santiagosantiago00000000000000PNG  IHDR DPLTE 3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f̙333f3̙333f3fff̙fff3f̙̙3f̙3f̙3f333f3333f3ffffff3f̙3f3fCAbKGDHIDATxcI0*U0`*d.CtEXtSoftware@(#)ImageMagick 4.2.8 99/08/01 cristy@mystic.es.dupont.com!*tEXtSignature0ac660e469fb3b89a555665df224a4be tEXtPage32x32+0+0S2IENDB`PyChart-1.39/doc/pychart/module-fill-style.html0000644000175000017500000002140110352146645023134 0ustar santiagosantiago00000000000000 16 Fill styles

16 Fill styles

class fill_style.T
This class determines the color and the pattern of the background of a region. Class fill_style.T itself is an abstract base class; actual drawing functions are provided by its subclassess, which are described later.

This class supports the following attributes:

bgcolor
Type: color.T ( see Section 15) Default: color.white.

The background color.

line_interval
Type: number Default: 3.

The interval between successive stitch lines.

line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

The style of the line.

class fill_style.Plain
This class just fills the region with solid background color. Attributes line_style and line_interval are ignored.

class fill_style.Diag
This class fills the region with diagonal lines.

class fill_style.Rdiag
Fills the region with diagonal lines, but tilted in the opposite direction from fill_style.Diag.

class fill_style.Vert
Fills the region with vertical lines.

class fill_style.Horiz
Fills the region with horizontal lines.

class fill_style.Stitch
Fills the region with horizontal and vertical lines.

class fill_style.Wave
Fills the region with horizontal wavy lines.

class fill_style.Vwave
Fills the region with vertical wavy lines.

class fill_style.Lines
Fills the region with a series of short line segments.

The below picture shows the standard set of fill styles. They are named like fill_style.name, where name are the labels shown in the picture.

Image fillstyles

Just for your information, the "rdiag3" style shown in the picture can be created manually by the following code:

rdiag3 = fill_style.Rdiag(line_style=line_style.T(width=3, color=color.gray5),
                          line_interval=6)

You can create your own fill style by subtyping fill_style.T. It should provide the following public method:

draw( self, can, x1, y1, x2, y2)
This method is called to fill a rectangular region in a canvas. Parameter can is a canvas ( see Section 21), and region (x1,y1)-(x2,y2) specifies the region to be filled.

Just for your information, below is how the Rdiag class is implemented.

class Rdiag(fill_style.T):
    """Fills the region with diagonal lines, but tilted in the opposite
direction from fill_style.Diag."""
    def draw(self, can, x1, y1, x2, y2):
        line_width = self.line_style.width
        interval = self.line_interval * 1.414
        x1 -= line_width
        y1 -= line_width
        x2 += line_width
        y2 += line_width
        len = max(y2 - y1, x2 - x1)
        while curx in range(x1, x2 + len, interval):
            can.line(self.line_style, curx, y1, curx-len, y1+len)

PyChart-1.39/doc/pychart/module-font.html0000644000175000017500000001174610352146645022031 0ustar santiagosantiago00000000000000 17 Drawing texts


17 Drawing texts

You can display text strings in chart as part of axis labels, plot labels, legends, and such. You can also display an arbitrary text at an arbitrary location using annotations ( see Section 18) or canvas.show function (see Section 21).

See Also:

Section 13 for a variety of ways to set default text attributes.



PyChart-1.39/doc/pychart/date.png0000644000175000017500000001044310352146635020325 0ustar santiagosantiago00000000000000PNG  IHDR_qPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx흋v8D!.5j2uϙɺ0@fbzo]&bz ؄^lB/6ЋM&bz ؄^lB/6ЋM&bz ؄^lB/6ЋM&bz ؄^lB/6ЋM&bz ؄^lB/6ЋM>{ȴc<^qͳB 4⣗|D Cq#X~ M>zq逈^Q2JÞW]"b=$N 7;;/W^Tˍ| .VF>{YN-ٖKrѸ\A ziľ]鯪aӶYA؎bY6^*e򏭯y[0yj|oy2~{*b=;oxy_ɢЋN‹??-_Cvi:o%UwxZ̿{ۧx߼wo}[^*FЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, dQE'B/:YzɢЋN^t(E, 4͠f4ҋ,ҋm3w"ziKzwz~իaW/ys\zu^4q"zi|Wv+^0j"ziK-6)aE0իÊa{uX%6UQċ;w:;ˏ.o+{IJ逡ѻ˗e|oq/5?!k^~iE0K/6&kϾ_?N&XOyBa5hC}2 xco}K#^Y1w/~ $++f/7Ε/]y J>Xgҡ]J^Y ]ŭ$++ԣ+ pNV.lB/6ЋM&7yA*s=^C*;ڑN~W):oG$GvNbm-pXE_5ɦ+;x ˏ?n~=d*9$R0wxA*byL9gmP 2Vj{sFbR cqZ>I^"sSd6D`KF/7$l",U[eMmԽZcVXǁ_5]0ULMkATUD1c]^AYrhATSӥrA ˦e7 n$Խ[PvNPʺ:7]^]viQ,{s%^ZPv}۷oZxvI_z5]w-&YnM=0-VY^M]B/FQa0@UhUm?9 uc$e<^C/Rv!k tLj<$)^Bꠒ}xMfuO@>_':B.@Q2M r?Ō#ŲZk&GY"F8Ei|%LL~e3WK4.nS_"Sz)֠~ =UʔHEh{ ZU:S8}iʓ';]*.R0>Hw츎oZ(IO'UbKę`2Ws51s|~42닱0eWȧ?/"E+Ǻ 9K0 NҘtU6튼dMZ{QrvیӾv&ʒ+[UFL6]{L4g9T9e茕IYvнIheH4p`q鈛j'(R Ks/RݡI"$؝/Gy1\DӼ^謁TRR}AX~ӊt/՟׊Ÿ맬K6ܡ|Eo~J?LTv -K9@֗ų@)VvX1Cqi`{Q^lB/6i).5~IENDB`PyChart-1.39/doc/pychart/images.idx0000644000175000017500000000000010352146636020642 0ustar santiagosantiago00000000000000PyChart-1.39/doc/pychart/errorbars.png0000644000175000017500000000765010352146635021417 0ustar santiagosantiago00000000000000PNG  IHDRR(e0PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" %IDATx݁zHE}7Wd"nNI`<ENYP He]|3w}9{q|uWdwzd,>zdlKC)R uu(%cCKQ.ʝ5JXoZR2ץV-u)]. dloZk )%c.dlo]j JT_ZR267KA)Rkux}Vh& JXK0_9K)R+PJƶ F)֥/%#^_ @)fKx}PJF.R2R(%#^_ @)֥PJF.R2R(%#^_ @)Kx}]*d뛥PJF.R2Kx}]*d뛥PJF.R2 @)TJɈ7Kx}]*d[ @)TJɈ7Kx}]*d/R2uo @)TJɈ׷.R2uo @)TJɈ׷_*dR*5<ͽmΪ]]z&h(^c] (U#TPF^c] (U#TPF^cPFtril(RB*ѥʅRUb]\(U%TPJR4NQRB:yzRTRB:1K D*NRLJ^.U*LM+g)RBJѥJ(UKRK *,U2]dv?Jc]d(U!TPBR%C ѥJGK\O|*ͱ~;\K|t?Cw.1KL*R*]d8=6M34۶yvT{:GwϽfRéQ*RHLkKxlнpOkB|t732]jXBjnu2x.NkVR_QoPjx.r{;);9R{gB"RRE@J|W/Uw.Uwu? ѥ4ǺԟRRJcP*]OC|*죹G|tTJRK *ĺTPBtTJRK *~TR%C 1K *D*JUuTR%C 1K *D*JUR%C ѥJRb*JU.U2R%C ѥJRb*JU.U2JRK *,U2]d(U!֥JRR/@*f)K`*JU.U*M3E_X&rK?@|tbi&EW`*JՉ.U,RB:ѥRub*t( trT/U.]\(U%frTRm^uTRC1K jD*JՈRCѥwQ6~R{gՌ.%#^_ @).dR(%#^ץҡx}]*d~|(%#^_ @)fKx}R(%#^_ @)fKxO/dR(%#^,R2uo]*dR(%#^,R2uoTJɈץPJFY*dR(%#^ߺTJɈץPJFY*dR(%#^~Kx}TJɈץPJFuKx}TJɈץPJFR+4D)uѧR2R+PJƶ M3E)֥֘d,ץh&E)RkPJƦRkPJƦYj[(%c. dlo]jJR_ZR27KB)[RE)ZR26ץ֡ RPJƆ:uu(%cC}]֕j7k1{^wLJQZ*R@*R T(B) JP HR@*R T(B) JP HR@*R T(B) JP HR@*zů2>Drtf#V>Hk#>,cr9d<ޗ31TaJF7({ԜYwg$SF̃f3'crdSJK(6*5Ώ~M{O۶ӔZh匾?cIJ-ed*1Wfji,8>~OiJ=6RNd!dAFYJ-eM;=w8ɬaR8ܡ3pR2̔q4Gqx[yRR.IqFצ=L3_2(uf֟RFo1ϼJqMttrYMJzX?^mՉ'ZNv8&*zq,&1|EHR@*R T(B) JP HR@*R Tއ[ľBIENDB`PyChart-1.39/doc/pychart/linestyles.png0000644000175000017500000001347610352146636021615 0ustar santiagosantiago00000000000000PNG  IHDR0mPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"IDATx[==~랍IJhHZUWHS Tv @00`` @00`` @00`` jLtz4v%iwg٢|}tWӮJ  @00`` @00`` =h~AZvr)z)7RnfΧcӒ"zi[c ^ٰiDܚ%3)wj]%v<)Rܕ Ʈ|N0v`֑'fgҷ,8{#}yO0-[g(.W3kθ9] RvrEd̅ƪ!ɺk8E xa#w^sio<{yUq ctY~R,Y݂)͔Js)!gO۝5:盃LH$#^҉J|uo!n-ms.*VY6q! &-Nk(D\2vm-PrM'WΤ.xnUXn:[ԏ<y^̦eLYzt]K~R|*~ :VJw=gWYj"RqI>d?Yaȶ,L}W0y6\<3V ΀ky`>l{,OG>GanĎzG g3Ǵ&|!@00``5Q,k[+-_]X-"J*M2|1T,5ZDZ_IèEx< r m{Z_Y> (kh YeE Y(khJGA+ki}e5"̏^C[E,W9eo-"lE{@0?͵` @00`` @00`` @00`` @00`` B^F?%iwg~_<7ʶcNk}үZ 1 @00`` ,Co<ľauѯVÔ|=vFŸ ' Nzi[ ݞ<CXu򉂉5KfRzWxKqW$rJ0v_Y*uٙm8 12i̹׮<(mC VΧebJ_mu=:֩ȯ|@p<)o|Ɂ) UmTF%kzS6ؤ"I? [".YlmZ MSPtجٮo'I^S dJLNPPDH0>ҙ( GoL)Ƣ~-ɳ]y^ &Ft8.τ3[77%{{:ث|/'+ fX)LLȺ:u)oL_CW vI:&O'~o'W.L52۫dն藻X3N՝fh~&_ݰsZ{K'^Jijײ~]$g̳tyW0O1nfvzk ٫.m/7i w^/ 3U#"wӥEuI~xX9sx\r]L3nNW[em*[1Z\("w+1f)͞OD>2_zann<, ~&y~`-fA5=uS3,U>4nX ˂oyjw_7uU0a>?3r^]\Mm σc#kR)~}HثHɓ *$F>K)<=V.aRsR*̛F>8/*#7y5U9o3-ģD7>rUa44yxRi&Wo2瀐o|  |p)޲]ܫ՛9 d@0H/9|pUzU^Ê넛; bjF~}UihL6S۫XNymLm%c}UZx)K{k̮2^ 8"vgQg%Z$ԫ.SeOtc$8^j\ZoA g9γ2=j%?4MAVgdǿNga$lʋ]׽_~^Lz:uJB!|*VXJg ^xxcJ5[nE;oOJ04qI|&|A/z('+H΋:cU*SDF0!3Y#YF0}^[n*վ's<LJv6* (_0 lUۢ_bͬ;T_k6LU@$Ga*LOe?(Hxҙg`.cm(#J$_gUWŶ엛;E}CYg*:F0EDK'Gr{-RTֲAOu;_(.y̔9t+~͟|ۺ_ۦZ8iεhN.W0EDVcx:_xkV"=:BJ-V9s]w/ϳZW7aL]R|R,Y^b ]nbUg=K8@&6wK)ͭ37͝y. =.ŻgKܾK UֺMC &M>s&R լ"SbVݕkk#oJiiߥߒv¢#ϱEӑ`l[ΔGE'e`Е}?o#f5I:Jm\Z)^j!L[J%BDq9u?(,By6\<3V 힠/QpEH~ژ=J>f)͞OD>4R:̭؍D>̷l=H%G`X53,U>5=uS_53,U>4nX 9k06gYΫS௛*c#f强&௛/$F>Zc=RWᑔ'2);7>ZUH|5JSxz#^/ejK0wo| z=|p)^*Fjsff1S[o| ´ihLM^-ׯdf!S]@6|p)޲T8rW7s@ԁ`D7>;6y.VQ) GnV]'bfS0*MC#gFB_4wF];7>ZUH|5wrSmfSHo|ƓXko.#U 20 Zap marks

20 Zap marks

A zapping symbol is a zig-zag symbol that indicates that a certain region of a plot is cut out due to space constraints. It's usually used in conjunction with non-linear/non-logarithmic coordinate system. See Section 6.1, for an sample of zap symbols.

zap.zap_horizontally( canvas, style, fill_style, x1, y1, x2, y2, xsize, ysize)
Draw a horizontal "zapping" symbol on the canvas that shows that a graph is ripped in the middle.

Parameter fill_style specifies the style for the zig-zag lines. PAT specifies the pattern with which the area is filled. The symbol is drawn in the rectangle (x1, y1) - (x2, y2). Each "zigzag" has the width xsize, height ysize.

zap.zap_vertically( canvas, style, fill_style, x1, y1, x2, y2, xsize, ysize)
Draw a vertical "zapping" symbol on the canvas that shows that a graph is ripped in the middle.

Parameter fill_style specifies the style for the zig-zag lines. PAT specifies the pattern with which the area is filled. The symbol is drawn in the rectangle (x1, y1) - (x2, y2). Each "zigzag" has the width xsize, height ysize.

PyChart-1.39/doc/pychart/property-canvas.html0000644000175000017500000001362610352146646022735 0ustar santiagosantiago00000000000000 21.5 Setting canvas properties


21.5 Setting canvas properties

A canvas.T object provides the following methods to define the information about the output file.

can = canvas.init("foo.pdf")
ar = area.T(...)
can.set_author("Charles Dickens")
can.set_title("A tale of two cities")
ar.draw(can)

set_title( str)
Define the string to be shown in EPS/PDF "Title" field. The default value is the name of the script that creates the EPS/PDF file.

set_author( str)
Set the author string. Unless this method is called, the Author field is not output in EPS or PDF.

set_creator( str)
Define the string to be shown in EPS %%Creator or PDF Producer field. The default value is "pychart".

set_creation_date( str)
Define the string to be shown in EPS/PDF "CreationDate" field. Defalt value of this field is the current time.

PyChart-1.39/doc/pychart/module-range-plot.html0000644000175000017500000001710710352146645023130 0ustar santiagosantiago00000000000000 10 Range plots

10 Range plots

class range_plot.T
A range plot is similar to line plots ( see Section 9), but it fills regions, instead of drawing line.

Image rangetest

Sample range plot

Below is the source code that produces the above chart. ../demos/rangetest.py

from pychart import *

data = [ (0, 10, 30, 40, 60), (10, 20, 40, 50, 55), (20, 10, 35, 38, 43),
         (30, 8, 30, 35, 39), (40, 8, 20, 28, 39) ]

ar = area.T(x_axis = axis.X(label="X axis"),
            y_grid_interval = 10, y_grid_style = line_style.white,
            y_axis = axis.Y(label="Y axis"),
            y_grid_over_plot=1, legend = legend.T())

if theme.use_color:
    colors = [ fill_style.darkseagreen, fill_style.white, fill_style.brown ]
else:
    colors = [ fill_style.gray90, fill_style.white, fill_style.gray50 ]
ar.add_plot(range_plot.T(label="foo", data=data, fill_style = colors[0]))
ar.add_plot(range_plot.T(label="bar", data=data, min_col=2, max_col=3,
                         fill_style = colors[1]))
ar.add_plot(range_plot.T(label="baz", data=data, min_col=3, max_col=4,
                         fill_style = colors[2]))
ar.draw()

This class supports the following attributes:

data
Type: any Default: None.

Specifies the data points. See Section 5

fill_style
Type: fill_style.T (see Section 16) Default: fill_style.default.

label
Type: str Default: "???".

The label to be displayed in the legend. See Section 6.3, See Section 17

line_style
Type: line_style.T (see Section 14) Default: line_style.black.

The style of the boundary line.

max_col
Type: int Default: 2.

The upper bound of the sweep is extracted from this column of data.

min_col
Type: int Default: 1.

The lower bound of the sweep is extracted from this column of data.

xcol
Type: int Default: 0.

The column, within attribute "data", from which the X values of sample points are extracted. See Section 5

PyChart-1.39/doc/pychart/module-error-bar.html0000644000175000017500000002216710352146645022755 0ustar santiagosantiago00000000000000 9.2 Error bars

9.2 Error bars

class error_bar.T
Error bars are used in conjunction with line, scatter, or bar plots to show the confidence interval of each sample value. See Section 7. Class error_bar.T is an abstract base class. Actual drawing is done by its subclasses, described next.

Image errorbars

class error_bar.error_bar1
This class supports the following attributes:
line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

tic_len
Type: length in points ( See Section 4) Default: 10.

Length of the horizontal bars

class error_bar.error_bar2
This class supports the following attributes:
hline_style
Type: line_style.T ( see Section 14) Default: line_style.black.

The style of the horizontal bars.

tic_len
Type: length in points ( See Section 4) Default: 3.

The length of the horizontal bars

vline_style
Type: line_style.T ( see Section 14) Default: None.

The style of the vertical bar.

class error_bar.error_bar3
This class supports the following attributes:
line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

class error_bar.error_bar4
This class supports the following attributes:
box_width
Type: length in points ( See Section 4) Default: 4.

fill_style
Type: fill_style.T ( see Section 16) Default: fill_style.gray70.

line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

tic_len
Type: length in points ( See Section 4) Default: 4.

class error_bar.error_bar5
This class supports the following attributes:
line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

class error_bar.error_bar6
This class supports the following attributes:
box_width
Type: length in points ( See Section 4) Default: 4.

center_line_style
Type: line_style.T ( see Section 14) Default: linestyle: width=0.5, color=default, dash=None, cap=0, join=0.

fill_style
Type: fill_style.T ( see Section 16) Default: fill_style.gray70.

line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

PyChart-1.39/doc/pychart/command-line-options.html0000644000175000017500000001312710352146643023625 0ustar santiagosantiago00000000000000 13.2 Changing the default behavior via command-line options


13.2 Changing the default behavior via command-line options

The variables in the theme module can also be set from the command line. To do this, the program that imports PyChart must call theme.get_options in the beginning, because PyChart itself is just a library. Below is an example.

get_options( ARGV = sys.argv[1:])
This procedure takes a list of command line arguments in argv and parses options. It returns the non-parsed portion of argv. Parameter argv can be omitted, in which case its value defaults to sys.argv[1:]. The options supported are: "--format=[ps,png,pdf,x11,svg]", "--output=file", "--color=[yes,no]" "--scale=X", "--font-family=name", "--font-size=X", "--line-width=X", "--debug-level=N", "bbox=left,bottom,right,top". The below code shows an example.

#!/usr/bin/python
from pychart import *
args = theme.get_options()
ar = area.T(...)
...

PyChart-1.39/doc/pychart/tickmarks.png0000644000175000017500000002676010352146635021411 0ustar santiagosantiago00000000000000PNG  IHDR?z1i PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx흉EXleL%j%g`;%[R-?r ?r ?r ?r ?r ?r ?r ?r ?r )yu:>&PȡC@k9@9@9@9@s?0HPO3LL/Ш69.TB}6;?n*NM1'vzs~w~g񭷸x֛6YM1v7Ll6&*;\e3Yg*&tb洀scldXjWrVv7גO D' `KÛ}|skëSlۗݝLEmXgih,8S8j~ >U}h=o-EsHygo "/?$醱(8w<ʊ-_1תމ!5Cfp\S\?ҀN*S'ͷNaXsU.8o"W7ߗo~)}FnmT@a:/z60P4*([Cܾe;yAW? =M|o6T:3hf@5Zo6q1U?.w6eԖ(K|ޒ,Rr9IrͿ~CZeY\κjkV(& Ym7yAOjS@5_z[Ewb?e<<~ӭ YuuNHbm?p OH=쓗 Ŧ̠`L&Y߱ 2 GQOX g?Ë7WuO3{5<DΔk .XC+{7tzԙ8Û 4$/of\ =VV+B{7V7nj m0.{oݙp5%'X6߱?8jE[ٽw! ͼN_biH6nVV*+? ՊPVXO?-o)]jZ">?f5 [oWg9@9@9@9@9@9@?܈~MWqhYb霵a%hOg)#J(K*K)YڇȨ:M_iQU?tfpWQuUVI9T/sduT^#ǦkvX'*FbfG4U:E7MZji~T\eFS^_E`4謦\ƨM-bVk6ήF<>?r ?r ?r 9b0Ǘďₖ34ʰT&).h9SK[XMqA Z6q>1'vzs~w~ߘ[0n1^ʯ).hQejt0ݼ!m6;h- ǶcѲti&4scF`qS]%RAOS\ТG?Kf?.U0\>?ΧԂ$(ҲRuq\oP5OVU> MqA"-+)wlC%XTSw}ٽͧ?AEZO_&}%R.SL.v(ܥ\iV?ŤSY>%'n Zi'АhSsdlaASr7B EO\ТH&Un_`N6Kn3.G_o|MqA"-uHv;P.6- 8rj8N|Jjh ZiَSaOaCnch>>˧<}&FM\ТH?.f2"{gSVc?G<Q(h<Ш]) p\2hJ-Ol ٧Pq.r?EZVC |>O|qh Ziy?xbatkCS4-l?!Ue G|Jו YGQ\ТG4˧Uء@f$ZS'u'\M7Ga<=0"ºv^єY=FX척qc8aܞgŕ\uv~],)PAZ/=>OӦ({ۃfG5y>l3l*V|sj KXrZ=U˥A bJ^0nҳ|OWS.a-9jT-Wc~͆<<7/*V|F~OSKX/9IAJZX"d!NO^Y#|ܜpHY h#;h+LhYRvC|zgh̘6FX읣0MZ. Rb\;՚\Ez9sy,vю0MZR֕BcTǯV|c[xRL9?/\+>[yVL^ui9_./W|oe[4n9?ϵ\(+7T_tXL}CӻbsnK-ib?0U?}be!ؿ;+;6ra\^^4dn]@IKi2_]7Q[Xk\;_Vәs?RƦCESb/--7T7މț Z՛k^haWTCTe.Ӥ6 QOlx1]c/ {4<ts+5}(rewUaJhi6< mܙ/̉+~\|[Y1h"((OlJ:bgƙ-X=̆#jCqaSˬ&-F. ao.]IK-YڸALf,Z^h9ɔ>U}8MZ<X~f]N:*S ZG.F"jH"ܢa.pεN_I]q\%[^ m0kb[BKyJMx-1ŤV#Sk.w4vSLR1n)EgHK*wE5\ d=ޚrՎ .vSOg}_Æ#eTU=ubs˦E͘&-r[}ă#~eH!:i- X2;ag=u4djQԻY''7ZLA(ځq__bLYfk5OȮ/3?e/i.0뫶-YXg~)~dw;,f.rRڏC_?\`u*v?{(вI.pY&!>54ii L;ֻ#O4i[rOS6l8Yw^QL-F\ *؏=kw-\ji;r_5!fGpiInn,3iOZʷ37\{͆J {rNe*^r5JQ.rkrՐw?i)O'^;{͆SJ7 uTAnD˕%kRsW4Z*IjC>spD6\ddV%[q|HVk⋺ybKƔ{?VJ7-{ +zd "-S/Ws~BZ*nCCnZsvd)#JUS7>)76!-5z{W}X2Ok-W< ic>*/߬ela<-ɥ+I)}}/0>-ɳ\)Kqguw(勇*6T_֠pPf%{vWrՔw;O]AJyOhn7䮨IcyR-'˙|՚ev(%Z.,WMY^zyjUnEU rFE^8b8Tev(%Z.,WMYVKﺮ in^9h]]6,UrF}MXc$w(%Z,W-ٝK5D=V]eay3@p}yxx0Z2E˕!֟~W6۠Iٰ~7Tf5i9h* 4YMZʬ&-g~(ѣI9@9@9@9@9ZɷЌN*s[4CPh3!&;X\x%2fD:j~"!w+n3hO.QK˨?GW@UZTkF*'z( )QunHQլUvne2Q"e 5BnE3߀V|@9@9@SO|> ?r gkҫO>}t"grݘfθ19$F}z1=ΛƿaknKom@5?e͗¶ΛƿBk-0 )T}e]AZ[fw|&Z7? ?6}10+na7δ)uZh儦BS-X4Ra\aKokё_ӇLĢF ˝jt&o'G 6}T\}O#b94fߚ6vjEZ}qm饘;:q.0?)2 gkEcT?Hb@Ku>ң+2ls-:IsGS%d-s]Z>E#-sv61ŏf#d~kOsݸ=mZloOTX@0Ni,Zh9GY0fH/򑄿\`~_~O~UE|ZAg݆X~,q (\`)b?iK,EcXв{ ?9 S0VB*8v EzrӨ~j9? |Zvϑ?؉[I=Z>P&rk kx~?\`z.0-.WG#=?ʹbB9r+YZk߹ZO;-Xвs~?\Iibظ|#=?HbB9r"iqikiĢ9(H#iP{pr?W$2TW&iE&ZsasjѤa@y98?|gbBo`aIaSKl ZC6Yr庼l u}i^?XՇMCPuyyE/՛#L{/8b[΢#6$QYL <˳;O0N`Wk-&6`5yvx1!7ο )PfdI|0]>Oȿ/?~ڇ5sL\L q&ԧuyKEzr' M-R+ qƸ 睯.&*e&w*&_xÎ.&kBE oabN/7\1)bBota?r y?)p*9@9@9@9@9@U+ =eƢ*B骇[Q%T^|ʋhǻ=a?"?I&xW'.St*ФEg%Qux?g.-ZhҢ? ?r ?r ?r?B=Tf@L!n~[Mg09'.vcrHz.y蟝 nf<=Zӣ)sEK1CmԧSiv s}g}>.'}%E.=yCh&3:ZKIQ=~-a9hIpN]אkL>LF|Plz ;:|Vb`k9]Tėߔdl4h8LJs^hznJf۩e2qW2ꝦzdZ8uˮ/әlꟘ2;? r"w3VB6˟Om-O%_j9g>0m ƫ0)OQGE8wb.ht6Ն1i:nGcthiy]a+r'נϒl] _[Zlo`!q;ŗv}#ZZ39"Xtz8or.nQqoi11qM3qiٰ99 ҋ\w\]f$JO8nGCqi|rz~sMu7_+{Sw.ӘHb4}~^HR5G6{ڷP~-WSٝ6]x(Cry]J Kf_/Us~!2qiEqԝɫ.y&-39@ao>g8iByO\\4~nM)rMԘn ՇMkVKecg .TKsj;\?ST<񝅺G@R1 aIDATkWq'fʰd'@CՁ}pK+C{mSnc셴uvb3ĥբ!8AvҼo}) j͢7?++/^q[k}uOY/~?9@专oz9@9@9@9@T9{B\5?. yIW=@Eh6O B}z#J2ҮDtJ (QM(Mgۛ0 2;}yyG˙e`Xlo?#{evm\8+30Xe%3cQˬ-b-W6iIGZuc-ϯ7=1:r^,g/?RS$Z^.l]rV,(y?1SZ5 Zkw}y[ʾ?batK6rUfg|CS}.ZK5%`k9=+1աXlZUp1ZLg]`YLrv,*Xl]Sfix`ԸcQҕ۷gXl/u>2s!YԄ65\弹4`C8pgverz, Ϟc0v?c.˵9@u5i؅?r ?r ?r ?r ?r ?r ?r ?r ?rbȘ=-ܩG9ĥ‡#g>\>x12o* >?m XjOvT?DK(D EQf)g_*״jGPGSwPW v55p??r ?r ?r ?r ?rw#])Jv <0f?3&?*yenitMjiAC≖1g!G&WC1[Ŗ6zpn~4M[ cw:S\nRus= 4?}8C&)Cc.援4bP$HF-^џvLLRЦY6Y&>;|WJ >}Q[2GvvlX2sAЦY6AӓU}fs8V{\|{~)QPMai<-}1l渮3Cn~}yc?994vgISs\!akѤ%a|rB-+TmMU=. -.3(ZkvגiӲ{>ii?Θe}ƕFScI[ w `w] TiY޺CIyV?okiM͗ ew!7&l; Uk5L c5Mx^jiӎPWm-McO9K>D|*aBcFʹŐM]-4f9{|(4f5Ş>7~x܌#v\"(r\Peޙ}oߴFؠfbx ?rwsФ/, ?r ?(A IENDB`PyChart-1.39/doc/pychart/node2.html0000644000175000017500000001614710352146646020610 0ustar santiagosantiago00000000000000 1.1 Line plot


1.1 Line plot

Image linetest

This example draws a simple line plot. Below is the source code needed to produce this chart.

../demos/linetest.py

from pychart import *
theme.get_options()

# We have 10 sample points total.  The first value in each tuple is
# the X value, and subsequent values are Y values for different lines.
data = [(10, 20, 30), (20, 65, 33),
        (30, 55, 30), (40, 45, 51),
        (50, 25, 27), (60, 75, 30),
        (70, 80, 42), (80, 62, 32),
        (90, 42, 39), (100, 32, 39)]

# The format attribute specifies the text to be drawn at each tick mark.
# Here, texts are rotated -60 degrees ("/a-60"), left-aligned ("/hL"),
# and numbers are printed as integers ("%d"). 
xaxis = axis.X(format="/a-60/hL%d", tic_interval = 20, label="Stuff")
yaxis = axis.Y(tic_interval = 20, label="Value")

# Define the drawing area. "y_range=(0,None)" tells that the Y minimum
# is 0, but the Y maximum is to be computed automatically. Without
# y_ranges, Pychart will pick the minimum Y value among the samples,
# i.e., 20, as the base value of Y axis.
ar = area.T(x_axis=xaxis, y_axis=yaxis, y_range=(0,None))

# The first plot extracts Y values from the 2nd column
# ("ycol=1") of DATA ("data=data"). X values are takes from the first
# column, which is the default.
plot = line_plot.T(label="foo", data=data, ycol=1, tick_mark=tick_mark.star)
plot2 = line_plot.T(label="bar", data=data, ycol=2, tick_mark=tick_mark.square)

ar.add_plot(plot, plot2)

# The call to ar.draw() usually comes at the end of a program.  It
# draws the axes, the plots, and the legend (if any).

ar.draw()

To produce a PostScript chart, just feed the file to Python.

% python linetest.py >linetest.eps

Or, to produce a PDF chart, run python like below

% python linetest.py --format=pdf >linetest.pdf

To handle command-line options such as --format=pdf, you need to put theme.get_options() in the beginning of your file. PyChart also supports PNG, SVG, and interactive X11 display.

See Also:

Section 13 for more information about output control.

Every PyChart program starts with line "from pychart import *" to import classes and objects provided by PyChart. Each chart is represented by an area object (see Section 6), which defines the size , the coordinate system (linear, log, etc; see Section 6.1), and plots to be drawn. The final line of a program should end with area.draw(), which draws all the components of the chart to the standard output.

PyChart-1.39/doc/pychart/node3.html0000644000175000017500000001336110352146646020604 0ustar santiagosantiago00000000000000 1.2 Bar plot

1.2 Bar plot

Image bartestv

The below program generates this chart.

../demos/bartestv.py

from pychart import *
theme.get_options()

data = [(10, 20, 30, 5), (20, 65, 33, 5), (30, 55, 30, 5), (40, 45, 51, 7),
        (50, 25, 27, 3), (60, 75, 30, 5), (70, 80, 42, 5), (80, 62, 32, 5),
        (90, 42, 39, 5), (100, 32, 39, 4)]

# The attribute y_coord=... tells that the Y axis values
# should be taken from samples.
# In this example, Y values will be [40,50,60,70,80].
ar = area.T(y_coord = category_coord.T(data[3:8], 0),
            x_grid_style=line_style.gray50_dash1,
            x_grid_interval=20, x_range = (0,100),
            x_axis=axis.X(label="X label"),
            y_axis=axis.Y(label="Y label"),
            bg_style = fill_style.gray90,
            border_line_style = line_style.default,
            legend = legend.T(loc=(80,10)))

# Below call sets the default attributes for all bar plots.
chart_object.set_defaults(bar_plot.T, direction="horizontal", data=data)

# Attribute cluster=(0,3) tells that you are going to draw three bar
# plots side by side.  The plot labeled "foo" will the leftmost (i.e.,
# 0th out of 3).  Attribute hcol tells the column from which to
# retrive sample values from.  It defaults to one.
ar.add_plot(bar_plot.T(label="foo", cluster=(0,3)))
ar.add_plot(bar_plot.T(label="bar", hcol=2, cluster=(1,3)))
ar.add_plot(bar_plot.T(label="baz", hcol=3, cluster=(2,3)))
ar.draw()

PyChart-1.39/doc/pychart/bartest2.png0000644000175000017500000000664710352146635021151 0ustar santiagosantiago00000000000000PNG  IHDR+%>1PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" $IDATx흋*D1x ñkʹb ;@vLz^0LzD؋{Lz^0Lz^0Lz^0Lz^09͈~z; 㯲 zK蠟kH2A/By/=ԒY?O~]"/]Drܞ"/&ǠEJtEJ\Hnm~2A/Bx.ԛt{^JL_}:ne/{tt%X^.Ћo^>{áLz^0Lz^0K0oiz^0Lz^0Lzv/c>|siz^0L/^6!*Y_~pS*uwuC/q+sܝՋ1/"Dsxq`E/oG/{_1\jKﳾ:9|믑ߧz/0G1^'[z^0A˖ǫc}^0A8z$￷zG55Eo/e_ "De*~;Y\; x9[_Jk8>/޸xg.!ЧbqQ"DJz9 wç!~n=^\++خm{4"`oy~}za}>_{Y7,)N~}ߎMX1a9kdKqn~5]iY؇/|*QGRclٸؘЋ"/>*X~|K^T~퀁y]["T~}edbX&O/L˯2 %pC}iCʀq?^ &^_.K/?Lz$)-t?9oC/BlͶi/;ȼK^RkЋ{? !ӮlK~nX^XzA8߸SzU}8߅-+_eƧ\_C//^.tЋ|ob^Wy4e:gŧPWyN6zμ C8n_`_eg^^Jgr미87ZD~\_μ *ῼGn̫ vVB/ͫХkU//zΫ0 #\_vU헦-{rn~^?K1"`B/ xa//[z^0Lz _ xa}B/ & `B/ &^ z^0Lz^0A-^9^\d.d*Wc~_C/>fVG>jJO(9>9/CEd7O@/:_V6~t=60őT )htS}=/vK}=[z^0A] z}Q2K Rq%z9^+^_% p}'x1bKJ^Nl`CrT\^@/?6D/+]u۝=ݯlC^NvUY|wyq}?oE Fl ы`QG@F;KE_<>uoi!z,؋EuP uiԽ ы`QG^׆ߑeqokCi֗b{qAKeX *N?߳2%%art rK1^8Hxާo</r:7%\zeס5Eׁ"wwҋ_y_ы 'vu "@5C/PE TQ3^ `B/ &z^Y3^>B+jNȦt~gu ZQz6P &eŁY9MwVCtC)F֋ҡ%R_BF}7FyEMS+B2wbN<|J|V-)GKJqc1|Sxr~Q4V/)Gt<^:t엱%m2z7}Za/Fx`S9/RZW1qlTH+e뗔#%z5 q YBI-Ѭ}JB˘Ҹ+JCח{tqRP#^ղcu+JCš:@(_ؗW ڏtz^0Lz^0Lz^0Lz^0L2QS< e5y|d#Tux;rܵy4xyx<zTTTTTTTTTTTTTTTTTTTTTTTTΙjzUן>6(OL{3/ҙ:eJK_ UNv5nR7X=P貮]#69/=T.1]T0+L;ME{ LEhםu=k$0SXyt;rL|,cNrp5ްAY:c:Lwl^TΘa9^JQ{`*E`O`O`O`O`O`O`O`O`O}rpJTA}7R :1(oЉ-X`*E ߠ8»"ZKb LEoʗTg;9\7(Z}/e%||{$)n8 L L L L L L L L3hן}7EbGKG2 ie}`Z$|4}`Z$oԐ30-7變;"1|d sH ``m toL y"q|coHO T7UXV\+U:LEʆ$V05| '_I`oUz0|%ZTe%$VʙϹՐ:0H3br"/*R)] K>VUo|8`},It*Q`jbrCWEHO1d+UzS~gb0ܾ47VOmfrci.3cz۔̶Tg|43VL_H;CUKk*і~GS)1rRO{זdLn] Tvc;ѽs߫Ov:7mcM[0}OҗHmi olݯۚTvS9$#1_B0-=6-򘶰-nK5mw%5mt;mbM[0GjcM[00mcM[04}#5mtt,0-{vl7ز#9 izc:cֺޘNv -k4͸Fj];@^[X`*EiR%0CiK%J%b<JwiMo.cz"0]i*Au>Ub b)g<`* p6>b)g<`* p6>b)A*rcj9 T SƤ<4:{MvV2SFi Ǭ}SjYqԭXq : bQ)3?H;\>5$>Qkn24=ƵRyHu^9XCkEd֎T1S_6&*%n,%H:qYNLRTo3Yu+ PJa/cucbf:{CRy8Ǭź4Z6yh/7UIPqVwSk#NͿu3>{j}gZo10b j˧/3_ү+{#ӿxC;}9|8~70b R`5n3-Z :O}En_A;K Bc9&[XJJk+sV1کXJJG4>L47bxC,%is?DYd1 o/!i؞f5N>.Ð9 ~o.5i7]1ӓ-O1lO-6JS}`/L=?f )_ψwMw)<3cK4vD3'@t3q{,W|Zln9[+S`O`O`O`O`O`O`O`O`O`O`O`O`O`O`O`O*.еԦ,no ~0K4/G3Z8LȾ QSZWwiE =xm管eerDo`ڀbtZ +7C0 LT^iVic0aS.VtFm]9bDt0v ȅOߟF/)2OF=`*Zj۞-:)ԔTTyIENDB`PyChart-1.39/doc/pychart/escape-sequence.html0000644000175000017500000002264210352146644022642 0ustar santiagosantiago00000000000000 17.1 Escape sequences


17.1 Escape sequences

A text string may contain escape characters that control its appearance. The escape sequences all start with the letter ``/''. Thus, to display ``/'' itself, you must write ``//''.

Restrictions: /h, /v, and /a must appear in the beginning of a string.

/add
Specifies the angle of the text. Parameter dd is a number between -360 to 360. Value 0 means left-to-right text, 90 means bottom-to-up, etc. If you want to print numbers right after an angle specification, put { between the angle and the number. For example, the below code shows string ""100"" at a 60-degree angle.

"/a60{}100"

/hA:
Specifies horizontal alignment of the text. A is one of "L" (left alignment), "R" (right alignment), or "C" (center alignment).

/vA:
Specifies vertical alignment of the text. A is one of "B" (bottom), "T" (top), or "M" (middle).

/T
: Switch to Times font family.

/H:
Switch to Helvetica font family.
/C:
Switch to Courier font family.
/B:
Switch to Bookman-Demi font family.
/A:
Switch to AvantGarde-Book font family.
/P:
Switch to Palatino font family.
/S:
Switch to Symbol font family.
/F{family}:
Switch to family font family. The below example draws string "Funny" using ZapfDingbat font (which produces some meaningless output).

canvas.show(100, 200, "/F{ZapfDingbat}Funny")

The list of available fonts are the following:

Bookman-Demi Bookman-Light Courier AvantGarde-Book AvantGarde-Demi Helvetica Helvetica-Narrow Palatino NewCenturySchlbk Times Symbol ZapfChancery-MediumItalic ZapfChancery-Medium-Italic ZapfDingbats

/b:
Switch to bold typeface.
/i:
Switch to italic typeface.
/o:
Switch to oblique typeface.
/dd:
Set font size to dd points.

"/20{}2001 space odyssey!"

/cdd:
Set gray-scale to 0.dd. Gray-scale of 0 means black, 1 means white.

//, /{, /}:
Display `/', `}', or `{'.
{ ... }:
Limit the scope of escape sequences. For example, "{/10{/20Big text} and small text}" will display "Big Text" using a 20-point font, and "and small text" using a 10-point font.

$\backslash$n:
Break the line.

Image fonttest

Font usage example

Below is the source code that produces the above chart. ../demos/fonttest.py

from pychart import *
can = canvas.default_canvas()
x, y = (100, 500)

def show_text(str):
    global x, y
    can.show(x, y, str)
    can.show(x + 200, y, "/12/C" + font.quotemeta(str))
    y -= 20

show_text("/12/hLLeft align")
show_text("/12/hRRight align")
show_text("/12/hCCenter align")
show_text("/a20/12/hRAngled text")

def show_textv(str):
    global x, y
    can.show(x, y, str)
    x += 150

y -= 40
x = 100
show_textv("/12/vT//12//vTTop align")
show_textv("/12/vM//12//vT/12Middle align")
show_textv("/12/vB//12//vT/12Bottom align")

y -= 40
x = 100
show_text("/16/HHelvetica")
show_text("/12/CCourier")
show_text("/12/NHelvetica-Narrow")
show_text("/12/PPalatino-Roman")
show_text("/12/AAvantgarde")
show_text("/12/T/iTimes-Italic")
show_text("/12/F{ZapfDingbats}ZapfDingbats")

PyChart-1.39/doc/pychart/annotations.png0000644000175000017500000001207210352146636021746 0ustar santiagosantiago00000000000000PNG  IHDRAQg PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"IDATx흉* EAl@r69oR @YwwXWq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIq&%MJ7)1nRbܤĸIqm܂;qߝKŸbwgR13pT \*}w.;qߝKŸT&79#W1nt0KqC}B>7:P̺gؚߣ{p{Yp$%'ӇA*Z} ak+jYuCN2"ڸ8fp@0+pcF}˶rV NYn6t aZ.4G`ia&Fj`݃ng86%C&kɘ<|E?-n:XuD;Ejt90j|q_oEn$ZAYčө*Oqn~UnҺ5V_)U4!w\u>q_mٲnWö[Qj$- ,'t341!az*Dp}?OO6~w'5α8^QMA1kuwwT;ݺVq?s n7ڦRjgvo5'Lg`Wmcϼ=*oYVG}Y1nQ2nuo6a5062KFՆ`8% ZЯN^2 [huy٘'xp=yܨZv]wbӌX@D9@"-?h;w+滵ũU/ƌ+т:|gOvm3욶mfV,:b#*u w7%[ ҹQaѺ+Űs;SaǀZ5iV?.^RxSc+mӧ=֞sRL!;3tKKJZ';=s?M>3cZc)O񌰿 uds/ZUn3hY.ιUwkՒ ĭr<;v]+qOlܔ+vOm1ºa76OCXM3qJ %@ilV;NZpǿ7>'rW|}79z}QVu~뙯l߫FbT{(]Nq'wkՆ=n\mzmɯ\ ֪7Kq7KsxW m;ߌ| 3s`ਥ/m\Wq^=EߺuZ^uwN뻸gð7 ]&YlY5Yx2}_3֗qƇHzֽ0 ,ֱ3enemQ4 Q9S r6xۙ P|?[7vwQ`*OdBZ[Jl 㮁"M&$X8][7QDJV$Z/)."qp_кkϵi4N%Ewwl-x5nˈ:0Q 2f_gҢњP5zR 4_Di ÒfRj? ,;k D3Py^ u~VIniPv́P~6u`Mkl^8~2UWMu?{( 룖ƹvZpW[qwk8 4O-wx'Ssj#*?\ 17ftOefsӐt3ߊv{^}tUOw9 ȵlF<('3f"aČwƽgb<]t}Zy1tވxH>dWbCѺ#tN&ᩥxfAö*~p>q߸ZĽvM\ӷ7-+Qe7qXO~y=:';dE)4|j"'x S Q?^|ͤu1eV`v3Y;=ߍ-{) K|F8t/W.Հp\{q$KYpV0= $&Bzb/w7ݚqn|m=vW9*v# 360qjnp!;qUpƨu'n^w"rpKgAHg>ދ;|ܧ>5[6v_5"5O_~ߗqZܽg*M3۸lHgwQWUvZ5;^{rmh~۵rxjZ5zk^-%nУqd~z n#h_-{FֽU/1^f>NmzPFihVڸqsp{wOp!X7w!XP0b&5zZ f^HZ-iy+boWb&ᚷ{ȩk ׫ya/t@@ݮZsu#"J+?X[6Swv=0`CM9RӃx8:ֱFpɘmz0rDgY޸ 3'h@BAwƸMf(O(Gn =ٺ jѺy(=غH=غ?#;OJ1nR~CIENDB`PyChart-1.39/doc/pychart/module-color.html0000644000175000017500000001234110352146644022170 0ustar santiagosantiago00000000000000 15 Colors

15 Colors

class color.T
This class determines the color.

This class supports the following attributes:

b
Type: number Default: 0.0.

The intensity of blue. The value is between 0 and 1.

g
Type: number Default: 0.0.

The intensity of green. The value is between 0 and 1.

r
Type: number Default: 0.0.

The intensity of red. The value is between 0 and 1.

For example, color.T(r=1, g=1, b=1) will produce white. The color of color.T(r=1, g=0, b=1) will produce purple. You can use all the colors defined in X rgb.txt (usually at /usr/X11R6/lib/X11/rgb.txt). The below shows some of the standard colors defined in the module. They are refereed to by the names color.name (e.g., color.gray1).

Image colors

PyChart-1.39/doc/pychart/module-coord.html0000644000175000017500000002641010352146644022162 0ustar santiagosantiago00000000000000 6.1 Specifying the coordinate system


6.1 Specifying the coordinate system

Attributes x_coord and y_coord specify the coordinate systems for the area's X and Y axes. The values of these attributes must of type coord.T. PyChart provides three popular subclasses of coord. Both x_coord and y_coord defaults to linear_coord.T().

class linear_coord.T
This class creates a linear coordinate system.

ar = area.T(x_coord = linear_coord.T(), y_coord = linear_coord.T(), ...)

class log_coord.T
This class displays a logarithmic coordinate system.

class category_coord.T( data, col)
This class defines a ``categorical'' coordinate system, in which the axis only takes discrete values. This class takes two constructors: data ( see Section 5) and column col from which the axis values are extracted from the data. See the following example: ../demos/categbar.py

from pychart import *
theme.get_options()
data = [["Jan", 10], ["Feb", 22], ["Mar", 30]]

ar = area.T(x_coord = category_coord.T(data, 0), y_range = (0, None),
            x_axis = axis.X(label="Month"),
            y_axis = axis.Y(label="Value"))
ar.add_plot(bar_plot.T(data = data, label = "Something"))
ar.draw()

The output will look like the below:

Image categbar

All the classes described so far are derived from the coord.T class:

class coord.T( )
This is an abstract base class that defines methods for calculating the mapping between sample values and coordinates. Every coord.T object must implement the following three methods:

get_data_range( dmin, dmax, interval)
This method should compute the minimum and maximum values that are to be displayed on the canvas. dmin, dmax are the minimum and maximum values found in the sample data given to the plots. interval is the value of the area's x_grid_interval (or y_grid_interval) attribute ( see Section 6), or None if the attribute is omitted by the user. This method should return tuple (MIN, MAX, INTERVAL), where MIN, MAX are the minimum and maximum values to be displayed, and INTERVAL is the interval with which label and tick lines are drawn.

get_canvas_pos( size, val, range)
This method converts a data value (val) to canvas location. Parameter size is the size of the axis, either X or Y, and range is the minimum and maximum sample values obtained by calling self.get_data_range.

get_tics( range, interval)
This method should return the list of values (not canvas locations) at which labels and ``tick'' lines are drawn. Parameters range and interval are the values returned by get_data_range.

You can create fancier coordinate systems by subtyping coord.T. The below example shows how you can create a chart with ``zap'' marks.

Image zaptest

../demos/zaptest.py

from pychart import *

class zap_y_coord(linear_coord.T):
    # Method get_data_range is inherited from linear_coord.T.
    def get_canvas_pos(self, size, val, min, max):
        # Zap Y values between 70 and 240.
        # Thus, Y axis will display 0..70 and 240..280, 110 points total.
        if val <= 70:
            return linear_coord.T.get_canvas_pos(self, size, val, 0, 110)
        elif val <= 240:
            return linear_coord.T.get_canvas_pos(self, size, 70, 0, 110)
        else:
            return linear_coord.T.get_canvas_pos(self, size, val - 170, 0, 110)
    def get_tics(self, min, max, interval):
        # Don't draw tick marks between 65 and 245.
        tics = linear_coord.T.get_tics(self, min, max, interval)
        return [x for x in tics if x < 65 or x > 256]

can = canvas.default_canvas()
theme.get_options()
data = [(10, 20, 30, 5), (20, 265, 33, 5),
        (30, 255, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3)]

chart_object.set_defaults(area.T, size = (150, 120), y_range = (0, 280),
                          y_coord = zap_y_coord(),
                          x_coord = category_coord.T(data, 0))
chart_object.set_defaults(bar_plot.T, data = data)

bar_plot.fill_styles.reset();
plot1=bar_plot.T(label="foo", cluster=(0,3))
plot2=bar_plot.T(label="bar", hcol=2, cluster=(1,3))
plot3=bar_plot.T(label="baz", hcol=3, cluster=(2,3))

ar = area.T(loc=(250,0),
            x_axis=axis.X(label="X label", format="/a-30{}%d"),
            y_axis=axis.Y(label="Y label", tic_interval=10))
ar.add_plot(plot1, plot2, plot3)
ar.draw()
for x in (ar.x_pos(10) - 20, ar.x_pos(20)- 10, ar.x_pos(30) - 10):
    zap.zap_horizontally(can, line_style.default, fill_style.white,
                         x, ar.y_pos(65), x+16, ar.y_pos(65) + 4, 4, 4)

PyChart-1.39/doc/pychart/module-arrow.html0000644000175000017500000001475110352146644022213 0ustar santiagosantiago00000000000000 19 Arrows

19 Arrows

class arrow.T
Arrow is an optional component of a chart that draws line segments with an arrowhead. To draw an arrow, one creates an arrow.T object, and calls its "draw" method usually after area.draw() is called (otherwise, area.draw() may overwrite the arrow). For example, the below code draws an arrow from (10,10) to (20,30).

ar = area.T(...)
a = arrow.T(head_style = 1)
ar.draw()
a.draw([(10,10), (20,30)])

This class supports the following attributes:

head_color
Type: color.T ( see Section 15) Default: color.black.

The color of the arrow head.

head_len
Type: length in points ( See Section 4) Default: 8.

The length of the arrow head.

head_style
Type: int Default: 1.

The value of 0 draws a triangular arrow head. The value of 1 draws a swallow-tail arrow head. The value of 2 draws a circular head. The value of 3 draws a diamond-shaped head.

line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

Line style.

thickness
Type: length in points ( See Section 4) Default: 4.

The width of the arrow head.

An arrow object exports a single public method, draw.

draw( points)
Parameter points specifies the list of points the arrow traverses through. It should contain at least two points, i.e., the tail and tip. Parameter can is an optional parameter that specifies the output. See Section 21

Image arrows

PyChart-1.39/doc/pychart/unit.html0000644000175000017500000001162510352146646020554 0ustar santiagosantiago00000000000000 4 Unit of length and the coordinate System


4 Unit of length and the coordinate System

In PyChart, the X axis grows to the right, and the Y axis grows up (the same as PostScript, but different from X and Windows).

The length is measured in ``PostScript points'', which coincides with TeX points. Usually, one point is equal to 1/72 inch. Several variables and functions are provided to manipulate lengths.

Chart magnification can be changed by setting variable theme.scale_factor. One can convert a sample data value to a canval coordinate by calling two methods, x_pos and y_pos in area.T object.

See Also:

See Section 13.1 for the theme module.

See Section 6 for the area mobule.

PyChart-1.39/doc/pychart/bartestv.png0000644000175000017500000001022510352146635021240 0ustar santiagosantiago00000000000000PNG  IHDR@"rPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx txl|-51 B9;'M"oV!oEEEEEE 5a866 sVVg!]̡}c-D ·܄ϧa {hnjOD >pG~jHY76 ?>i`_ J ßD-зs<Q_nڙZ `xo'i2S;&~] ʂX 1%cw<@K lJZ͛|Kw^d]]ZX;@wSg~v۬*̆"F~Z^eOwqZ&$@M}W aS(7nDܵ;76o|F{Ui}vl] 6j] [t4qJ%>7@.shcuX}vY>7@!uX}vl}oŲFa>7@dVӰ YVfX]^gJD:wT"s:"@@"@#(LD͏b2Α̝n |)/a(P+w X8Y)^+w i% KʝFnٟ]mx)@Q0֊}wXVeZ`Z`yllV#H |Dda> kV#>p1xnV#|ॼ}d)`< ^L|>q^9m"["<̣Z?i>7@Sֿh~ak]B/~D_moU‰X`Mv߱D`}>  p?a.shcuuXk k'ZQZy`Zַ[9gWu"7|Tx :U>u"GD;j0V*2FOl}v#b,PI38{~Ӑ>(<~m'V旴וҝX",\h-*[H.l 名偝v% m "fW"\+w=ңNF"突qƯ/-rS+'cۏ2v!Zħ?GExy#!ahhF2>ŔLJX0<$ CZ?8mX]ViC0}ED_XKq\قowrk9'l|V>"2%0[ XH^ @TUa>C`뛮/Lz-XOst}fswW | >ioBk*u2ʆ ?X;JX`gsw,ױ<0`*FYo:Y n݉:̜ Ь݄"rw.":><Z,4H(R+'S#[+>YF: ڊT[\VPnΑy`{ ˊ28?/p%"-Pz`@?TEןC|l{a_V [q\8cH{hEj>ВIm|xqf(9>UVe[OnP WBi |'⹻%)u^G\{o@oyH:<#-R4eb0H.moqX>i}6%,I&`&."-v>{DSGD62qta|s73ޙ|g}|I89nCz΄"mLҩ_آ.; yV/-p~vH )| -P 2GH^' >0_d@7V$n ~;PW'=,:Gzz"5EJī;4KuZ_-*ɍDZ`(\}ٜiGp~v[满@, @XyZG$.qy`}>#mT0Mc&O}. y[Mf0﯎8Nj]Qx#}2Œ}#+`&H!H0kS֕{y>HnV)Z(#]R ·T\h>;@d ͑GHKsDau> : k Q_ Q_ Q_ Q_ Q_ Q EEEE0WuzZV. ̎2 oKD?ި_Qfk2Xv_TLq?f*kͥY bj& lW^_zV߬#!Q5y`9}+~լda7 n=]omIobN]t]`*C Xx;20-nM·f2G R. XMW[xXLnl ؛ ̎_e\@</0[X z]A"@~BFE5y-~]~oZ]@Nkt'JH. 2DUw(>/`+\^tQ`vOo;U KQ5(@(@(@(@(@(@(@(@(@(@(@(@(@(@(@T p\Qxa#s*IR50G, R +qcQY:q 9.lGYe![?;/kXą-ܸvӱ*.l1VsHE' O鬆nNװH 0G kX$7*%nnnjY\QV-H(܇K.QQY{k’U-`sq=sIENDB`PyChart-1.39/doc/pychart/index.html0000644000175000017500000001410510352146644020676 0ustar santiagosantiago00000000000000 PyChart

PyChart

Yasushi Saito

Email:

July 2, 2005



PyChart-1.39/doc/pychart/module-canvas.html0000644000175000017500000001326610352146644022334 0ustar santiagosantiago00000000000000 21 canvas - Controlling output and format

21 canvas - Controlling output and format

class canvas.T
Canvas is an object that corresponds to a single output file. It provides a set of methods for drawing lines, polygons, texts, and other things in a manner independent of the file's format. Canvas is usually hidden from the user, as PyChart creates a default canvas when it starts up and implicitly writes all charts on the default canvas (unless the user specifies otherwise; more on that later). There are some occasions, however, in which you might want to manipulate a canvas explicitly, e.g., when you want to create multiple plots from a single file, or you just want to add lines and texts directly.

Class canvas.T is an abstract base class. PyChart provides several subclasses that correspond to specific file formats. For example, pscanvas.T implements methods for PostScript output. Class pdfcanvas.T implements methods for PDF output. format



PyChart-1.39/doc/pychart/module-interval-bar-plot.html0000644000175000017500000003072310352146645024421 0ustar santiagosantiago00000000000000 8 Interval bar plots


8 Interval bar plots

class interval_bar_plot.T
An interval bar plot is a special kind of bar plot that draws an alternating sequence of bars. Image intvlbartestv

Sample interval bar chart

Below is the source code that produces the above chart. ../demos/intvlbartestv.py

from pychart import *
theme.get_options()

data = [("Foo", (10, 7, 10, 5, 5, 12, 13, 5, 10, 3),
         (7,10,8,16,9,3)),
        ("Bar", (5, 10, 12, 10, 9, 3),
         (10,10,13,6,9,13),)]

ar = area.T(y_coord = category_coord.T(data, 0),
            x_grid_style=line_style.gray50_dash1,
            x_grid_interval=20, x_range = (0,100),
            x_axis=axis.X(label="X label"),
            y_axis=axis.Y(label="Y label"),
            legend = legend.T(loc=(80, 40)))

chart_object.set_defaults(interval_bar_plot.T, direction="horizontal",
                          width=3, cluster_sep = 5, data=data)
ar.add_plot(interval_bar_plot.T(line_styles = [line_style.default, None],
                                fill_styles = [fill_style.red, None],
                                label="foo", cluster=(0,2)),
            interval_bar_plot.T(line_styles = [line_style.default, None],
                                fill_styles = [fill_style.blue, None],
                                label="bar", hcol=2, cluster=(1,2)))

can = canvas.default_canvas()
can.set_title("Interval bar test")
can.set_author("John Doe")
ar.draw()

The list the attributes understood by an interval_bar_plot.T object:

bcol
Type: int Default: 0.

Specifies the column from which base values (i.e., X values when attribute "direction" is "vertical", Y values otherwise) are extracted. The combination of "data", "bcol", and "hcol" attributes defines the set of boxes drawn by this chart. See also the descriptions of the 'bcol' and 'data' attributes.

cluster
Type: tuple Default: (0, 1).

This attribute is used to cluster multiple bar plots side by side in a single chart. The value should be a tuple of two integers. The second value should be equal to the total number of bar plots in the chart. The first value should be the relative position of this chart; 0 places this chart the leftmost, and N-1 (where N is the 2nd value of this attribute) places this chart the rightmost. Consider the below example:

    a = area.T(...)
    p1 = interval_bar_plot.T(data = [[1, [20,10]][2,[30,5]]], cluster=(0,2))
    p2 = interval_bar_plot.T(data = [[1,[25,11,2]],[2,[10,5,3]]], cluster=(1,2))
    a.add_plot(p1, p2)
    a.draw()

In this example, one group of bars will be drawn side-by-side at position x=1. Other two bars will be drawn side by side at position x=2. See also the description of attribute "cluster" for bar_plot.T.

cluster_sep
Type: length in points ( See Section 4) Default: 0.

The separation between clustered boxes. The unit is points.

data
Type: any Default: None.

Specifes data points. Unlike other types of charts, the "hcol"th column of the data must be a sequence of numbers, not just a single number. See also the description of "hcol".

data_label_format
Type: printf format string Default: None.

The format string for the label displayed besides each bar. It can be a `printf' style format string, or a two-parameter function that takes (x,y) values and returns a string. The appearance of the string produced here can be controlled using escape sequences. See Section 17

data_label_offset
Type: (x,y) or None Default: (0, 5).

The location of data labels relative to the sample point. See also attribute data_label_format.

direction
Type: str Default: "vertical".

The direction the growth of the bars. The value is either 'horizontal' or 'vertical'.

fill_styles
Type: list Default: ['function <lambda at 0x403cd534>', 'None'].

List of fill styles for bars. The style of each bar is chosen in a round-robin fashion, if the number of elements in "line_styles" is smaller than actual number of boxes. If this attribute is omitted, a style is picked from standard styles round-robin. See Section 16.

hcol
Type: int Default: 1.

The column from which the base and height of bars are extracted. See the below example:

              d = [[5,[10,15,22]], [7,[22,23,5,10]], [8,[25,3]]]
              p = interval_bar_plot.T(data = d, bcol = 0, hcol = 1)

Here, three sequence of bars will be drawn. The X locations of the bars will be 5, 7, and 8. For example, at location X=7, three bars are drawn, one corresponding to Y values of 22 to 45 (=22+23), and the second one for values 45 to 50, and the third one for values 50 to 60. The line and fill styles of the bars are picked in a round-robin fashion from attributes "line_styles" and "fill_styles".

label
Type: str Default: "???".

The label to be displayed in the legend. See Section 6.3, See Section 17

line_styles
Type: list Default: ['line_style.black', 'None'].

The list of line styles for bars. The style of each bar is chosen in a round-robin fashion, if the number of elements in "line_styles" is smaller than actual number of boxes.

stack_on
Type: any Default: None.

The value must be either None or bar_plot.T. If not None, bars of this plot are stacked on top of another bar plot.

width
Type: length in points ( See Section 4) Default: 5.

Width of each box. The unit is in points.

PyChart-1.39/doc/pychart/about.html0000644000175000017500000001043610352146643020703 0ustar santiagosantiago00000000000000 About this document ...

About this document ...

PyChart, July 2, 2005

This document was generated using the LaTeX2HTML translator.

LaTeX2HTML is Copyright © 1993, 1994, 1995, 1996, 1997, Nikos Drakos, Computer Based Learning Unit, University of Leeds, and Copyright © 1997, 1998, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The application of LaTeX2HTML to the Python documentation has been heavily tailored by Fred L. Drake, Jr. Original navigation icons were contributed by Christopher Petrilli.

PyChart-1.39/doc/pychart/previous.png0000644000175000017500000000077710352146643021274 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YPFy =p3f?0bKGD{lIDATxՒA DiIZe/8vv$/ H5=S`'R3jBjy 6.3 Legends

6.3 Legends

class legend.T
A legend is a subcomponent of area that draws a rectangular box with the description of each plots.

This class supports the following attributes:

bottom_fudge
Type: length in points ( See Section 4) Default: 3.

Amount of space below the last line.

frame_fill_style
Type: fill_style.T ( see Section 16) Default: fill_style.white.

frame_line_style
Type: line_style.T ( see Section 14) Default: line_style.black.

inter_col_sep
Type: length in points ( See Section 4) Default: 0.

Space between each column in the legend.

inter_row_sep
Type: length in points ( See Section 4) Default: 0.

Space between each row in the legend.

left_fudge
Type: length in points ( See Section 4) Default: 5.

Amount of space left of the legend.

loc
Type: (x,y) or None Default: None.

Bottom-left corner of the legend. The default location of a legend is the bottom-right end of the chart.

nr_rows
Type: int Default: 9999.

Number of rows in the legend. If the number of plots in a chart is larger than nr_rows, multiple columns are created in the legend.

right_fudge
Type: length in points ( See Section 4) Default: 5.

Amount of space right of the legend.

shadow
Type: (xoff,yoff,fill) Default: None.

The value is either None or a tuple. When non-None, a drop-shadow is drawn beneath the object. X-off, and y-off specifies the offset of the shadow relative to the object, and fill specifies the style of the shadow ( see Section 16).

top_fudge
Type: length in points (See Section 4) Default: 0.

Amount of space above the first line.

PyChart-1.39/doc/pychart/unicodetest.png0000644000175000017500000000374610352146636021747 0ustar santiagosantiago00000000000000PNG  IHDR^$ PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"cIDATxz Eo ppGL6:{H4*i]44 Cx9tAx9tAx9tAx9tAx9tAx9tAx9tAx9tAx9t`͗v_̹]ο|3m*ƺ}QH΍QievxǒN;o39"&DiZ93yߺ a*o"϶Kݕ=b[N^|z] ΃1a+Z(nkKS\M3e}:;8=̗Du'p͹Ѯ>Xb+`ki#o~aPVw۽wZ|wA.AGFs)"{ytիk.iHr o8owcΝ:re6,7vִ%gwBwFWyͿB7KgQ[slQT]WZgAdBm(@W}o]>Ax9tAx9tAx9tAx9tAx9tAx9tA )[ۇ/D8~Nlt>ǝfɕcs~9RB"T(IrT|001<\O'LmQ6t۸TO~[G|9i9^ ,B*ؙOzp% %w 1 Introduction


1 Introduction

This document describes PyChart Version 1.34, a Python library designed for drawing professional-quality charts. It produces line plots, bar plots, range-fill plots, pie charts, and wind-rose charts in PostScript, PDF, PNG, or SVG. PyChart is distributed under the General Public License (GPL).

http://www.gnu.org/copyleft/gpl.html
Follow this link for more information about GPL.

The following examples illustrate uses of PyChart.



PyChart-1.39/doc/pychart/pietest.png0000644000175000017500000001011710352146636021064 0ustar santiagosantiago00000000000000PNG  IHDR>PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATxmz }g;YOvCbtD4j \9}:5^5oB_@ a0@a0 P(  a0@a0 P(  a0@a0 P(  2ī2!ڋ@~Pj/a0}0}}TEUK o>bzBQ\2T eW/T azByaa23 8bB+Dxj0t0 P(  a0@a0L(v(  4ҭ P8(  a0k a0@a0L(c0@a0L(+ѳ PMB_BRE|s](rS{ҭJYQߟؤdAx΢g(f)b1cNϖ\)rx|-6)rs/ӷI) IJ.%PHQeɏQzuɎ[&(]F'E2%/ӕbdyg*YQLP *lR%'JI E4%'@(U򡄒<7Tr6](gɬvs&dL$K)yPLRQN?<%ʄ&*,(q&(pPi2IWi%CID9\/ (v6IFy[ %y2n_4547[$r;hI ZTN`2EW{Pk,efHQJƛ$$e xj%˞O?";bI2 C6` *ճY94_sa4()&("K%^e_=ZcsreALDMPPM W5='W^)M2Eh>eXyw#fB2Ii֭Z3ep->UPgԀ 9N?=5\'ġt( Xԡ6`Bje:/:H JIJ  %PQwu(M4`d(&(¾TP %k"{*T(&([Í  I JS\PwΦJt/W#~"4Kxz{߰qۋu)[|]ܣ+cZWf>{%_Y(wX,g8{LQ,bh|ίŬS4O9PL XmJh/d75=n>P&ݽ8m[ÙI] V~p y~q&P~UJI[^2P*>^LrQE|(W?P( W P.YUJ7|6M( #MHk<~oPZ5Ɍ26+dG10M访ND&P&%8(ɶLmA)P'^a*ll钩R)mzcэI>EPWNҼI% Z([tuULPf O,*b!MHjȑ}8\DYX)}8U釤2Y)K\$=TFYYSI}퀋o_|o$P{+d@.U`NK]u+2AYXއek$lPkk"JN(Z96[!Db Ś3 42q4 P(mˌ/O(Sc(B U(!i%e P&*6<1)OS*Jy-٧ U( aKf(Tq}J?P(2T"{3GS*/!-^rlOix x(Tͧaf*u(  v3(UBьBʰGyr9z}tGT:Bށ"sZ̠wC(X FxP(`2)˗#O0.2P(`G ʵ'O E5dړʌ;#a+(מt&n]3eI'->uE>{'պ>$y,1tbh%O?(מt(/n>\zR힥K@7^P4=v B PGr>PrFP0J9\r})P@!O9TRƧO_ 8s)PY)@!c⽿(_ X@! <2 v3 P( AG0T P( cEُ7.(TmZ؛xB|BGo^>rPbS@)+x#PƁk6Pō|m>@sh6P;$(  aU2@a@"IENDB`PyChart-1.39/doc/pychart/module-chart-object.html0000644000175000017500000001277610352146644023433 0ustar santiagosantiago00000000000000 3 Attributes


3 Attributes

The look of a component of a chart ( see Section 2) is defined by a collection of attributes. For example, an X or Y axis includes an integer tic_len attribute that defines the length of "tick" lines drawn perpendicular to the axis (see Section 6.2). It also has an integer tic_interval attribute that defines the separation between tick lines. See Section 6.2 for the full list of Axis's attributes.

Attributes are usually specified by named arguments during component creation:

ax = axis.X(tic_len = 3, tic_interval = 50)

Attributes can also be changed after a component is created, but before area.T.draw(), the main drawing procedure ( see Section 6), is called. The below example has the same effect as the above.

ax = axis.X()
ax.tic_len = 3
ax.tic_interval = 50

Each attribute has a default value that supposedly gives you a standard look to the chart. You can change the default values through chart_object module. For example, the below example has the same effect as the above, except that all X axes created in the future will have the new default values.

chart_object.set_defaults(axis.X, tic_len=3, tic_interval=50)
ax = axis.X()

PyChart-1.39/doc/pychart/pyfav.png0000644000175000017500000000036010352146643020531 0ustar santiagosantiago00000000000000PNG  IHDR&:GPLTEtRNS@fbKGDH pHYs  tIME -,O TIDAT% 0DIMJ!쿊\q{" 57'Z 13.3 Changing the default behavior via environment variable PYCHART_OPTIONS


13.3 Changing the default behavior via environment variable PYCHART_OPTIONS

The variables in the theme module can also be set via environment variable PYCHART_OPTIONS. The value of this variable, if set, should be a sequence of var=val, separated by space. For instance, the below example tells PyChart to write to file foo.pdf and use Times-Roman as the default font.

% PYCHART_OPTIONS="output=foo.pdf font-family=Times"
% export PYCHART_OPTIONS

The summary of attributes that can be set via PYCHART_OPTIONS follows.

font-family=name:
family Same as setting theme.default_font_family variable.

font-size=size:
size Same as setting theme.default_font_size variable.

line-width=points:
Same as setting theme.default_line_width variable.

scale=n:
Same as setting theme.scale_factor variable.

color=[yes|no]:
Same as setting theme.use_color variable.

debug-level=N:
Same as setting theme.debug_level variable.

bbox=LEFT,BOTTOM,RIGHT,TOP:
This option sets theme.bounding_box and/or theme.delta_bounding_box. The value of this option is a sequence of four values, separated by commas. Each value is of the form, +num, -num, or num. +num and -num adds to or subtracts from the bounding-box value computed by PyChart (the unit is PostScript points; See Section 4.) num sets the bounding box at that value. For example,

bbox=-10,0,+10,100

Extends the bounding box 10 points to both left and right, and sets the vertical stretch from 0 to 100.

PyChart-1.39/doc/pychart/index.png0000644000175000017500000000102110352146643020506 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YPFy =p3f?0bKGD{lIDATxڵ ТE9, nP 0+=2OPK184΀1 +19Ib6L5=t9+ :0"2M , HKO.9 D/Dʀ Џ7 }@s ?@*gEH䐼LzTXtSoftwarexsPMLOMLLV033R7070TH.,.tȭ,.LK-K)-+KK^3zTXtSignaturex35N3O2N5M5705L4512NH3KL3L1JIL5!XzTXtPagex360666 GwIENDB`PyChart-1.39/doc/pychart/anatomy.html0000644000175000017500000001504710352146643021244 0ustar santiagosantiago00000000000000 2 Anatomy of a chart


2 Anatomy of a chart

A chart comprises a set of components. Each component belongs to a certain class, from which an instance tailored for a particular chart is generated. The below picture shows example of a chart and its components.

Image failureannot

The standard set of component classes follow:

area.T:

This class defines the size, the location, and the coordinate system (linear, logarithmic, etc) of a chart ( see Section 6). It also contains axes, plots, and legends, as described below. At least one Area must be created in any chart.

axis.X:
axis.Y:
The axis class defines the look of an axis. You can specify, for example, the interval and the style of tick marks and grid lines ( see Section 6.2). PyChart provides two types of axes, axis.X and axis.Y, corresponding to horizontal and vertical axes.

bar_plot.T:
line_plot.T:
pie_plot.T:
range_plot.T:
interval_plot.T:
rose_plot.T:
These classes actually plot a chart. You can draw multiple plots in a single chart, and most of the times you can even mix different types of plots, e.g., line plots and bar plots.

legend.T:
The class draws an optional rectangular box that describes what each plot means ( see Section 6.3).

text_box.T:
This class draws an optional rectangular box that contains arbitrary text. It can also contain arrows ( see Section 18).

canvas.T:
The canvas is a "virtual paper" that defines graph-drawing primitives, such as lines, rectangles, and texts. One canvas corresponds to one output file. Canvas is used by other components in the graph and is usually not manipulated by users directly. It's handy, however, if you want to draw a line/circle/text/etc, directly on the PostScript or PDF file. See Section 21.

PyChart-1.39/doc/pychart/module-chart-data.html0000644000175000017500000003620210352146644023064 0ustar santiagosantiago00000000000000 5 Reading CSV files and transforming data


5 Reading CSV files and transforming data

The basic function of PyChart is to plot sample data in a variety of ways. Sample data are simply a sequence of sequences, where the term "sequence" is a Python jargon for either a tuple (comma-separated numbers or strings enclosed in parenthesis, e.g., (5, 10, 15)) or a list (comma-separated numbers or strings enclosed in square brackets, e.g., [5, 10, 15]). Data are given to plots through the "data" attribute of a plot object:

l = line_plot.T(data=[(10,20), (11,38), (12,29)], xcol=0, ycol=1)

In the above example, three sample points will be drawn along with line segments that connect them: (10, 20) - (11, 38) - (12, 29). Attribute xcol tells the locations of X values within data (the first column of each sample in data), and ycol similarly tell the locations of Y values (the last column of each sample in data). A sample point can contain None, in which case it is ignored.

data = [(10, 20, 21), (11, 38, 22), (13, None, 15), (12, 29, 30)]
l1 = line_plot.T(data=data, xcol=0, ycol=1)
l2 = line_plot.T(data=data, xcol=0, ycol=2)

The above example is equivalent to:

l1 = line_plot.T(data=[(10, 20), (11, 38), (12, 29)], xcol=0, ycol=1)
l2 = line_plot.T(data=[(10, 21), (11, 22), (13, 15), (12, 30)], xcol=0, ycol=1)

Module chart_data provides several functions for generating, reading, or transforming samples.

read_csv( path, delim = ',')
This function reads comma-separated values from a file. Parameter path is either a pathname or a file-like object that supports the readline() method.

Empty lines and lines beginning with "#" are ignored. Parameter delim specifies how a line is separated into values. If it does not contain the letter "%", then delim marks the end of a value. Otherwise, this function acts like scanf in C:

chart_data.read_csv('file', '%d,%s:%d')
Paramter delim currently supports only three conversion format specifiers: "d"(int), "f"(double), and "s"(string).

read_str( delim, lines)
This function is similar to read_csv, but it reads data from the list of lines.

fd = open("foo", "r")
data = chart_data.read_str(",", fd.readlines())

write_csv( path, data)
This function writes comma-separated data to path. Parameter path is either a pathname or a file-like object that supports the write() method.

func( f, from, to, step)
Create sample points from function f, which must be a single-parameter function that returns a number (e.g., math.sin). Parameters xmin and xmax specify the first and last X values, and step specifies the sampling interval.

>>> chart_data.func(math.sin, 0, math.pi * 4, math.pi / 2)
[(0, 0.0), (1.5707963267948966, 1.0), (3.1415926535897931, 1.2246063538223773e-16), (4.7123889803846897, -1.0), (6.2831853071795862, -2.4492127076447545e-16), (7.8539816339744828, 1.0), (9.4247779607693793, 3.6738190614671318e-16), (10.995574287564276, -1.0)]

filter( f, data)
Parameter func must be a single-argument function that takes a sequence (i.e., a sample point) and returns a boolean. This procedure calls func on each element in data and returns a list comprising elements for which func returns True.

>>> data = [[1,5], [2,10], [3,13], [4,16]]
... chart_data.filter(lambda x: x[1] % 2 == 0, data)
[[2,10], [4,16]].

extract_rows( data, rows...)
Extract rows specified in the argument list.

>>> chart_data.extract_rows([[10,20], [30,40], [50,60]], 1, 2)
[[30,40],[50,60]]

extract_columns( data, cols...)
Extract columns specified in the argument list.

>>> chart_data.extract_columns([[10,20], [30,40], [50,60]], 0)
[[10],[30],[50]]

moving_average( data, xcol, ycol, width)
Compute the moving average of YCOL'th column of each sample point in DATA. In particular, for each element I in DATA, this function extracts up to WIDTH*2+1 elements, consisting of I itself, WIDTH elements before I, and WIDTH elements after I. It then computes the mean of the YCOL'th column of these elements, and it composes a two-element sample consisting of XCOL'th element and the mean.

>>> data = [[10,20], [20,30], [30,50], [40,70], [50,5]]
... chart_data.moving_average(data, 0, 1, 1)
[(10, 25.0), (20, 33.333333333333336), (30, 50.0), (40, 41.666666666666664), (50, 37.5)]
The above value actually represents:

[(10, (20+30)/2), (20, (20+30+50)/3), (30, (30+50+70)/3), 
  (40, (50+70+5)/3), (50, (70+5)/2)]

median( data, freq_col=1)
Compute the median of the freq_col'th column of the values is data.

>>> chart_data.median([(10,20), (20,4), (30,5)], 0)
20
>>> chart_data.median([(10,20), (20,4), (30,5)], 1)
5.

mean_samples( data, xcol, ycollist)
Create a sample list that contains the mean of the original list.

>>> chart_data.mean_samples([ [1, 10, 15], [2, 5, 10], [3, 8, 33] ], 0, (1, 2))
[(1, 12.5), (2, 7.5), (3, 20.5)]

stddev_samples( data, xcol, ycollist, delta)
Create a sample list that contains the mean and standard deviation of the original list. Each element in the returned list contains following values: [MEAN, STDDEV, MEAN - STDDEV*delta, MEAN + STDDEV*delta].

>>> chart_data.stddev_samples([ [1, 10, 15, 12, 15], [2, 5, 10, 5, 10], [3, 32, 33, 35, 36], [4,16,66, 67, 68] ], 0, range(1,5))
[(1, 13.0, 2.1213203435596424, 10.878679656440358, 15.121320343559642), (2, 7.5, 2.5, 5.0, 10.0), (3, 34.0, 1.5811388300841898, 32.418861169915807, 35.581138830084193), (4, 54.25, 22.094965489902897, 32.155034510097103, 76.344965489902904)]

transform( func, data)
Apply func on each element in data and return the list consisting of the return values from func.

>>> data = [[10,20], [30,40], [50,60]]
... chart_data.transform(lambda x: [x[0], x[1]+1], data)
[[10, 21], [30, 41], [50, 61]]

One of the frequent uses of transform is to convert a date string to number and back to some other string for display. The next example does this: it takes the input for date in the format of "10/5/1983", and displays the graph in the format of "Oct 5, 1983".

../demos/date.py

import sys
import datetime
from pychart import *

def date_to_ordinal(s):
    month, day, year = map(int, s.split("/"))
    return datetime.date(year, month, day).toordinal()

def format_date(ordinal):
    d = datetime.date.fromordinal(int(ordinal))
    return "/a60{}" + d.strftime("%b %d, %y")

data = [["10/5/1983", 10], ["3/5/1984", 15],
        ["11/10/1984", 16], ["2/22/1985", 20]]
data = chart_data.transform(lambda x: [date_to_ordinal(x[0]), x[1]], data)

ar = area.T(x_coord = category_coord.T(data, 0),
            y_range = (0, None),
            x_axis = axis.X(label = "Date", format = format_date),
            y_axis = axis.Y(label = "Value"))
ar.add_plot(bar_plot.T(data = data))
ar.draw()

Image date

PyChart-1.39/doc/pychart/module-area.html0000644000175000017500000003620310352146644021765 0ustar santiagosantiago00000000000000 6 Area


6 Area

class area.T
Class area.T defines the location and size of a chart. It also defines the coordinate system (linear, log, or enumeration) of the X and Y axes.

The X (or Y) coordinate system is defined by attribute x_coord (or y_coord), which takes an object of type coord.T. Class coord.T defines how an X (or a Y) value is mapped to a display (canvas) location. PyChart provides three standard coordinate systems: linear_coord.T (for linear mapping; this is the default), log_coord.T (for logarithmic mapping), and category_coord.T (enumeration of values). Most charts will do ok by instantiating one of these pre-defined coordinate classes, but you can also define your own wacky coordinate system.

See Also:

See Section 6.1 for more about the coordinate system.

For log and linear coordinate systems, the minimum and maximum displayable values in the area are computed automatically from the plots unless they are defined explicitly via attribute x_range. In the next example, the X axis is drawn with a logarithmic scale. The minimum value will be 10, and the maximum value will be computed from the values given to plots.

ar = area.T(x_coord = log_coord.T(), x_range = (10, None), ...)

In the below example of a category coordinate system, the X axis will list three strings, ``apple'', ``orange'', and ``blueberry''.

samples = [("apple", 10), ("orange", 30), ("blueberry", 20)],
ar = area.T(x_coord = category_coord(samples, 0))
ar.add_plot(bar_plot.T(data = samples))

We now list the attributes understood by an area.T object.

bg_style
Type: fill_style.T ( see Section 16) Default: None.

Background fill-pattern.

border_line_style
Type: line_style.T ( see Section 14) Default: None.

Line style of the outer frame of the chart.

legend
Type: legend.T ( see Section 6.3) Default: a legend is by default displayed in the right-center of the chart. If you don't want to draw a legend, you should explicitly set None to this attribute..

The legend of the chart.

loc
Type: (x,y) or None Default: (0, 0).

The location of the bottom-left corner of the chart. None means to use the default value.

size
Type: (x,y) or None Default: (120, 110).

The size of the chart-drawing area, excluding axis labels, legends, tick marks, etc. None means to use the default value.

x_axis
Type: axis.X Default: None.

The X axis. See Section 6.2.

x_axis2
Type: axis.X Default: None.

The second X axis. This axis should be non-None either when you want to display plots with two distinct domains or when you just want to display two axes at the top and bottom of the chart. See Section 6.2

x_coord
Type: coord.T (see Section 6.1) Default: A linear coordinate system..

Set the X coordinate system.

x_grid_interval
Type: number or function Default: None.

The horizontal grid-line interval. A numeric value specifies the interval at which lines are drawn. If value is a function, it takes two arguments, (MIN, MAX), that tells the minimum and maximum values found in the sample data. The function should return a list of values at which lines are drawn.

x_grid_over_plot
Type: bool Default: False.

If True, grid lines are drawn over plots. Otherwise, plots are drawn over grid lines.

x_grid_style
Type: line_style.T ( see Section 14) Default: None.

The style of horizontal grid lines.

x_range
Type: (x,y) or None Default: None.

Specifies the range of X values that are displayed in the chart. IF the value is None, both the values are computed automatically from the samples. Otherwise, the value must be a tuple of format (MIN, MAX). MIN and MAX must be either None or a number. If None, the value is computed automatically from the samples. For example, if x_range = (None,5), then the minimum X value is computed automatically, but the maximum X value is fixed at 5.

y_axis
Type: axis.Y Default: None.

The Y axis. See Section 6.2.

y_axis2
Type: axis.Y Default: None.

The second Y axis. This axis should be non-None either when you want to display plots with two distinct ranges or when you just want to display two axes at the left and right of the chart. See Section 6.2

y_coord
Type: coord.T (see Section 6.1) Default: A linear coordinate system..

Set the Y coordinate system.

y_grid_interval
Type: number or function Default: None.

The vertical grid-line interval. See also x_grid_interval

y_grid_over_plot
Type: int Default: False.

See x_grid_over_plot.

y_grid_style
Type: line_style.T ( see Section 14) Default: line_style.gray70_dash3.

The style of vertical grid lines.

y_range
Type: (x,y) or None Default: None.

Specifies the range of Y values that are displayed in the chart. IF the value is None, both the values are computed automatically from the samples. Otherwise, the value must be a tuple of format (MIN, MAX). MIN and MAX must be either None or a number. If None, the value is computed automatically from the samples. For example, if y_range = (None,5), then the minimum Y value is computed automatically, but the maximum Y value is fixed at 5.

An object of area.T also provides several methods:

add_plot( plot, ...)
Add plots to the area. Each plot must be a plot object. See Section 9, Section 7, Section 11, Section 10.

draw( canvas = None)
Draw plots, axes, and the legend. This procedure must be called at the end of every PyChart application. Parameter canvas is an optional parameter that specifies the output. If omitted, the default canvas is used.

See Also:

Section 21 for more about canvas.

x_pos( xval)
Converts xval to a coordinate on the canvas ( see Section 21). See Section 4.

y_pos( yval)
Converts yval to a coordinate on the canvas ( see Section 21). See Section 4.

ar = area.T(loc=(50, 50), size=(100, 100),
            xrange=(0,200), yrange=(0, 1000))
px = ar.x_pos(50)
py = ar.y_pos(100)

In the above example, the chart is drawn in the area defined by rectangle (50, 50) - (150, 150). The point (px, py) will be at (75, 60), which is the screen location at which the point (50, 100) would be drawn (i.e., 50 + 100 * 50/200 = 75, 50 + 100 * 100 / 1000 = 60).



PyChart-1.39/doc/pychart/pychart.css0000644000175000017500000002306310352146643021067 0ustar santiagosantiago00000000000000/* * The first part of this is the standard CSS generated by LaTeX2HTML, * with the "empty" declarations removed. */ /* Century Schoolbook font is very similar to Computer Modern Math: cmmi */ .math { font-family: "Century Schoolbook", serif; } .math i { font-family: "Century Schoolbook", serif; font-weight: bold } .boldmath { font-family: "Century Schoolbook", serif; font-weight: bold } /* * Implement both fixed-size and relative sizes. * * I think these can be safely removed, as it doesn't appear that * LaTeX2HTML ever generates these, even though these are carried * over from the LaTeX2HTML stylesheet. */ small.xtiny { font-size : xx-small; } small.tiny { font-size : x-small; } small.scriptsize { font-size : smaller; } small.footnotesize { font-size : small; } big.xlarge { font-size : large; } big.xxlarge { font-size : x-large; } big.huge { font-size : larger; } big.xhuge { font-size : xx-large; } /* * Document-specific styles come next; * these are added for the Python documentation. * * Note that the size specifications for the H* elements are because * Netscape on Solaris otherwise doesn't get it right; they all end up * the normal text size. */ body { color: #000000; background-color: #ffffff; } a:link:active { color: #ff0000; } a:link:hover { background-color: #bbeeff; } a:visited:hover { background-color: #bbeeff; } a:visited { color: #551a8b; } a:link { color: #0000bb; } h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif; font-weight: bold; } h1 { font-size: 180%; } h2 { font-size: 150%; } h3, h4 { font-size: 120%; } /* These are section titles used in navigation links, so make sure we * match the section header font here, even it not the weight. */ .sectref { font-family: avantgarde, sans-serif; } /* And the label before the titles in navigation: */ .navlabel { font-size: 85%; } /* LaTeX2HTML insists on inserting
elements into headers which * are marked with \label. This little bit of CSS magic ensures that * these elements don't cause spurious whitespace to be added. */ h1>br, h2>br, h3>br, h4>br, h5>br, h6>br { display: none; } code, tt { font-family: "lucida typewriter", lucidatypewriter, monospace; } var { font-family: times, serif; font-style: italic; font-weight: normal; } .Unix { font-variant: small-caps; } .typelabel { font-family: lucida, sans-serif; } .navigation td { background-color: #99ccff; font-weight: bold; font-family: avantgarde, sans-serif; font-size: 110%; } div.warning { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.warning .label { font-family: sans-serif; font-size: 110%; margin-right: 0.5em; } div.note { background-color: #fffaf0; border: thin solid black; padding: 1em; margin-left: 2em; margin-right: 2em; } div.note .label { margin-right: 0.5em; font-family: sans-serif; } address { font-size: 80%; } .release-info { font-style: italic; font-size: 80%; } .titlegraphic { vertical-align: top; } .verbatim pre { color: #00008b; font-family: "lucida typewriter", lucidatypewriter, monospace; font-size: 90%; } .verbatim { margin-left: 2em; } .verbatim .footer { padding: 0.05in; font-size: 85%; background-color: #99ccff; margin-right: 0.5in; } .grammar { background-color: #99ccff; margin-right: 0.5in; padding: 0.05in; } .grammar-footer { padding: 0.05in; font-size: 85%; } .grammartoken { font-family: "lucida typewriter", lucidatypewriter, monospace; } .productions { background-color: #bbeeff; } .productions a:active { color: #ff0000; } .productions a:link:hover { background-color: #99ccff; } .productions a:visited:hover { background-color: #99ccff; } .productions a:visited { color: #551a8b; } .productions a:link { color: #0000bb; } .productions table { vertical-align: baseline; empty-cells: show; } .productions > table td, .productions > table th { padding: 2px; } .productions > table td:first-child, .productions > table td:last-child { font-family: "lucida typewriter", lucidatypewriter, monospace; } /* same as the second selector above, but expressed differently for Opera */ .productions > table td:first-child + td + td { font-family: "lucida typewriter", lucidatypewriter, monospace; vertical-align: baseline; } .productions > table td:first-child + td { padding-left: 1em; padding-right: 1em; } .productions > table tr { vertical-align: baseline; } .email { font-family: avantgarde, sans-serif; } .mailheader { font-family: avantgarde, sans-serif; } .mimetype { font-family: avantgarde, sans-serif; } .newsgroup { font-family: avantgarde, sans-serif; } .url { font-family: avantgarde, sans-serif; } .file { font-family: avantgarde, sans-serif; } .guilabel { font-family: avantgarde, sans-serif; } .realtable { border-collapse: collapse; border-color: black; border-style: solid; border-width: 0px 0px 2px 0px; empty-cells: show; margin-left: auto; margin-right: auto; padding-left: 0.4em; padding-right: 0.4em; } .realtable tbody { vertical-align: baseline; } .realtable tfoot { display: table-footer-group; } .realtable thead { background-color: #99ccff; border-width: 0px 0px 2px 1px; display: table-header-group; font-family: avantgarde, sans-serif; font-weight: bold; vertical-align: baseline; } .realtable thead :first-child { border-width: 0px 0px 2px 0px; } .realtable thead th { border-width: 0px 0px 2px 1px } .realtable td, .realtable th { border-color: black; border-style: solid; border-width: 0px 0px 1px 1px; padding-left: 0.4em; padding-right: 0.4em; } .realtable td:first-child, .realtable th:first-child { border-left-width: 0px; vertical-align: baseline; } .center { text-align: center; } .left { text-align: left; } .right { text-align: right; } .refcount-info { font-style: italic; } .refcount-info .value { font-weight: bold; color: #006600; } /* * Some decoration for the "See also:" blocks, in part inspired by some of * the styling on Lars Marius Garshol's XSA pages. * (The blue in the navigation bars is #99CCFF.) */ .seealso { background-color: #fffaf0; border: thin solid black; padding: 0pt 1em 4pt 1em; } .seealso > .heading { font-size: 110%; font-weight: bold; } /* * Class 'availability' is used for module availability statements at * the top of modules. */ .availability .platform { font-weight: bold; } /* * Additional styles for the distutils package. */ .du-command { font-family: monospace; } .du-option { font-family: avantgarde, sans-serif; } .du-filevar { font-family: avantgarde, sans-serif; font-style: italic; } .du-xxx:before { content: "** "; font-weight: bold; } .du-xxx:after { content: " **"; font-weight: bold; } /* * Some specialization for printed output. */ @media print { .online-navigation { display: none; } } PyChart-1.39/doc/pychart/linetest3.png0000644000175000017500000002302410352146635021321 0ustar santiagosantiago00000000000000PNG  IHDRWPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx *_sٍ8RXK߄DCT7 'N @8<py 'N @8<py 'N @8<py 'N @8<py 'N @8<py 'C434sj;DPLX!&(M<RZ"Ndȣ>OlS`y )߇dc_fm L(Q'w(R?3ch[ L(QvcMklMѷqm Ld.Ry '˃s D@˃ y}PX$ :1@ C^m+ ZA3KVqhU`HG\jHT5;!R-^^ۍv_ɜTǸq%h:%q"XWN յ#Q@*byy@ @8G`"y@'5T%y.y@'&0y:y@}61]paI _e٣d1eymӛﲤn}g +&N^VRM8']n Zzdm#UĔ4fii_"Ib!uy⓷=~v,7y F=^ E&gUM:ǢNV~{1Bd5<"yG"ǫ1BiТhqKJJe'|E)lDn*yb(Y&EG(M1TQC2}ZYnd .u!( gHɗ y#c Suؤ뾓g?))F+㻿=(kexp5]5_'g!uIPq]9vXV#c?!u)sØ.j^=6n#kA "ŽÐfdGi0X<)iqN =%c1fyWҊJ2fc#cA"o Kw\&(:Gih9%* zz\C+:Gi8zu m?=2p,0c%0{="GS#U/ѳvgc^U+C!qy' M򰎎MG^w1:XU^~OFԑ-DZ>^, ̎fC_GN\WW!ޫJqy(]k2bFpYW#"sypvG;r}xC=Rč$rtGVef{ƌH3KXޫcG`3Έgh}!Jy|!{>2ϪhyLܵ+~AmPBzc#RpzGa³Y]_0l/m$_0C3"CyۉFڬEIOiNvkGd(uZ(^wghՒ&N;]klyp#"<#15GFN{D0RDz-#>rycSk/KnF0 *،3|}^`' C? U.qG{m#QYKzKoVʃ}rFQ/?uF0{ ej{1Exs.6f-QǾ最S$NzفE%)a<^&cW~e1ᤏ<ЙDQGH c]쪫Vd %{pQq\neRԏ#y ˻=*8 $H0%L.9qȸ=rO>;Q>㬆?n>2IgQx/+#7y&ɣ}xP]>Li[9Gv-V=B4pTI^=/5)yr{{׵'~S>r]Oʣ}xrlN5:o&,>qXq7Rg]v'2|?,^ q%Nd oyl}\Y{re6ԡ><>;yt^G觨O\t:R4Jߋëvzh!?Ы.η粇Zk(v:zy{}J7h&Z^$Ƽ̕W8؃Ty̛E-ܡ N)zu`㧎Q|yIgGASSl1x߿òf^x.L{@e}^[#s\g>_&aA{1ԇ^胷O>Gs%⎟wfǜ aRֽלRx-jfG{TpcrS!לvZgΛ/KeGiX227{XljAaƮ]#DRMC}7qa^:93~c'}P&NVdP=#<sA^pZ3R|vG8uy_C:i}OMy@M0?8>'AԒ1PM~N/~yk}DXGҢ<.fyϽU*BKW ;v8c̫U Nǿr;oҕ\?Aumm薀t#sy|-IyUx[8Iy4= 1Lg&{TH 2ɧ;7qíAԂO݇g^7 yձu.Y{,g> }xcY6[!=yn[gϼ;<{EǠdyl0?9>Vq+$vlnك\kև_޽߲}۬;XDyzEPd rk}x,NHܱ팓iY-u L(y@G4"csc"!=n;}2n̎@1㗥`7JZ!JUGy K^gM/+U|;rWwH7{?( </9.WyͰ1qfqk}ǔmqTa!y>N^Czp ^byϿ}|3]{G=zgòj#M~á]cGҾfW噰i.2MaǢ|ԇ!c#cs%!žg8[utc6_q?#$Sݵ*B&ksy~ͦ&}Єۃ=m)O;ڎ9k6a?C8Lp_Ý}\åMin`{09'>wi>ϋ;Mg|}d4=~Qǹp28gfE_}ؔD5M>gPguz.wlA\q9lѵ_qc|c_e> ʽLa1E{/cTp/j>܇[>SG=fbi}.]{v=jA:Dn{x#!yl.iq1^>coe>{c{~N屩o^w?ge91Np3]Dz<&xˣEW7:93F֔_E"5e Cl4`}Y1(HHB8`{~1^56vzUmBty@o" n~0/LxV#n'ֈOinySYARd axVy-̜ޞ@{ {A ,<χл+s*~i>"-\·]1t.&7~4CѝWNFN1uhÚ޻4J!uA "(o#1j%G=&y4<,<}v'WO1݇uHTƽnڽ1?5}ؗJ7;7Gѷ E܇sr>Aۧ&w[}o_ۘǰQ:n{Vy''oM=zj ,w# IiC̃OqќL= {DyU q3o}#cĔqd^E*1 @7H%oaP{&{x|@=a6}^C{4qqG~zGz="ypCyCYCyCYCy)2;ғ8)2;#t{ҙ6jN&JdJ6r;-EK[t|:d6J\G> i4a}*ݧ~䩁=x- G{_vttα[o2Skwn39zBu)i>4*&!Y $<PՃKW~Ko?:10ϽMtZcTH5 Br`sGK,K˶Ӷ`OW'^%mWslӵo-e{~ji~8$8??ްʣھT>._Sz۴:.gF9b~qJAn0IIDAT9.}HluS{x$chߪ=%F9Ts;O:kc3|t[߾w"G(r^ۏzIL6{+qWxMz.q.m>h0ǾPsqn_A pM?S{N\Xkc~ {>dmBzs{ogc1қڕN5pH#O zv0br0Jjcftvścϲg3]ZX+OpG؃&yb&0)?fsڦ.kIa]er~<$'Spy 'N @8<py 'N @8)ZbvYYRR=Ǵ>o>{-m!Ŭ/:{-#$ȁQ<~\7S= _Q͍n Tf14TAe(]mSӭnTf!W 6{-U΋:{-7\=Iu(ZlvO|+٣dy,qB{,"yux9"xIENDB`PyChart-1.39/doc/pychart/pychart.html0000644000175000017500000001410510352146646021243 0ustar santiagosantiago00000000000000 PyChart

PyChart

Yasushi Saito

Email:

July 2, 2005



PyChart-1.39/doc/pychart/img1.old0000644000175000017500000000027110352146543020233 0ustar santiagosantiago00000000000000PNG  IHDR 2!PLTExxxlll```TTTHHH<<<000"tRNS@fFIDATc`v@b, Vb& b.a1j b b: g0N IENDB`PyChart-1.39/doc/pychart/img1.png0000644000175000017500000000027110352146641020240 0ustar santiagosantiago00000000000000PNG  IHDR 2!PLTExxxlll```TTTHHH<<<000"tRNS@fFIDATc`v@b, Vb& b.a1j b b: g0N IENDB`PyChart-1.39/doc/pychart/fillstyles.png0000644000175000017500000002361710352146636021612 0ustar santiagosantiago00000000000000PNG  IHDR0 PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx]K(AW4УrABHn a>WsmY9||?~:0 (@`4Hp<㱂8Ͽo'8;"-"R W L?Loo{:탈% 4ɯ&QՂط` `a81̉FW eW2-W0iҷ1L>+=0E/00&1\_D9^aÔqsD_{0iҷ1L><¯ a~`R:¯ b|Wy0Y/00u]Is a+ǫ< b:x|QՂA ρu_-s(j`?Liെ-TV0@8K3(`\B-zr sRH]r/wTZs[EzμVS52rٓ3gVm^_Z? !膅)=&reqc]dַ껺`^w9cWi!&B|> UhߌS{>;97`JpީvZmA/_/ 6Ok߶jz ~HwԴѯ+b{]nOPvoSmZ0~BlA(쏄om[0;~H鞿8 @x7ڷ-jTt!#w01C!wߩ6CxGLt;ڃD_0{\0u_.|OC' <ǎOP0o| 03='t!=;+GL0'f(LlT=nՂ 蹂r|bźoz`hH'F~?!`n,i x$G`z=ф?S )q4\qTƬt/"5 p4\8d]9"v'`c3bTny< sx0?Th 0I0?s_m` 8\~.:L!j6uoxI&h]1SLuhB0Gl0' I0?ui1La9y=L_ sX1 m =w !|!&SN/Lp5cL P\^/Lp5cP cH8^a 8fss#1Lj< W9͒)f&I/ a28b̏Ä' 8Zژ9G+U m5u-}mFԊ_W†Z0C1V0xhHO"Gppoub'ks>=X0{b[h FyE3  _ƈMM}_wG]8lIEن1[qHCzM&ȸ_zzL7Ţu;L׫XAԧ{*Eꚢ6ߥ%U[M+A≤;piE-([=ߙÕD*X`q_lSȴ\iʡ[f:HN:i>C>--Jzav/hL%k>ݵ~॥Cp#uaKj0+Ȏf8QM2l+ϕeE(x3y}:Zn-F䴹|4 ,(9OR:/-kTPQ rؒ5ˇNc5dNHJ'\ioH)wd{r.a_rM+nFrP]0p& -t 4t C/Yl} `zZ:Y_ZۼA0PQww X0$NyN`/ Ey2 .LvY\0wt?ܱ Q5m1n>iƦPaTzjXW6/'jpJ~yl¤g&?U+M5\9굇ՙ6 bOkyScS &HW͒YɠN6Kf2fV>K04uv`jt3s侱%fcZk 2\W<6_ٸv9,=ۉJgv`oJb&dQWU%71Z+S0\pnkvՙ7W@OwlyS2um.= ۼAiq00\Է9`􀟤3Lu}$Fs6'̪ƇKcu䢵id.isܠQWOA.;. @0P @ (` @0P @ (` / 8H* & \앶pDRPq_ D\?c#b{ *KpB*[pyꅶs쉿= $LΝ5p ywLѾ$ayMp>cޜ2Ӑ&_(cdD c/z!1޿aVD^0Ś#sד^֙Z3$qGz^l`տt/FI#cbz bz Y\1L47P0QLaSϡ_zhg`zI00#b|a堙c`n2`4pȧI7s$L0wzA tL 2hj#&[La~vIUf+xs|lr(3i|n *]W=5/"mUu,_K%X9ۼlS!٩ծ%jWUabT!VGdڬx8BslWvŨ}_&[#8ZM[.\0ɑV5t*5Ud/ /pV]@-Q )R[d?fZ}_T#]H8.4 +F-edkd:PĻ0s[y%8V?eۜ31^]m _YmKnG&6LOƜ$rh QSZT:3QVmƐr9>Uety%0Jf}]qmWrXLLhieŨ/nLFܯ]sh{MN NG$av! jjy,ƀl${4 pkpf𸷖YRGқԈ3`D8}VV{K1} _Mdڕ]fՒ8IPI\ =uiᰕg.-MїԈa e0`s>.sFCYMNtg3TFaVsޅF YIȤkd쨸ʬ}-j%3.\Ȱ+.Gԙ]խuvo('͙[451TECQs,`9fq /F%w;380#Gj[0A[A.Y˨)~ls\WPkaWs~ G3= J0ҫ "QL5`VW4h*jc8ʹԿF1hjWEغj1Ljv dP @ (` @0P @ (` @0P P˗I x$G`370[5\-H?Qw5C!M0]s iLJҖ'H饳`nCVy%L֣3'H%E0qŐA ͑8RzaaK:#w2]9fs$my"^ &T(f"#xnh9CLjyZ/Q0  Gld?G¿a"LF%!Y:-OđKOs܆1uW9<GJ/}s2#H#`9R<GB/s:#,Y Gld?GJ/]c[Ldip4\H&H饻`2ᨻ͑8RzwkLJ1SK C/ly&bK{sϟ0Aj6GҖ'H7_+H8 ld?GJ/bt:#,Y Gl-OđK3d<7s %Hˑ8zGʖgHe d$L6G#1̭bd%uW9c8Rz&3?9@ (` @0P @ (` 4 FRc4^\keXVUA"n/X[) QSDsH!CIUn[+HZ-`eHS>V}3y?Ֆ*V[-#!PRi/oV MPuQl(ƄuB\K|{:ܳ$3rQ@}|G[KAG0p{5i|mm qfCkLV FXMcIr~GUzlmۢv$,9zRǙ$1}IU!ȰoDVk{P;V[)VIh?`EK7lHf&$aJ0&-a6Mkm/?j[f87!Kn:0&/K\G5ebɎ;L\TͰoCnkwwj` k(O6 Ѡƪt^i`mwLb=D{!g`\ [۾PFe.͂a6uQo8lHqe\qm&蜠۴u&۬6U` omɛD?>8juj֥yF{1,LUU)A5(m?&~d;3LNvmڧe V[/NPwba繞űdv57mb<;[^e7{kP >j 33L̺&u*YMCE%n9-LbBD[ \-+v plkv[7&hgptʀ 0A0 ' < |raQ=d"hq`%==9 h۳ٓ[zq@0@>lv`»hfx Ipp?߈G?UFpy5kO)f3C5kO)9Z3Ip070gkPX:X)c S`?j3 1ɚI505kY-b0$"^鿵fBCS"?pL!< ɀ;k&R < AKfڠ+zRZ`.o !AeԚI5Dиpf| )@0@ Wkarb0$"hb1LWbao0|yf| )`HD@qeI$n_ .l t l t 6ap\#@TzkaIDAT0]8" d u !ٻ@8‘R < 2fG|1 pz?8@0P @ (` @0P @ (h7:B>3Kt`8;9ӻDWeهо$鍙9~tE0?Z0~io3=~;C*0*6jc||ma{A Dzd +e(VeY ( woqLoYnQ M\)V+x5fxMʻo5ؔ*R)l^ԶP)]7cG\ E"=ų S>L*M _~>(J|l%s"O='@0ͫp]I1f}B`c#!9k1ZUYLL-Sc3B19`L'l {XuYNm_᧷[~#H/ Q}1 MA;һ8ă='g)ԜWq 21.4 Clipping


21.4 Clipping

A rectangle, polygon, or ellipsis can be used to define a clipping region. Any drawing commands ( see Section 21) issued afterward are confined in the region. You can even nest multiple clipping regions, in which case, drawings will be clipped to the intersection of the regions. canvas.endclip() ends the clipping. Clipping commands and endclip() must nest properly.

Image cliptest

Clipping test

Below is the source code that produces the above chart. ../demos/cliptest.py

from pychart import *

can = canvas.default_canvas()

data = [(10, 20), (20, 65), (30, 55), (40, 45)]

# tic_angle is the angle X values are displayed below the axis.
xaxis = axis.X(label="Stuff")
yaxis = axis.Y(label="Value")

ar = area.T(x_axis=xaxis, y_axis=yaxis)

plot = line_plot.T(label="foo", data=data, xcol=0, ycol=1,
                   tick_mark=tick_mark.star)

ar.add_plot(plot)
can.ellipsis(line_style.T(width=1.5,dash=(4,4)), None, 30, 20, 80, 0.8)
can.clip_ellipsis(30, 20, 80, 0.8)
ar.draw(can)
can.endclip()

The following canvas.T methods are used to control clipping:

clip( x1, y1, x2, y2)
Activate a rectangular clip region, (X1, Y1) - (X2, Y2). You must call endclip() after you completed drawing.

canvas.clip(x,y,x2,y2)
draw something ...
canvas.endclip()

clip_ellipsis( x, y, radius, y_elongation)
Create an elliptical clip region. You must call endclip() after you completed drawing. See also the ellipsis method.

clip_polygon( [(x1,y2),(x2,y2), ..., (xn, yn)])
Create a polygonal clip region. You must call endclip() after you completed drawing. See also the polygon method.

endclip( )
End the current clip region. When clip calls are nested, it ends the most recently created crip region.

PyChart-1.39/doc/pychart/colors.png0000644000175000017500000037553410352146636020731 0ustar santiagosantiago00000000000000PNG  IHDR2 <EFnPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx==M~iY(xkWp#lxA"#p068D<و&q"&2x 35@h5(3³3kЛvWuw}tuw]w}:Fƫ3p/ 26Y@ 2ۙʢvl| f3m6>Y}&>xhמwמ4ڍG6t3W9>x[} DWD!>sZf=2[%DwPek\71S2'eO2;\9邯eDk0yGec;k,yN 'Ֆ5DϚc׌c鼿a,2 [i(25˼8(sżLh>w0/4D׌eiyGL2D`,+2]a^&L2OPek6s (,g[fnNE!DzLt@zC, 2WFed2v,FF9Tu˺1ɘҰ[@g?jN}[ݜ퐉}AB .勘$8Yeej.mr %#`ˍe)hclr8K2G:ti~uc1%bs2Z4>;Igg+8YeZ ɕ6u2muiQiF27]Ux%3JnY7&Y*v+|Q׵Ʀ+wPmuَej2s5n%ed*ALYƲ̑ XfN&eV2\=*YA,~)GӅŀ]1Y1+ d XQL[:ÿSo BMQ&M M Ej2JN í:,z,S[anceg~,y}ꖖ1䳌Z&XVC}#Kn^kIQz_SXeQwJns톘CI27¹dlg8Tu˺1dXVMf]uN9iJa5,[Ȝ2ɚ_ut:`Fn.K4\бM톘-g$q5xߒ:RuK˘drYmUAT",<,QSȉWwoS񁸫e*=^83O)⮖Q?Iy[r|nkj_|s:\nK{˜brMٰu[XfBwe2aA2o IdŤ?(,r*`0 z3kz\bZV VN('05WL53m̿9rW *d; U)yZc/+&XKZϞA4T,sk`Ť2l?b%L=[c/+&YZӿB%w 1pn&+&XYبa`y^_Sk`Ťq7^exϯ'`é5 \b]]jIy2ͳPb0pjzf`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@Z&"hUCY?|h}ȥן}̤g~|ͩƍ4>"~ h.6l#[wkjO7|l2o<γVɲE?X11|QS|y(3ē'QfO)Q?x+ʜ/2e5nWyXL=QfOIQfu"˧w2e`^FX&Vc,(mX&Myi+j᠃çeUN.e)L$Lie0gMc9J>i#Իtʹr,\y(%[$5ԗ*l%gO'zxQmWJY|6:P&!%OQM0\Wj{XElWC!SX)O9a0 ͔nxS'sxRqN{[r+2XE7lűJݖ[JjJ}thFA8uI hj f:ȩPlz'1UմIGU@JBrHJb*M ^,3lՓ`|f9 Dbz\SOle9|PNQ=%qfa=1/mS['dGs>IOo:fWxU[SRjXI +xe̿S=|51\7)NUjl#~RAbS,tR:Ǫe6莆9Q|&:^<_9W{l)4-EC`+c"~SI:]7 j} /:ht V]IJ;؝hgFR,c}?$Vuhr[u2gpc-8i:)`Ůe:X^4Y_Þu{T1\N9zP-lWVrH$Ypv)/Zf!PJ,%{P0]7 c6݅/Mߎ}t>R7蛄+S>GYa! ]ELv-ֽ_uq-3u`42v &u~n\뱰L=?o}OϦOG)=c-n o;5ԭ5m2$̲mmJ%/UC2xԣ-{Yfθ5mŹJ,LjaEW]?KO'z2:XB2t/M9d밇-K2leƍ8˴XfeP<2mQfaY "2m(E';_Xɶ $#KZ&X&xA*X`Yf^vWy`5^ufeΩԪȳ L3,eM 0+-o2{֡6ۣKX\ BBk Ow̎tX 3~L%lGeƵͼDnDrCu/+,\7Q0K$ۣť /?Y2" Ve2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , µLME4и³[d*ok|o Rѷgw?}ʡ-iog}ȥG>nyr|wq'Qf+L[{9=*=3KS[9\eA[}NߪOoTo9Sc 2(X&^r|ηiWeT˘zunLS92";y|S]exRa,Nύ2e5R2'+Eh,Ls6xΜ Q&^Q&[33V1D(X4ek\Q|m& exR1 ̶s2۩<e"xRa,Nύ2e5Rˤ( eD 5?%o9Sc 2(X&^2ˤi\5`h<7$|+x|S]exRa,Nύ2e5Rˤ( Ge?_?:CB;heD`X@eD`X@eD`X@eDx#4B9>r /ߦ3J1LZAZ ,cb̐2d-%LYs;dk426gZ͕yevKJ˴UQUQu)A5ꋦ>%sfRSINgvl⫫JMgë5$J])Se~u58PTbkύ5GڍP:eYM8X]mneKL%=CCN2S "lGk5gdW {BN֗JbxLG2m8fYٯߙ,ٱ0O vf:mW}vj=DQҤӌOeˎ!,SUӖJS'[:Y;SR[ESa;K`~b-ӮgJQ(ԻrPEׅOGntwr5,ho9NR=Q],ZJi[4|9+lў2󙈪%6N~$cL[)6}-6㩳0_p ゖY(e#mΌӨ^W^8'fw["i d9eB_LBx=|O˘?GʤZ;_STQ w2V˥eRꐛ2*`8uZ_oݖX!˴(ˈ4Pәi /?Y,cת N0[WUTmeݱU1278ueAsYoxq7hˈ5:+=ͣf[u[fm)j;=FnB˄2m8|cnޖeLݷo=ձwc,`mXeհJYZ[B`}SFU߷(BrzH -̴Iqx_f́e5V@kS9`y#,3hn z73N9VwJRh9T2P##ƔCq4g5ޚ~9e&!Qe$H-vkrf6\F;w+V2ՃqlNnqFu9AJԺՌіkd>x>,2)i >2vl- eP+72dV~n\n^ ^gk0_k oB_ L@6"ε"I<[&X. /$տ2wXfa1YD`Z&WX~9 ,e!_/e_q mx'/ IC EY mx'/ I EDZ&_-$ -/D`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@Z&"hUCY3M5Sָ4zI^}f[dhڍy>x`Gk\y34~mIG&-Ǵ'FOO,h\eL1EfJӸ2q(h<;ʬe 2eRxeDk<;0Ը,ʬg7'\Qfme"4.C/C2Ɠ 2e5ˤ0xra,qIa^&ZLeb5.0/(üLcx 2)<2e5eDj\e`^&I@(#ye5ˤ0xra,qIa^&ZcuC`,# ʈ`^cx 2)<2e5eDj\e`^&Iұ ev5e`,X&XLƓ chK 2ez0/qXy]gGe"5kV1B\;ڭ b(O5M ,\| [>Ӕiiew7)+˃41&s+f*JgEؘ"T 5e]-SnԪ%Xz g*h"0[m3\A:Х:$KTvsqݺKXZƪ))s+e)bqT7kV[F Wf 1*=v NU4ZZFkv8JӪLua3enD]ˤT2GctFݷ̼^Gқ*륖N4ߍeieViogJ+2Ec2&s+b\m(o.sϮeҹU_7oqX*Xϳ~LcmnI)@OuTJ2Ex\0RkUD 35ou;㭊y7u޺W*u'xǬ-hi>JhT;{$]:v > IDAT)[ag+i4P*T5:vٷLS fS v%vاnxR'X6wM!BRΝF2×ekU̩bp2i"Ī-7k*Wu"%sV#v[&mHDE6< JyĶRIZ'O/ߜJySIZxQk;򈭦U" ,uܿL6yo IuesG29g3yP]aNYPSWX0'-`|$O+,s0>'9H*G29i#yR]aÜmLQF(cǕ QrLֱ=~*l 1lT=֒P{Àmvأk"UUXCTn=ٕ(|1]Velή9]v8qejU&YkFoŸԺy!g 1ɘ j(FU^{Ut5TEUV9e,ή|ӻ\8m̘;ٛ]*4}-7E2cR/g 1ɘ x9 ^{5֮Dw*˪|S)Ruv%ȘHEzתeVKᔜ@^2D2]혏5wdƲ2]> !{df`e lbG[Y癸lєzR_͇WVL&I$/g?,/3m)޳ԏg23NZ$y9C(K,-(LYpFWNLUY$y9$yeyXEzq p΍UXNY$y9:-~σE3I$/Ge.([&I'UzTF/fI^:,`xOڵ)JZSs^{Z$y9n&+;X&e)ө:WAEUs*$/g.eyeԢeC5gI^Μɓ/D`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@Z&"hUCY+_W4LE-2i|/}~|Q9>'k&/#ƿ> 2_xj?wgǍ,O643ſ>yWu5S֞7*OODQ ʈ4L\}/Μ=Yyިc>] c>a, cDxK,X&EL D-^5 o eBD{y/3/qIa^4eke5.2ek0 `^Q&^",cixO7*'6_ą(sa L%a,X&^#83eeZ)IӤgRtk LpMYZ-n+)vG+|eTU͐H;V "e 6:+N'Rk=EM#1Ubb6RIϤbRM۔;SdF2:7]v'2ÿU5n`-ӎrLFUj {✧m0Ubb>Z)AӪvrKwmcLdF2cFM歪ys;gb,P/M_ymҵTb8iWb*qR4jSf`uRV}7 e%UjΘb}exaԎebOb*YXZ鰦SS*ּG0ݦtSd2Jiͩ-erMפŰCimvϩX[$ nFVLw[Rim\³fQeFRT_+=kOqӶFq*1eY~iUIlͥ4M/6T2Uc|McpUf3l4wz|wTcJb4ݚW4yH88JL+hL*v̥mʱu%G54e$+[iy2xf¡0d>zSqSIha:I2WU3JI&=ʼ6ԉ{jxF۱EUc|Mc|J2k"ʊei!t;qE+gZZYLR{^tekke¬3w37.h,sb\+ks}9/pn-Ӽg\UUx"X` ` X&Yf^ױ٫-AVe^եV ) %/rxq-,γ,Ve^L3H䜅rU9 3g<~`9 7ޗi]UTPR*b,c/Z .s,\X&[TSwZPR*?q-vy|9`e-n/;RE'.ʱh18S/Lōe2YHyBK?eyzQtGeN\x_8NZ(y)W#d3 .S_&,A\Xōe3hlYMrU92zbeq zdq]tnMqBK OYzj9 uRʩ20񔥫'S\, 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" 26Y@ 2E}}i|sLͤo~]=4~fLb\ܧlm'Z操GYfǍ4~oX{οȤbqe>5kQ^eƘ~PdI5~yI DklĘEYX7ty[DWc=Pek<&028y=a,c;Ye5ˤ@y3 +c2ˤi0/qXf9X&Z(XFƼɼX&RL D7؈1`,s\cm͌f`>fzOq5I Dk0y̍,u2vP%/c2o1Ýa, c4 e4.˰^Q&Z ˤh0Ը$0I Dkl2`Lcehe5`LcH 2)eLgB1YL2QeX/A`,#2)e"5ˤ@y3üL25X/qX2 hq_@eD`X@eD`X@eD`X@!3jS#?) jAB;s2U㈗WY\jmL]ŊLVxere2Wԑ\k9I\EY$e65-I9yywre[=m<˴UQpWykmiû6,4o03$RQW4#jAQS}U1JezHcHdiCHa'8fllR'[Dt9ʱ vp ~&utJR6ebD.V5btt^Zf-cA3i8DFJF)rUOr>|ިVR]ӨN{Yd֘N崑$R謪qov2^ :ҳ\biaN3QUgfK?}n^^{E럵Jsmwg;H)¨1&QоC,ן7^1eS_dLu#7[ٴ5*M,3'd-p2TIn*xl#yX8[ˣ͖)@skh㡝޼fiESU/Jf]}%KuEmtGzot5Y^_̜}[soFC,8A{kEf-7|BҟџT=rXfȦ1[Wspj)N2Vok3Ɗe;W5Ҋ0yқ*k{a+D-G^fk[0eZsbtSol$2m\뫻j)khE1XjTs3q="c((.MuE˿֗rl]Pe3x ă1=8ߙH_ݢnɩ{jm3khsqіr2q}"&z9otY~MWc~Avmq#q2N ~[iOͥM-<4e1ݜSݦfkPzU[^{EOqn)Y/GH+¨1%&kt 7T4t 4[2'Jcs6=2]S>fqbzI}ki6Kѩ6\[hZ/>y#2)8X6<2?~w.X6<27M,Hӹb9K&_@3,s}hijJM I䞹`$ r}hJ-7)k=gZxfO[ZxI syeYy=iK /טҼB\^`sz^ϴr\r1K9g?]<+֯K _qbxeNYy=;ɒ&^Z sK^+,sZٱL\GwN.er)gZwWh:Y\^u,Z\+3^qbxɼk=G[\k^qbx7 2˼X6`,`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD)ɢwPx߶TmI"?"E&k&L㷬yotxLex2?L[L6SoǠSeƘ~)c-C ke4k8㗟3w21̾ƣ̿Z(#5QcFQ,^e._@h0xva,qQyʼr>fzoe52Ϗ2_;F|e_eˤhe522xX&43=9a^F(3DGQyHe9QFX&^QLEQ)29A `L%QLQ&^(#(sX1cˈ `LQ&e0/s @LƳ cHSeX/s\(AzzeR 42Ϗ2e"4.2_G 2" , 2" , 2" , 2" Xf!vY\D2YQ/*&{Dj,;H~^d?N^zD˸|k2kYaof52XFnV-ZE(Mז'e_^ͰݤJP!JT921&aUV5U7ir/V(K]b̏}Vr>"}Lvy1gשJeYM:omLF9Zr-dzLYtoZatmKы6鎝jDisʦ2dbNYY [n5TeJKpZ9*;?fw&e *IЮpzV:v]nGi]ÖYµLOeOzn*ExkDk5nʺə0IGVȪ1OnvR|8xY >v 0VvլzڢLu2z(Z&B|׶[afjzFumS[glrSvkp& IDAT#ǏӦ,Y=|mCi/kB-,V˱ReStrE]!feݺf!|9 |QҘN϶evoiwGi2~BJ}L^$Y^[WEUN]n[Fq2[zՎeT*2ˤd$19~nj;CeZscUY *S-I n)nՠ[ۖh̖qe*}s-`EL$B6==z9B[J…bDPc-ejTMxu.ШZ&B-^n1+}YNrcu-E̐9 Sod7c6;ncj2 ,3|˄>^c/j.MezX,^rz~nT|UwvF Ze,ݿLLI#GM]u\zGmv~9kj eBj9@sv<֝TVYm8 -f*bgdoDQlL1$vS}-spn4ubo2FebðfHUyc 2Fef %ۥx2M`U&,s%6\,s%ɫ4o`X:~ה)ĢNF߽\Zh^_{0H]sWzz+X3&ec,:2<0sރf嫻v5q5sX02#IVRsTW'$mecYf}ur5409@[] $\`mk-ajR{kwi`r´_jHs aeVWG{9 e9֮Z\59i,sy o+bi`rB]zkWVz.wΟ9LH G, LNmך,'\*tc]eO&budhyVKxմܬI;`x%'<+i,ĕ."2N\y"R,/ĕ."2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , p-SlE 4,T__tg[do7F5nInI>PxT_ōG6mf~2RkO,`=c~!c筢7e2"exe ,#Uc5ne6XxeeV3w2hohQe 2D4.? b32j<2O2kM7~r(eU,,0qSc`\ZG%J2U(l1\+ȵ 7BbQ2uMFjhjjaZKfaNͪrv6>fKcyJ`Bq0epK@ξ"@*lΦ [qC/h+$%WBktec'd5L,SSh}%6pLw6X[s^wtxؔ`D"4J0sZ^A2Yf.AY\]Y Euabe?<-vGߴE,3qGc21`(X 31ueL OEX\]g[-MsM XmfkݬiύI-_[&"^XiJY1%oWeTzbQrubtR̮!aNL[NW|b5'N~:}ܮ15yeyڊJdixQ{i{J05l*p{>N,J}5t^7-FF=g}ۿm+C2|[ex;Sw4BY6E$x-PzNʩekRH,JS seԝq}'cF9V_ek2`1[rX w蛺60y֘:e}+$_wv- Vas6)nZ&%O٦gӱ0S_9Ym,YΏ$]'2qf{qFW[&(7:H,S rgfygTerî¬Nы2EaY~`X@9yeqܟ ˜Z+|__/ӄxeN\y<1׋L`q/̉ >/ո;bz--9q`|_̢^f9oe,ex\k+,sނK5.`2YԋLXk2,TLeZ^uj\s-~Xzkxɼi >ո9Ϸb'VWڻ@;ieXwǕ&w3y\j+Mg&dW<1],p , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , p-SlE 4,s??TE&E&E&E&Lǿ{󏃯4~4?QD#e\}[c2#e~Z=4on<2im<2i6Yf#eDcJ+WB|QOW2etG5_Y(xeE22k5X&+T2{8H7uR>,`Kla2ZL e1Um{F׹SWFe^mjvh͖^hY6񭽯F]%%2sÿU5nsj]S`13"֖&eɑ ue(}U[m]*C&5?su'$?>U+_ ZKVv-'i kZ#9H-KQhyabgf87q͜X$2~y2-ӨӼsDQlh9V:WwD֘0zM]zW|}Ha0}/WDd2_=˨bՍlV5xIDUG\`wNK(=DYF[=xTcT7C}/WDd2s&–&NWLJ#.㑄ߜnX?NvKucSCJcrU$)Hb2u9yuh˶3[:)Wue$f)*1){Y:&5/]%2ҾF}k}$9H-fJ3a;_4z$ݓֺ5"ܜCXdɄ5aOʘ)5?suiO^n)-mk8/7"ٶUz~aԣM>_ po<|橆MY"=Cpe$gbz*bau$'EdnO_ v5@'\"o Dr/wsv WID\p?^`uFjS'ɒ /L' G!m~ 9yŅY̙KMb+LDX,`̳\jXa",`̲򙿄:s[,c?m2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , µLME4и³̧~7[d[d44~w,nfz<0/0Xu0{E2Ee,#`^&BGe6a^S,ü xe`,sX0/Le"5ylhZ=2eYEQlagٌEkscR dWsJE1lM7h酺DCMۧh*ȎUӵ'WYv$Yf<s%eS*a(mRߚSPJeΆ2bQGSuCUC*3씦IIf=E_1r*ȎUSJWTm]VˬUzGîDU]J]Yh>b[NgSeVqj@Z-NȘI,zeNPdrU5}G;C%&XL%٫ MQ[{]jvrLt˘˹`*bL:^o`S59E a]kۼzaZW|[-ű+v[8$݆eZugm6Xuҟ?=t _k+q2+uo]+tїhs>2_kWdU;]R[,JܲJ;nYFej/Jƻ?rPo/84MJYT*r|Y5ڰ)#Wڞe*^]ehrh9bַ~[ %M[}qkю=SvJnӹBc-r̉yjXussU9BɹR.`AY1.i \)BB(W| W\Uer !Zw VL> *2or+%sS 6ʱj,+VJeW0篘| %\UUdY)R2X/9c/r2Vʅ;+&m~ W#p,Jz9SͯrZ)BB8|\Uzv? ,s }b+&c V]b>$ , xe ,JZU ^b*3bܼxeWͫ*ތXf7~*UoZF dUoZfcI_o-^%׼ݟP2+7/\2Ur2| =y[0)ɛZU𮼩eXU ʛZ]yef72" WXn ,_ w`n+~_ 7%d濯 WyXɫWMyɼ }%~ 2" , 2" 26Y@ 2_}z>SѾE&&ImI#wȤ4><6,o>sY\G&-|;WW#e[|ͤO{{_O2_QWOA(om<2ƃ#cY}\6q721AXFKS72"w΋2L6ˬcN2e52v(h<8Q˷|Wa,}-4?s(ƕ`,AXQ&^|23ev551{(cfa-wV[e<Ee`,AIIcGc,`,sXyx L 4kX2e58 IDAT2)+Ÿo>exeN' ,Bn7yeNZ˴lϞ:2}`Z,ijLY6E9̢(}[EQMMV}եiUCYɯPTcmOurΔuMaaf eBFYNc<`ZԤ9k 6!F چKufn`aa k}Xȳ(T5SCM^VuQR+z<~XcyTæ9b9&As+yS7=;ӖɅXcm[`p,cZtJhL 6!˄13{ M_dUMoXNd*6u1m)#֙='h[HdP̸S,!VmrYfְ,3}37ݼ!^KF=?;asd2JUֵn>Wt]ex.muSaq& o,c%Įn lrؖII+$wYF$lglUhLͤx]Lgiad͔9{A˘b j; pew2öLMg !Mrln{!Ui5TWS+2p%i]Gb$j(!LyG#5ohN/HAB-8u3C߀(楞o XwK +[FW|>eZ}Xgη`:VkK ;{BvYk̵%atm{.k[ ?;&Xm.\}Xwd8{&9;Xku|*9{!XTQ=ݮ8L4i^ݭv1^9Aѭì9a ey oQ)"S+L,,sfÏ72눵L{7]-snWz,sB~b--sri?,{x˼< 2">erfS-cK]E `Px$V<2ڿU6qx:^E `TxkC]E `TxkC]E `PKRW<2RU6Y橖8 , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2"\dQDj(<[d*wȤ?߶L_FG.K>Dao?Tkw6,Gn̥i=s¶<2?xzk=2{n\7Ex^N(12GG>ˬGQfOc#A6<*\5 (e oˬk0Ia22Ɣ+c58&Xfc/|eV5$ic5`^2eR`^41 ce`,2oXF251{2cy3 ed09qX_ e g5X/qX2re`,2oe`,sXyx eR`^4a k0Iy7`^Fc`,eL ek0/X&eL#890IIQyH 2)0/fed@C , 2" , 2" , 2" , Bn:'WG~ޖEٕĜ}dJ9MYOUϞċ(ھ6}Mg,sVCns׮2{{meJ| 9Q,27I*+fmL2mUEթ /fˢ*mgbp %וRK-h4 U:gIz9J}]6_kVj/\?9ꢽR5pjVQnUW&:R!mnEYF]ףQ/UWU;k~FʡU;+H][Y3B=|Q^z_iօRf9C'5V ICӬv c8J_2S˹k+ebanE*mӎ2:e+q|d{2]/)u;]W&Z^րש[&ܯaniӨ/8<~i;"Ll2_^v{o"h1CE2UVeXj9@zeҽs)N̔}o(Td=64YOjO7^RVR*:5(8\WnWeT2F4.}fl؎>Sz:m,3e}=M4-<9=˘\efrIM9iuh5(eaunQE=w2nt|7^ڹn78 <˜1dI@6ā|PZ<̙21,,s*@x+N\(y)WXXU^PRX98ov eWqBKb@e7ąrρhd[oƉ %/앟+cW›a3t韴PJ.Y9cv*@x/T3PRX9YUVPRX9/D`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@Z&"hUCY[d*Ȥ-2i*I/k&??g&wL9/'Z5֧֞eX{nR1J9TT}~{5Uq!EU,Q+Q<1 ZK8zo(`ߣ̵oJEZ<#י60PN< ;%aH݁<0` X'i&,s ;>;a,Wsת*ros]ɪH>Wjn"QkϬZO mR^m3N3F1ol5*g]Ʋh[QqGcH,V&BǼz׭n(Sk4|Юn+5N7st ŴT70 t߱e9|*Suv[FՇ+zO߈Z$leZwqX2.ú8Y6A p/̌R_;Ĕx.(/[WvƑcod%2K2 1?^u[ﻡl.a' UzevδR2[f2,;çkg\DJe&e}!w۩UNXF?^oʤy;`n Y2&P]r7[b7d7n?v#AzB8qekI3PVK;uXTVwGJ5xTC4v 6gX@z+Xf I9BǼ}=zx~7_f<-˔a%n53m}NvZr\PPcN$ev0L+1;p㸮|7vkd;a3WZQY3G-M1m0 Ń^[k.Ɲy qu|eF2-ǝ,2gx9,!XLL<2g{>z<2'{^z<2{^z<2'{^%z<2czk.AV<2'{^˾eV~4˜Py-k$㉖{^%z<2=Ox=˜Qy-T~ܴ/e[,s?x#en]oײ ˃eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@21I@enV?>l>&ϯ?:=?~_ӯ6i4o>&#累iGg#[*-WypKѻc2Dn,{[_p72ǔ{(3+{(_e)[DǗ-C׸"_܈23gEKr7y>sF.%w2{yyLlpoe5e5r2n>4e5eb 4xHid\|^\221e2ϊ2{y eV221e:83o1Yi@hk<3p^K\_\&@c:3\fG#\z_P/#(# xV^[\_\&@2Y2jp^_(K!xfἌL D2Y2jw^\FQFA.(CL De5e༌Ɠ,_hG34,2" , 2" , 2" , 2" MTK컲c~{i˳ spծZue -gmJd3.ǘZ_$]5EʨzOxģ-跏ڵL҅H/™x,e.D Y+[4EiEe>S2ϴf V˺Wa<淾l{FJ0O[VX m~\C`jN4TPą29Kٴ.aaN0>u]Xྚ&;^T/?daeJ&AivBϞCX2淾ڎE3}zsv?.>v\!;papOangΧװ4 W$XLqĝ/?fn8Yѯy9{f7OҷWYzd!&=mKUe-$ҭY0qɰZi8=1[jZz}LWk6}/b}:ЎHo}[f:iiuƹ5We7lXi8`&9ohN#ˌkye]LݍWb*O5vc6-Eٸφoϸ,1%2 15}衉+pn.teşMˌky(225^z}5ӛOԱٴq8<,Nz,}z6^≮d<Ųklwk!Q,Zk;Rl4=MBo}3[I&Qe;-3[? >*.4^akqzc[ W$Xh-,tGRtG6}؃1JuTaCBLMt_ٟO='9೻t uUٳX8?NQ[f2Y ':cjT2"y9@uO$X"H&n.l&X; 2e{B`; 2򢭳X 7  *@Iwy‘ %/$t/9^P2 i.e3.-.LENrX&s /.}&rX& /g +u,YŅSW(%X&~ʌ*.B,2,Yٰm L(ir6,su,YŅSW(%X& /-y`p). %2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , bn$hqW 2￶D#i׿uc"'?ٽ'#ii#We~}pKe8u*H?9%:%8rN5-nY';E_qe*ǘ_em,>Y=feoDQF(3Ĕ_/b}}(sce22eeHie212fI([iv>j=, QF\&2\! \f~>fxMie212Ee.=/3}e! kde6 EkLQ_#(C.\ONrr^FLQ_#(ye|4edP/A8ʐkdy^(CL0Mk] IDAT2 @z kLQ_#(C.Aeb heѠ^_\F2D FeyLQ_#(CFƹL& 4а2" , 2" , 2" , 2",fWKvf$5NY ӪJs50Ξe*lji ϳ̼Ze#-3qeNl -G8o2XX&3- )kREAIEQfhRiHwv+av?EѾe\tB-uO߾6Ta\ޡVWplJnԭmV)wUCy1MPn_iy5tY'@1LmJW0YHEZ觰^t_ѵbn E/km^QZbyZ^)bh[r<֘E({c>vZB'@1&k _5e-WtSfT3lѵ3~ڗp?т-3[ޱVcW]@=5گuaxhL"1w&UBcrd caʺ+}r 6)Y,jW;plc8Ʈlumv݋qV5 iZD|T w.G0Ee ;[f݁eqZMdn:uiBev4YHc"c>ɤX Dedox--3yeeJ ,x8Ht9ҘEz̧Y{-LUTJiנnJw{rpYfH 72c8ƮࢩnU Cc4%p?q4X)zU( xx6bNSYѿ2n*E༩F'\Fê1Np1:-ZbQ-Uw5CXY=RGWz<w^;F?U]Ui-XbdޮY.?S+86յ%ÿYP<4bT;+̫E/fdyva, 2wˤgڨ<+ p/),iF<+ p/),92[ޑ8g:chά<˄sIY-Oئ)T*L0U~ҲqZWeB] p/ո ,J?ҋKOBENiyXdj\ Ef-49UWeBٱi[i,sK5˄r])-4*T*L0U~\K5˄sU)-/4)T* , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2")Iwհ,,6o-Fħi#iTG$>6OOngR {"#ǼOW-F]ҍ>aYX';w̬~}'4`eFF[5@iQfhT&ʐxkD|1-y Ff|Lf.l>eV<3/YЏ#QfA.ÕLG{}@IQ22zkp^&J#\(rGxkyQ_iQf'̪rO56 242e"r^fUDClcἌL e\fW\Fe5e5!he5rer2 2 Ӣt^rO5>l <,^C-2<%ʐ@@\_IQ22zkp^&J#\(rGxkyQ_iQz_ rO56 ϳL& 4а2" , 2" , 2" , 2"d1*uR^ 7bk{)'D2d]i g->J[OըDyA8:s C q[&#[<2:]4P;ncgQϲLq:7odonΕZ?gn`sq:e2Sk]Ƭp#B?xL*'?z᳙r㯕UhUD}T:s_Cա2ZaA5L-+25M q(k2„vG*eDbe|#r?1LA8 ֯AR $`eDVP}[4vZ0)[&8,3.ݹ42n_iPkM]vw|ٱHayzܪk8:8_X&8[3z,2ikga4:ݮ~YeDP!D.ij` g\u]/2I47.{Y5tPV.\#f QÝQ0 0_cjs #&m=ZF^SyQ9AgQxk#j቙zؓ A&5qힴ_L8q%3, 2" e, {UfUf9^^+ Mܖ3^ DMܖelw2zId$mٺ,>YY4 p[B-Y4 pWB-s_~xYvreA򓸢I}L /gDMܖea- /OMܖ\fR}eD`Te2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , bn$hqW 2ofDVH?|{OD_v_mi|e_m>hϫc1gSY-ppKqTm|L_n,nY+;;mcשj}<DAT}yٽefWEQf*nU#'q=geeHi\ev&2{yyLe~;L2 r'2gnU#'5QfquQ2ke5.=/ۅ_~{(C.@\_2Q22c e58/A.y r2Drkkp^&eWEe! ׸ͣ L2 r DikP/A༌ rp xk@.# xr.Cc r @@(Cce5.=/C# r(  kk\w^zLB;haeD`X@eD`X@eD`X@eDYfRj^KOP  oQ;o0Lezl-Nt*vm"lT0aтEJn[Wѽ2*2'Ft%]FiR6-},SzsԠ=- "2gZ%WVQؽݵ~ 6ԠRiQjh,p ,u?Gl.iՎݫk{ux8wDv|}jutT/?vԴ lU8[OH-aV9b̶jDY^NU7ؗMѪjSG4_J:zOPSKwWIf0 y{`=4oFe]:}X N_s,cyx U4{shi3qS ovAlݝB˄iBIJMِ6-.ٞ>b2ǫQy ypjQ.^t5{U,.Qհ3Ã;YwF-?2V*~>v55f=bgӠk\24$]QyirALUonR4. j<͕\-3^΁vXTz,2XL"0 a`zV%@ã.6_r̸!o|iH4P{E!"x\4 Ɍ^yS@uC4E.6^2'eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@21I@e<"ѪUO{">|ձJD-Ɵq@ò}ypKei|j<%8rLM؟-}ݾf7:xQ T?M{O5v72}"@/mSw# ƕQfFyuo$y) Q&X(1Ges|yJcneoaDGD r92_}y rD` nC\Fy Die5ed||F[NrҰe52E|;ru|231k# \sxk ke5\Fy Die5edP/A.#(A 2WDe4222re2222D eb hp^_2QD r2_}>C̦ ?heD`X@eD`X@eD`X@eD,,3]$^.}') GhZRT vFNޣ7d9`K)wQ^a5nA t?ihߗ\,cvJ..*q6 ?պdeԠ,2jXm`Zu?[.lWW~A 2v-GNߺ/6|ֵ0Tcj?HfiTM Fm~<\!]N6|aeNlƹt.LoZ6tr g1`Xu}ne_ç]΂jV_aen'M+={י}_]Xz{&HH,3j8kfYq۲Nrxk йBph7-HF%Ĺbj3[2Ҙlwm12i-tJYU%ZjMjޫg:TCKzxMbY< N.S7Ngߪ0 ,#~Zl-Y4Xf|Jy}fR HowBS6MmvXwY>+l1FA.1_2y2_y#QDroKˬ ef2D(ˢ{.}}(E3xDi|u>fx}(G.y22^2 A ༌L hdp^&| %Qf| 2221eָ$ʐhP/yD` r'2ik kp^_\&4e8/A>Q\[(u>z_ r rD`1o^%Q\&F1ljp^FQ&X\_\2v48C/ 2" , 2" , 2" , LkOx|cT-әf~vF.S- ژΉqQڪLwrjhHOg]3Ҹ,Ja4gݍl:먪J?,^2 (UvV<n׵YMouMW{! cmmi+ӨNN+4ј~W(w2 K0Le\\&YeZ/J0{y6e!hSڢgZu}tF'n{ZY w:rZƳ5wv̺ j~"B_vkVVE:[ތ?ho p8=,avL p݆_w36A IDATɼJ4pZ]9O-۽Aw{iø 8w-=F2lLo%̹ӟ9q+>ٚ6;NtƽD9Ш ]t-mzd82jLQ{HvѐI؟MfL85pF`uUTp9yU.Ft oƟl"ǰWL`|l5VjRBҰGb8^ݾ<hCnoׅsV 4`cN0=-ibLn O6jIlIOԨ62`:_ '2O WhgqdiHvDQIf9Ujh? El.RkIFF,??[ÿ/\#pD}ֳL?ˬ_uWC j?/X#tDD}ՄH>[=K#˔OТ?/\#pD |[Fu*{}di.,1̌-[2f.rw0R -X7[Ål"CgN-[hH>\_:=Xg)C<㯡{l5[83ko_FЈH4G$ir/*=^!Q6"^2E1*ɇeimik2aCYiz[stB5GDdɇABun,Si:Tpp#<01eHw}Lټ'Ҩ>/|1?O9&i|h(Kj?nDQ_(=y,q8C.3⼾}."2?[3#QfA Di˸1x y\fLQ_(e2^'2 QfA Dieeb he52QcקY܉2312 keb hp^_\&J(AiἌu!2xhe5214 keddee|4e༌@(A%ἌLQ_(##(yk#2xhe5214r22142D( e5e/X@eD`X@eD`X@eD`X@DeTagN\&4QTj9+SPѢwST+<ͱ1Mg+^#aP⚮ xvC䤎_'Lإ;?n#gӹ{ڭ~-eNów5vAc+'SLK.E;EccafdJ#4)* ]F^.t;"2^P8 ώ?аnz-&kv)c'QpJlj5J"* ר=&givtp|9ه6U -9v۪BTfOU+{հr6۶vM8ӠakuԱ_/ ώ#<5_SiR Ǹd en6p"ǰΦQ}AB,=;c945vm^\iM˜{/.-hR.V-Z&D x2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , [8&"hUò/-ѪUG$҈[46o4_S6?l>g#Dg-e>ippK5 <%o[oLGۙQFjM{Oeitd~=YaNyAvxZ!՘ŕ8,1FdS\ы8CyApQFt[?aDŽQCbH.3 A %ʐ ༌eb 4eVc78/ }y?[l,V=3&i keedkl^'vWh6sbugnj٬;rRvGIOPSg4t]ajB[ |:>hq#B nz9~fy}nmXFQ!j=۩%˅2tl8\aYfrh+ ه4n'rL ,#ר׵YjmLh B[ r:7N1vWh,jہZ-?,3I6뼘lM.~Xe>!ӘOgtj=46eWNP+4r@=iDò_9Uiym3mK݅h4dR\aص=_{z8 GOꪚ}hG;{h\էj8:/*KCK l4dl>E7+SWЀ6*2Ƿ_C^L@=K^M@)v _@^M(2Ddm ZwF<2Ϋ59I4VE'h4"Tp2= ҌA}2*eBG@@dl-ZpaF!`>L8Z"fUqq4G`NQ\'ڹ(^3V:k< =]~ƺScj:θ0k204pFޓ!Å>gj"XTƪSí[Uwe? 2ݕk]UnPT-#03l=dW5E~*ܾYuge|4#&[L4[F %\,uSnuge|4#MZfYwe4jTcOU<0e4#mZcF-?+`Zf1JoVylU/F2y|Yio!г5:i= wjuVݙ2q=[RØW)E^e|5t@ݹx=eḠHcZUw&̡F2U]C9u_GMIX2Ǻ6F3{"ИpVg՝),s2k2 Y`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@1LqLE4иea/Hj4}t1{ˇ47 Ou*O׏YݗTC7TypKeTn4:%λDG'Z(7ߤMW64>1eH^(狡QfWd;QQ_(##\u\ƍ+q\fqc~2 |ޖLQ_(C1/23 7Y=2C~$YA keb༌@#\ˌyQFA Dieeb 42D(1S,Dƕe6ύ2_.˗DM Q&48/A.A :1p^չ̧8yGeD7e9֠^_\&J(Am.c^G\z)DQ_#(y kDie522e8/qU.鏨 (# ke4rer221eD L2W2d@ , 2" , 2" , 2" , 2*5ԀW!UO8L_+4sni6(O0Q>YCcb][g[BY#QX&hI2˸{joS3KzFqFK2Jn)NN]o-E_ g\MK֡LTm6Ń!_Eih}eoG{=0,,c-L'Cpj;}5p0we:Qܙ=='t{x0WhW23@r\p%AH- Dj /U" \t-Ջh,s?x1s܀{h$)[bxLiJc7,e4?x1OiJcWUjvB 4kU) ;_j0{)~liH#4vVUfwR]WE4jU VE?t.j.XYFWx24?xUSmU;[94VT;gL0U 4kU{>4JcgeiURYi|݃[*|v,zLe{U<,D8 QF3r!oEs\f71(r 2/Ay) Vgn|*2/2OѰe^Z(Rkr^f| .D ʼ22D ʼY|FQ擅Kfoe8/#(DҰp^&X gDrD ʼ2^FQ52/aLe52 Q42/a^&Bc'2K-Cy- KiX8/AFƖ!ʼQ4, 222/Ay) e58/㯑e2Ay) 2sP/e2 hq_@eD`X@eD`X@eD`X@gWKqsX5p^a9p:jM8Җ(,YW*5J㖲(dr̃I=4x̧l2PY~wddj i`6noƅ[,3i]$cY=(vO9֞jA;>B 5^< {#erIu|VЛҽQ)4@S3Š;24!5_^U}Y{䡊lhVI?GOweh',,S9վt5B?P T;hxPUwmt]U|#Uji27s%s$(o2 .)@7c]DmF,x<`x#H5fgAi2H^T~7D:j4m>҈ed"z\@m3ݺtzb^h,e0l2E]Ac ]*zq9^TM{SKγ|2?m`>kTnHTӠO?ك%zcKvh-/ԪrCjXIׄژj> %АR=b=ZbS#f%:[*}g_oiq2iɝW!^aXXx$s^Wۃ*13KYV$=˹&'iԪ?5s&cK| _so7it%4,o2eƋh܋7i{;~7۴ @0Y[f:BX u,Fw)Ƌ2n[X4cxѼƫ2-=:Q_gQD\4yFQ+{HhĎDGQ\:Sރj=9Q#Vֿke _2CGip 4ֈ=w$#1eZjL0AIh=Ojʞ;2ӿaމxkB@#VW#Vܑh۴[_xe&GxjDʞ;#16-W_=Q8U+U+{HjČD#U++\朑Ո2іyuz *2gF-Uiu_f]ZYA_ֹ#5Z, , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , [8&"hUò?9%ZoHxpKqč4ao|c1ƏHُnY1$Z}pKq?7HqpKe[kSiyQSM>l>2{UwDGDtDG˼A!ـ(EsO>|L|{(Sson>&2 L[>[1ie5.2?^1cQ\K#\2"2/M=q5eS2ܧ׉ ^48/A׸|:(C.P#\2"2/Q;|23 rD&p^&r༌ KkdereN2^S\&@#(CL02/yD(dr^fQ/sW.ُ kp^FLF. eDe^Z#({.1k5z2 kP/#\&\#\2"h!_@eD`X@eD`X@eD`X@!L˨֨ DC;d=62k2rtHiF{4e"%4u% ([ʢhDJ!"d:kaUeFg/eOUPM/g .ΖEپRyJq귝CuQ n|afD}e{sf"kFYtBCd^lV- hhk^4e1pߌh:dǬÓrVӳ9],ƍv wY ڍ|IW`"4~3"Ve*=6uiym 4YeIhۺu]tP>Yuy63f9_o*7ӲT6߶,W`1ݿ5#4.yqĬyo5aq~0.K!hm;m,؝ή)}gDFBsh5nW*g ^n׶/K-@ßAIifD`-6a(TFnze.0(vZ.!mm;4~3"FC j8Nݝ3i#|=PWU~՝v7f$6z0~3"FeNǼ+chQ^gh`4u5 OЂ^Kˠ /&-5fgBR14rTtMv~# X_ƽ澈-c32z A]fa_/Xfs_Ė6kdy-& kk`2t~ >exU%qB_/X#t`d}909GU;0\#y_o_FH4&V*V 5XJX ߚFdv.SXĘI_[60_,.LekTnbG&}__zF?P(<)5PH10g'-_{xnRiF(}D/q^ȤѐGH ,,DW1WzELꚿ I_zD LW2ߵ/W|2wU#2}kȉL-sߚ<5r"SeD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`s$QDjXgD#i;FqzL6<9&}H;e~-xHR>e>lDv{t&kdH ƼDGndӢ +ide!yeQ"odS8 sF QgDH."(C.AA.2(# kyŝ2kdee" 422QD eἌ@(y(̢/YkDiked˼F6 e"^FAx22&ʐD@.# kDie5.2 2 e422hDiked˼F6 e" 42/q^zgkdee" 422QDLe2 hq_@eD`X@eD`X@eD`X@g;>Q\w҂Fٜ2)L(C-FMK@#PlM4RZ24AY&i hDyt/bXƎXeke"G+TRwu bwhQ6Y~˴nGtƨr  fcMOUeLת ~2(۫z1F/Ui4V;rq!ACyo~6^\ði{bgs7ZB>OhwmF{l{uJ7i/D8h41M0,,&U/ouS,sUƣCDiq >?pXps+59r>^ZðLL7yLyWojp 1' D6 fY=u۹lctVU3}PjXx 21i:GF5݉4.Ϩ&VpQFitxGo}5  ocpbp_YòL5 ^WMU1hxY6p\phcޏl1/aXXV9n씪ꏇuvzʼOWop4,inOeƅ fc j^uLϴy Ǖe^5ⶐhe4}X:42:?ȜQv'[e49ӳ4d2Ddj1rhe[gk>.DjNq *M̄]԰ .BxXA`-n/D^Q}F+as+/ ioe N@ 9űQűcŧR梖hr-s72Ebh؋PO)+q+>ϝA~$_˄a@$YűQűϩhrm"-!MLPQ2APCvbqlgq$1>hr5!MLPQ2J3c#4|c 36MC5ݿIiM# iI86T÷8֕h<MeԈ2bH5"@ó86n=Y; Ԉ2b5ėևgqlC?*>sŸ鏛я5T6ly22ZNBó86Jϩhr6!M2J$Ҋe\TQg*+4 [EhW|BÐen^TngB+4-, 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2" , 2")Iwհ,,V|\m>&4;;n1F6-ƻ#γ_|~pK5DiHܒY/>߽33n2۰̻wEK/ؽ2724r2FQ`v\f71(1)#\sjWE0>23̅23r<<<)0~Girk|psj~WeFQ\El"}!ո{H#(xkder;/3foe9 58/A2lƃ2dU# @@#;aqye522kd3DV\_(Cveyy.Ce521p^Fxp^&lj2Dh\;睗^&ljWϩ98P/㯑xP/A6[5r L ٝnk9L& 4а2" , 2" , 2" , 2",j=N0MbhgsO0UjTh-NiFjp0`LZ.<2,52nc|iMi݄u4 :,OHeB?h~?AmڼR@ BðLvLe9~#4{na^f6 ܅@ BðLFqTWj9(x!\7i7 Ɠ5pakpa>Im.x}B|xefi^6%l :<2Z; .ϨbS+4K{^ gk 2WFM9:SafuUh )6oh<]#Wh✉jQfNWh+46gƅPЈH7q%s 42vۢma@#s˔~-h$#s/YC-7dƔi/U[0X^P}vpҤm {j+<5ɿ~Ԉe Փ,a?ҌZpF0[ow?~8̦CIس|ۃ+*O*qԈ&ox+65cd_js.:p ZsVڝx[ +]%!!q+ڌS4iN Ue`>uU;gZzѭjPO( ;Q=L)=Jóߏ[fU6MZqnGCǕͺ՝ӳޅrѭjPO( #⑆F0kS~#q}&phtމyVnUz GiB\0kS~#Xf*4{MefX.2TwխLF]xFk)eGhx,3MlYoQ kA~<;e5jca  S~#٬hm&Bsz)vU3ןUz kY`;ʤpHuEpP)㎘=h;g=2VS8XCpazzST_y[&]k$*XYTMEEM;p%i8L󑮪C5eqz)<{+ijHͳۻ|eYTb^pWѦT غlsK'JReD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@eD`X@21I@e>{޽lv ?6i?"~DHQH_|o>/޵b<,2%Z~HypKeK}pK5 lwO?VUsvKe_R(=]=]iIe޿߽ef6ݓE/ؽeideo'DՍ(b'ټ21V 5Qf/}z,Mp_eideE.,T2v48B/ e$ 2X@H` , e$ 2X@be{)֯T/K5d:CLRSEh3ᡩ+3ۍ~3qghX Zq 8ǟLi4,XS->ùY|"eӰ-S$]ƻj.Ϩy3f;Uw`4,ӯqTqg܉~8W7Pò5/S_Y6=;Ҩ)kJSvd;WrϚ+c&zTx[kX6,ә5f 4ޏ;L*xqE]N ƻx/3483nw]xJLsW)j?vH0j,]6- {dTSa1gXW)mwǎ> >#[f%2j$IɌ'; m,; *nX-jfZkCm_*.HJې 7/'m'4YywYa hDtϝeʶp*۬^mEFݿmϕmQgoI ְKf }'˙e/Ooj`=w*ۖ<~%?p[ʊnWӅaS-E%\aĥvIFROV5e`v=\(Vyl^gkt}%]ƺky^˄kD0 ׈@>5߫TSCMP'2cesQ<Ԩ XcU^VkEQlvܢ7%L#O:܁|嵌OCP >M%n5a'3z }Y24~GH0> ηᨪ4"g#V?V5}CcAMf8e5R6#P#O*~c|k]dc(`FϘP6l-sh˼Mu|7y&E/pѸe2e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H`e}(ƫj8Vwwn6{dc&k_ۼs{d,fڴ?-es{!}1?}s{ ]ncڟn޳E.x"v!,4N2cNyq(}e6o.\%ف\fq(c>Kyq(gYf_Fye6rLL DA\4e ոLa^&EQk2De4e5.eeR4.ee^q\yPDe\gQ4.e x(üLLL DA\4e ոLa^&EBQzp0/A.A.QF y* eseB5.eIѸXa^&\m 2A22)e rp\6a^&T2Qy Fe^LLL DA\4e ոLyzB;h2X@H` , e$ 2X@H` , `N:AK#[}:A;2he4_ Nj hأjXV1*lc?MhۙA]M hW2ٵP4hѣVؔ6{'34+Jb*cm6S]sjaڵKvCN(4S1C'34,wʪ5װ?[|19Q9aeG(4|=کY ˝eF{β %{HPEV=:X ˦e{ 84M?m2iL1J/UB\28'2Y0/$ѿd"ACe.L$pş2ܐ2ܐ2ܐ2ܐ*@BLy4q;14bx1dj|w|qs'C6 2kk W%k+wl}K#;9̪nU-iAS:(icLI=1al"S x4c{7FrYFiһ1X[WV nƥf,{ #FN 7Ngki8 c4#p =El}^=4mj^gVmʊ452CRg-axҁYqZ{Cc9D#;Kغך2jۼ^=_6\P/x {đmGfb86"P#;K̾tLzv[ӑsX ŗΓk¤tQqbI쌡lݱ2^oҨܾ!e_(Lur11jI쌡i$wCm8ZjҨ GlC<KJ?JCm=}8ps"ᵮ01gkƏѡDy+LG!bGi zeElpvU4e敟bɖy$eۡ5~Fxܿ#FpN2{؆=Uj3N?2oԪ*?W:&Czq6~#79<2X@HP e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H`e}(ƫj8V6Ȥ=2i|smWysi\?[.o|ߘZ;l]߶O/d[.|=Ƨ{Ic1?e܎̧W;O^(m_/|ze~{&bQ挽څ%Q*ΧXf E 2kGysJ! ָxګ˄kǬQf̞<\Fp{OqeBq(scs 22)B! ʤp(s\(üL<2U(ew>fxNYhˤA.LLo2/㙏<\F`^N\&I(üLƹ 222oe ׸P.3_~{y;e5 ָpʱ) ˯e.0/q(C.LLoS/#A.ALţω2˄jˤ@A.AI 8'0/q ʤp(CLƅsB;h2X@H` , e$ 2X@H` , e4*%]29 8C#ÿL5C5*+Q*aiDDiÿLiR;0) s`[e[3˱2ڏw~87'X&2n_cjqߔ6{'34Coo-Lr>vAN h5`o-wxZXwn.ŧL2Ӡo\E|Lu ާƫOL]<0 hjSȝ/iԅowQ!\0xM~ z. #˸ִ}QgU7|=[kqOɖ װqvF3~ݦ\Si8Yvc,_cjo,%[&\&2Y װC&3ŷVwe[xYj6O=ꖱaصMMue5"Iَ[iTQuWegS;|݁SOḴel+ca24sa6%L~,*^FcGӧJñmQ$pFbrŒ Hڐ0&*~c Ot֘fz[j{>9nV3 hbrAchJhbyBtnӇz. 2pfl3$l; їM䆒[mm,Q'iv'$b!J_wMLO=M,3qf w-sh'nwoqnI4%fI834ij[-[z <qQFTŬz`*TD\1kU̪rc M^^5*fזL?<*ՎKAttv5+ $Л:"4*f.&p"6w 5 /$zQ7y,GiDT.-]c,.\sW#X|`FR <#75]I242FD2k}*bj]M- H*gz} (˨-/M5 wyV 9T"-#iDU[6iait#?YPzW1e5nS[wXaD+13ިu8Hqc*58%Uw+0L9Lgv}@6òсyBIC[_vK. p`+a9K[y;3fe^SֈJfx+D4 ;"8.uaXΧ ;*C2T[$+C2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ XZ'"hcei>G&oqƗ/[.=[kl3m?s{%|i2sˤ߹es?Ls#<82_cIO<_=[ؼgh`AC( keRL9%˄kˤh,&ie4&|߇?R̐xe>L.>wveJ[YK݌ Ӿa?R޺<}JTv4J׽m)@CBi,clcV¹K5BSuL o4:;ݶuoZenZ]rӛOs7ZsqzF#i8ֿ0ӫq݋u}TA<|*34l5 C P>''px-c[NU,{_ŧM;Tc0XF54C⛗;mj35ڬLO 1;_i<  h͕z~ o`4@2h+N,wbK#Ѐ{e59$/T;gsM wQz|s ^pE-..IV /^]yy(z/qP/lXC}nKh)Sn{do5 ̓5"g[b/jգ4s kDG㾻͖,v.S2њ.4 4Qc0X%X&L#Z \#}8^㮻[LLIg̪ƭv[ae=TOHkZD<>_YFa(ۡ1}8Ec[3,ksXf8o=+7ʝtEB:b^m@zq m|)EcݳKqԐ'L^;L/9Nc2.fmD\MO^wƾeNO 8C~fUqIyTÛhӰݯNJre$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H`e}(ƫj8V6~I?IK_޹e?1ƿ#o3i|׿{̟2mڟ-esˤ/عese2iߎ̟dg'91w(/o3itd7*n(ci8]Lٸei% IDATe52o_<(s|.rN!yA hxd 2e1ƝRK\YM] V/POg mհ=Î5[Xg+ re 3tM]Ayk6䆾Qb3gfK##0d y5=Q2üǕtghX.5լv˸Xs7ghV03wϨQ#۱)4E؜3gJZ8 2ݮ-۪S`gf}FΤQͣQjgShTi=>?2iXֹخA<֘aO#Vjj~oDIvӳ4z1F7VjJfBaY1Ny-3n}h0^zţM;Z~=mdϬ>_ʧRmew6ˬ|Z$߼L]Uݹm{,Z}w'M^ &1L3ۻO"Reiԛ)[pV[mϧՍBayW2 ihnOy0F~9] {LҢq.t=ZƝ =*x44% ayH̳Krxf(d+E_-r%t\ue%ӓTQcU`e%ӓTW_*>0]#w<=Iy5wL?/K C s%d/'p ̾fk8zw8Ǘ^OO@- 2J|Dj^`WermmZΒ?xz7e"_<2YK[;L(HЮjI__|QSLS6Zf;eD` L 2Dr-^2U92\12{D72_"=>#Bms?[ŗ?#he52) 0/{e2D72_X/eΚ,4I ʄke4eZyE33,Wd(|љ%FfecZeMݯq̩}ƸI̘0N]uwL~˒ceV)TejØͤh`7um։n@ݪ&[X5Rٰ?)6 rc@6иukĺTkr쏻}=[DC5`z?M]a8w[tFFяC4^B#+zT>z)LL¶iyi9Nf8jhs?ǟJ/>zF=M*V8ќa6:fpwﳥܖp'eUuGUF6ʓјX/MB#w+zhQ#~tϘ~c9˴49ΘaJl9 ҄gnS_OK4KqYƞܶk$vwzj?R Mepg˅o$ !0qǥTHusD! *pEkkȖC|X;G#P,WGT"[$#C2jXjp'34BŲ|=72D Del ^ P}S4Ԟ~ճզQ 9q? ^ PӈM#g.2lz1` W4zFo+̜-k\tms*@m;zFn+,3oݚ9wD;&HX*UvDVX\ :࢖JU4E-s*h\Z2UWѸW A` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@bib,he>GMW{d=^HȤ{{K4wn4oǒTk{MԿڹp?ع2i۹eseٹ]"|j_>jQUm3iqL̖8olQxFQfA ʤ@.#hlr24ܰO]?eD2CsJϏeRF1ʼU.>o=Z9(AI\F8}^fr0/z$yA he5Κ_*a^&A $ib3"2$i,:f8e52)0/h0/ֹgVy 2D` L 22<=2D] 2˄k0/QF ʄk\?ʐh0/Lie4`^&\2˄ke52)P/+2D Q&Zzp eR Dp L)9#1/F2v48B/ e$ 2X@H` , e$ 2X@y7DBjYeMߙo!T&@#2mɲ8\Dr2̓?Z|RV-Ӝ0Drre졖A͘چƥv_KM4\,2V˹%e S{?4 ӭue{/?34nw1Eu +Ta^ivIusK{n:I6yWQ[zε5Vgа,-S9!t*Խӷ5nqkw9/;DF8n ]i|i/̌}5gXZf0QÝ,T7v6ue  YcŰGf4MnOMA2clSդ34,3К- XjGhհg4yw'45ߴ}[ 2AV=UwX4:.~)4T(g+jϯ;cV3C+%Ҽ=Dq[,v3!iTJ/aY˔H3IuOKS+F"mh`[i۰{$5k̆s9C1%0hge3iRw)p+˔]qG8diTקk`SRAًdnxLKPH]ax~"9K7k [&xW_Q_~?Svd[{FL7,eapR/2=PN};*$"Rb쳫6N>b ՈwUijob-i]jEFTe13ӡ1ݰږYUy]!>KLF]\{nG̦(qETe,@#\2*aWշϩQǝU4d5";͋re, .m_%vJxjDE#HVo\ftK8)̼ʳ M_T[&L#Aڎ"YbZ\;e"Wid)9eb{wxeߝ[M۹vn4zwo,'54[.|s^>=pn=[6ecrEO`2eI(qS|w# E.2 kG2W2ey}<sY1Í(иvL.üLe1DLQ&Ss By rh e52)\*ļure5.ee5e ԸJ.CL DAzpkG2˄i\^z rp L WeI(#hl1i\;\&ļ 2Dh rp L WeI(#hP/q(s\y0 \@  2X@H` , e$ 2X@H`M˥MKBsx@#qM]T&u! 证FayXqܨ4JWBD[hj gGSQZE%,Ӝ0и'|87%Ybkm[oQcY3Op׮1vSk(c<_45Ee5:nKrYXǶ5vHGG(g)&+}_45:?qkG]3*5St?eR4{ nEͰ{k:@(qMӊb㛷á0K?ýkst'jtG|Mm+] eQ/o[F0tc5g_9QbZ|TIFHp-ތLF]t;([͙]M+WaY[2Șa kތLF]Ls;p]b4MUtƣ:+Y#^ eEuzSD7QFG㺫* G٩tZ,}Ao*谍Z+Fʪ~f&;3-iI+L܎JowlBoԋ;3R:H:V4θ$Z&M#80q;:+޳e񗎠qqޏeK h;L$/;zUh\wd` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@bib,hevL=2i˿|/LI?w>PfLoveoZ;l]nsY擝[&x2sˤWwn4nٹes;2^oh+{(\ƫqFe6a^&Zyp eR 4e5e4 ׸J.üLQ&\(ALw>zoI\F ʄk$i\q^zG$he5`^&Zyp eR 4e5e4 ׸J.üLQ&\(q(CLu LQ&\(q(sy Y2oP/s_hG#42X@H` , e$ 2X@H` , e$V/]-=f.>Kc^5,QV!FK5r5$OeKe#5,&2["4ޗ%2ݓ"Y OaYS/l_nbJeіqhL5R6wh;fi#V}cS?ox}MQMeLn\^< IDAT9ᶡ42jXgkW|2n MvKk4v)\ݳfz}F7 |ݩIjX,c:T7oֲ 12bӳGx3 wa 6|7, oa"ְx2Oj;o׺,N Gh?lig\ǏoإH ȩut ˻ysߒcFLh\2nxr7x[ 4.n;@M4*[9Zq'7x "Gq-Zf:ͦch(E} ,`t%ia5$iͦV70#,pnR4utZ7jnpl][~?c?׊)ż(q"8\7`86~Fhope˸fܥ 9ix*3>؜)Z7VuZ} LF)Z7VA\PQ ^]FjÅ-fUO 3 a0+3>-X&RێкĶ kZGnm8࢖8 , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2>Y@U5+6#?Ive?gc.=2i|eL#Ə~}<2=Ӧ}voWL-eZcI[_ٹe{.܈24Ή2ϛwB(>xF[(y{!˜eo/eN80#ʤhbY\*e2YFJ7C5*+Q&IUU94r2[{ot2qݭ}m~>*?Nd[STYT0(4k?R[q ܡR٭*u,?Ԑˆe a{ff\Ih h쒋œlm_nz麈i( Di4Q7uTjUX&HCl~TYs gI=Cc\E9ƏZƍv=.Ұ Bi8o)5|ó[˄io6Ln_434Ute 1)vY)aQ!aɄ֚VY0 }cS4ULs/ێvZTCڤvQjꦨxP?,Su;,CL۸Rؿ qSmmҌb~WըM%oQ _?XLkppƸ*d݉ՈF3qqS%r|6h l1o [j34ULNt?ҟFeEE&&tѿ,DZV=YP#ٚi[4ltd*)A(1E=NB_H:Nps+FkR[ki㳺"֨kD=W2{Lhdhd K*qz K :I#D#v_e2ew\xF"#52~M42/a:06 qb_ liܨٴLۜh˼L@Vb-:YLu-K@V֖9/B#hV9/BC.8e,5?Y_y\!ݕz-s`񟪡79O s;cvT2\Xj8 <\ e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ XZ'"hceiӾG&_zKcLg|{?Uwկ2jb2eIc1Τ_rYÝ[&?عPؾei׿׳{(#̇}{sEk_os^Veq?4l߈2 LQ&rA\f|x3/sϝ\Q&\(Q濬e1_njQf3!YhU.>o=eDp L 2IEe~\Q&\(q(3YF>üBʹ 2Dp L 2I?9/3-e@422C 2!2[̏Vy 2wDp L 2IEeI ʄke4.e `^&Z(AI\F8)^F\&Z(AIzAc32k e42D rx2կ ʄke4.e `^&Z(AI\F8)^F_G  , e$ 2X@H` , e$ 2.2^Bkk-SR5Z%Acwjˆ:`iStr.*+,s9u5'X&2T6T~:Kw8.5M6<252pc1nV1;_4nw1E_?i,u`א]Jh(ú|j:rk~ƣŽ_Fx* fii^&x&@4ht lEА5ԕ)fYqik~nx* z^lHNŏI}VWU$^m5sv1Ǐ[fKx*a@#ԕe!^24ޟƓ|,+˔^*xEwY+נ4kР*@Zȵ85޹eqp.32 CdWuqYS=[_ƶp6%]6X:٥%N6b8}k}.,s.gFz|F%L,u{9Wj]2NvWPo^xQNZ'Vu }E-S橻roQ_d@C5d4d}(ACZf|T"u}"!p;jk$z+<3QG[Z_q`a ,P#N6D#Nv3shH}N-S`;If>t;nyW#Nvm }!;92VN<\'Z';ki(ZCaoY2^$0:JVxfh uއen"YgN4eَ:Jj-_g>ԐXf*[~fGNmH lTxf8 .j2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H,-SE 4^Uñ̏~y3m{dڹ#OȤGt?>fٹҰxe>ڹeڴ?عes?ehq2ܹe2i9d_?߹g.lF٢?=_i?ΖQm0ټ2ڼeie52\fN.ԸN.c+Ey\*eie52o5?y2}eWe~N.A42o|/srure2Dp G7`<̐ =/s?3,0/,eEe$2Dp Ge2e1s# LQFyx e51?eeR42D e50/#@ ʄk\8P/#hP/L DA(LLf2je52k0/ᝏ! (#he5`^ze Dke5.e4|1x5I(#he5I X/<_G  , e$ 2X@H` , e$ 2^TKw/ =2]g v^f 94*y,s hhhv3 Ј*)mg 5.=4uaf3}u*}Bl4MXrh¦YrIv^cJ#X4а,cZiE\U,/T4bp4]aQu[אiǏ4~-S<4а,-㚬5nɍ}~Íw9C[;}bH+p EcdziaYŒ{(\Wfu{#ô$}34l\mn7: P,FAghXaqkT,s0pGܚU4 8Cⵌ)`Qeո׎U$ Mc=M1Az+ :gK؏tyFTj [7^+ahh}Sߧqeu5Δ]5=oT-q8;;bHFCӘ #`iaU՝ɶ'¡ڏ5grF͝Kj;DC՘8iq%J,oQfՠn-6M>M5fЀ˔]qw9C9&4.MāY5aɟcAP \/M\>C^W*e,9>rW'\qCp932Y:Y8di2]wC](|x֛??6ΰ9:C̽AKߴF]T5`WҤ/]$Ȅh^ە_R.gq̱8oV鶮ߛW*n%Vk1^]bXKR/PLAiH4Ocٿc7m,h$uFfUH,!Ju-H0a'%5lF֮Ru9z&vKipC5?ZCh~Ʋ_=UJ۪~o^_if5\[fUiX?/5k) հqKj(ט1zE#3z62;`v۴uO !afwXܦ2 0pP߯1prJLF|glVe=mqFŏAN7[fKNEߎM Ӑ߯1C/P^4R:g*Y=Oצ>!0hmT-Q'ײw{$2]{$,52D4 `^&I(A ָR.üL8ke52)L2>YhĘeV1se@42׎22g 9[\1ke52)0/#h0/LQ&\(A.q\yp keR^FИeh0/A hDk\)ae^&^(AIyAyp e42D rh+2˄üLQ&X(2Ny\2v48B/ e$ 2X@H` , e$ 2X@beH*rƮkl_|34,+T#v8^ ]=bW(]FsFe%JUBn&|(^2>vpgh<6Һ1=e6x7iVyrL/`>ٜ`eʍGQ^o쫅S%hĵlJFit:2QMs)e3|-Ӎ6ϻeS$e k7BY٩f8t9Gö\.IvZZH*ʱX6#N.[EUcjZ[ghXin6r4nĭFBRL= M 4cvχZw.9;CLԷH9ԕmqFVcv4sLRQ0 >aa23Q,3<̇X~ 4,a҆lfjl 6.o,$%(` IDAT#Cڔj W0I qڦEi4Z#Fe<.234,{龄Y ܹQߡUT: &h]v_8cVe,3~ ghXv-Lj8h)y,|HL? I21{QVbJixnMU-p434,\ O@cS4 <^tWӜpa> ,o6UX@B̻)%We"$T`#;f6"jc9oh 3Z?6j$ZޅUJǯqӊTnƮaf^gX7UOEwhEܘێ+ fKxEC]rwTgT7UO޴;4?xn{=ts}_J.̲o,қUOC4Ģ?xrle}77^/R,#j(K5%\ e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ XZ'"hceiӾG&O~'7Lߵ+O4~u7cW4Y5>-غꢿܹe';\[.-W|sk8[\^?e/{5?-|=FO64G}L27B(c~AyY?M(3+3-[|s 2eeie5e4 l19 LV.UcrQ&\cW~A.qV.üL2a^2Dp r<ˬ5e5:a^Q&\c'Ɛ<\yae<3/e1Ý\Q&\\Fyh rp+2?r^fHYhe5eR8+a^&Pc0/rh LL fUe2$ie5e4˜2/CL9 2 Dp r e5e5C.CC L"P/#rV.üL2a^2Dp r<ˬ5e5:a^Q&\c'Ɛ<\ye4eޤ^"ЎGh8e$ 2X@H` , e$ 2X@H,}t˧8chOnxF 7C5*+QFKU#v3Fj/2ݻM&QN+sF #5,&eR>@#Z9295g6{]%Ȅhk8xrh$7;^6i5nw[u V7^[eS-//&5L-MseZk_nXnӫd ǝe;nfùk7ܵW*}FU4Nݶ[p+o]ØbjJIc4g)Gר `:j i ǝej'Y.s!3_$pFe7B;L=ШaKQf4y-!7\"kw/uƸƙoZy5]֕IL)eQaN-2zer YNh@,*͆ =64IfF])Zvț"jTw }xZ~#,Ոh4˴cYhmT5㸫12FqWԨMę Q춻͏O#wefBm}gh ӵՐvv$2F4X<l1z+܉>(O2 =W,-Pp`x&֖W_m!eT2Lp%32X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@H` , e$ 2X@bib,he[M`L4~G}<ȤW?ve3qsGٺ6/4Ý[&ssflKvngDV~(aʻ|Q{&y|T6e>`J!kĘ*Q\4ev Ey2eˇ\(ԸJ|.31GBc3e>>,4e4222Oq 2 Dp r L2a2)W22)\*ᙏvǐx5e.0/LL 2U2\F2QHv 2!0/A ָ|.3cfω2w˄iˤ@.#h\%0/¥($he5e4`^&\\&rA*Q\&DS"٩2Ǘ2$he5e42I˄iˤ@.#h\%ʐˤp(s2ƛ\@  2X@H` , e$ 2X@H`[&UhDӘ܌g5а,9$wɼ}/>ԮQM;̡ghXB-S7dv`+jl:eװZ{#J \Qc34,K˴-n.KMK|[ŲL#+ݒ]{e:Kha;ظm{4eiU<e>m~7Ў =cckK:K/_78Vjv7ք]tKCR9C=0#J'ӏ~o̦F2HT]׶;q]o7moN/q|8[]Pqb ?itbgsxfSLV2}j̇{H^e{TXy,q<{4yH 1[zաvRy[STcR[D5ezhd Uf8|; U&lcoTekϩ2SFIؗ_~c2{TY?2,Rex}Ol8h,e>՗,9;210.#8nSecepܥʜ<.gTE_q-} eeTf2ݵ}|*øqxLw/K9/ø'ce&2eeT2̗*#8/qa\q*C_&/qa6U2Pee72̗wܦܼ/|/}U&em e";n\ewܦܼ/ø*em}/q/ Ad$  2D@H " Ad$  2D@bda)g8R~e8fɲ(̡s!t#w37CUom*|RP׵Ȭ9L:c \uUTG19:{bwa{Uۯ8 2av"SM~pLds,uכ'7dKxeG)}(M!(,6/C맍LCk4"F%/s[4g*M/3F2 s TG57GCVT+Lӭ1ݝG怆ph x mžZjpGp,ף}A'fҶRVTXg! f;2#nuQ'1kJ~ħ=~$02 [z #BH7fbC[3>1$_rL8ſ0ǑrM[d0T|"SD#hDV"L[d:4"ӞSJF}ȼ%Ỵh6o-/jdkS&d"[ ^ Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ F&&:xD'[$rnD~T㫖E2Ǐ^Nol\REÍK{׮?޸m\9ՍK޻vM|cv GqQpVd>TVת2__^LkJsdB8N252e+Usɾ*i_Ǘ2ˌ/OV,^ЗwЗY_?g?p 2st\frKsܴ/s*sUi
    Jd yT="#Ԛo]#>>ULÞv{nUfywˬd&aRܽћ,{O~wb8LfWpWh[PG1.i,qR |= w9n5[o7x }@pHٲk=Q##Tfr;7_e]o_!14۴ $D88Yi͉kovk66un9+,t o϶"^pD8ZsUyjٿ#Y,2n~mvg<>6>류jԿppZss(?A.wq&7+r\eo9w"p<2p'qu{dsčY9Dfң KM%D%foB59u_c:{=942>LvBccoM#2T B@[rȄM*=!M ^qtɱ䮑 TC{KnIr_FvC]'ޒFF990ɱAar-mdϗ'|f?96b=;;GFsy='dž;;F&d§y_zO w<&w7 Q " Ad$  2D@H "VZx IDAT Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ɶIbā,2?"ѪBo=Oo9~E"'?޸5Y}OVڝK"7qIqIO6.[1UfqJzMWe֔oDhk5U5:k"?,ܦ:rB;21ܦʜRNebp}o0=f\fqʉUA6UJvZ_20.x;21ܦ0_qqx;2L 2T2e70_AwPeT_3.`L eUAr3*}L*p*|ǭe/x;21ܦʜRvQ_&# " Ad$  2D@H " Ad$  2L_Ǒ3dI"S9 ySI+}].M:ّN*x!"S4ŤY:\رUšNܦ%8oF?͊\ۢϻAu®Ûq[Yv䢣 Kf>cLYؕOԏ}#{f [Q=*}:\mk[1 ܉{he#e?G"cgn=C{fϺJ紕4bqU~y`GyZG6]][z>yPUsJJN̚R= գy\+k܎k\].<~[min/0pӴg}lG>vT^fxe4o[+3ۢliƽa2TK;:(3TG"0i;wY-M1y[:.<hGSǯ & ёuC!]hhؽ&Eލ0znoGo# m:ƒ2uPݿ~@>*&s}Ba=xmCv7~T)qT~Rm0q Crp35+U<>(betn;Se_ _9Wۛ;BL3ҿ!'| @b" AdZ7N% "c9x2%z297n82ɀ¼ɀW{7nug~9&876!͍%7<4`'lY^|}V_lԘ_*}LXd ̤?bΎLUMK?:Lp\Ȍv+5[*;jraT@G_u(qGUީ Sև'V ݟX0`|td^4RF u(YmiL~rӜ5TqohK}1TGU(DU3{R畃hxC9;K :jS3idf+(U=Bc"3Ycr2^P#'m@>M]56/L"R 3~\Ǡ:LnE|h:0<wOCi)˞޾odv 3{:n0]c"(33_0>9XLo}\"(?@n0UG|6'!vS?42m-ϊNKϩx:BW|wFiZo+onSv ݝp8fdg)F)m~B?x<- :樤`zH^S">:aosN}][*φ ?#t~n^'OCjm%lv֯11_9b-T"/;c[AdEț~; šJ9 8|, G&w"/۝)iJ DN owgiJlC3pGk3crxܜ*N/{8)k8d>yΥLO @ޟ5}q;:Ed<SbW 2p[v?Nqb}}E8)+8l6]`>ƤChE?cM֗v O?1v$Z@d /Y1hvq]6%v" Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ F&&:|gD-9uDo}_oS9H-9To׿qIh]/6˗T5?ظ$rl% UfqN]Re&8c6{W˅"sRYPe&LȌʷfu*3uҗY|wڪt{L_22L%56eYЗف-ߚcE_fD9Ω2:qA_ArЗw/0y|ĸLwe\2qU&qJdc׫2ˌ/|x{ЗvPebMQ_q23̷5Re&L*øqeT(})U2З;2QS"4=L0_FuܨЗtPeehЗ w0_AFUq_210.#8;2Q2Y&/}p2L 2̗w>.s|v8p8e$  2D@H " Ad$  2D@H ek]F=9r7E:QXE~VU©&\ɛ\J vTEFn:hG8,"3ex{͗|90yyvsVI-;JȎw)0 vKiydb1e}}_>SSNp4K~TywjmlD;í\ͺw09x{Ϋ=&L;TE͛XQwl +֭z}YrmmI#lQ၎n$[kXv/2'O=ޱ|ȸwe^^So36Gl8DsΝ;āåZeѽ"+o(ca雾,8nIn#~yiO6&3)zi{'AfC[k3׷_kA+o(cv"S.ű9/<킊#"(gLێr8آ#I{ݫw"ۑIn4{ldptK&Yp>]u=qvz96Fα|Lh{>âfs:.9-&:D-G5v9?c3.ɽQM+o(cggj$~d4 u_泹r.idU^ۊI>1[s~9xF{:$r5|\&o?6B;Cݻ~ 7n9b0QLJe^ӿ9/ 3}U\=ޙ8G@d\@|^G&oqppȸyxwHEHd.8 |@T2: Ȍf6Ñp> @Rfb;j>#|@"3v|@Gy6>d,#z8H<2YlGpžLϘ*/'fEpxAeYl z8D^ Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ F&&:-"=q"%㟷Hog\?l>>.2KUl\REWD4޸$r/o\9TxBs/TUX2jG X2wLT=UAѸie&eT=UAخ2^ʜ֗=N[e>Z/3qЗrPeTe[2}2}6ReTUFUF21 }L*/`\&AwPe4̇a*ᬶ|ʜޗ0.3qЗ*#822Q;חaL*hܴh\y<{L_f/;272;חa\&AwPe4/`L TAwFp_2e/;2727aL*hܴ0.O_Menq8 2D@H " Ad$  2D@H " BK:<^qD}>Œ oK਩7ҳ6"Qkj#ޛ}Lߞ[DW&pXLpd~X;A#͖Hబ4'=79*2͝&2ʆ *)|ᎦBO0={ XoO6{o2]]jwgy5g߁1e}VUo/n-2͔p> ݨR9ԱjH}YduvU͚*6l/^|ܫVtK{^d3+[|޸wd")Zs7#frxnMɳ>y|==|տbxwHL:ZdW7nv7y^.aDQ H٣}_q7ٱ^ֽjzo8o=j|9LXtLdƧ+ α$=7YLDW/md?I`xEsSzxJcI6{{ow\_I)Fprp gqHjEG2nzE>ם-{WVSs9&jFV6,<^ U##;w`F[ѯ:mpGeӺ)׵+^ޛKR,Z ǣ{f1ڽ FFuT^h;26{C,˔]v~F?|_==[8YnTG3cl~XoSZx-T(izl5@*w6{CHdlj8s qbow"&D M Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ɶIbā,2?"Ѫ}_m"gְtʱE"O/x-9~ERO~x{\dD_۸$r|%Ud~qIٸ$rW7.v~zM*mMѵy5]|jwzMh5]녪Oښx92s 'foVeˌ/;Ϥgk2W2g;T`U1]~;ܥ-}mAY^_櫋שeT} ex;0.;XtW2sd,fz}q?fx|*C_&AwЗxqxLwMٗ|qF__feU&Awܻ/øq}2>UL8eT2e̗wЗ*#8Se˄||r8221ܪ/øL Tq*C_&e2q@Ueb1_A_&O/ee^/!/ Ad$  2D@H " Ad$  2D@b52fu_>au.`RʏpF0N>#*o-=#޻ĬWN\'Gf화k84wYB罆ccW^gY٪M][*:\-[U[̝R~eE̲q m^efk*ok[VLWsXf)Wm Y?*MjLU&Q?qtڪ=saHѵyцYvesv+}ZpX",5o7X7]Gg1Id *wȧق=hP]SM=&xG 1u3;K5 ^ݼ7jr_Pp̌G|W7LsIsW7LޜxcǝG}bhp_1+@һ8UKpXnv5G%ufɮ=G66̔aCV<s!݃qY{sXHy,<<ƑMx%; /hFcg~0Ha ͒gG6s=k-ݓR7s242id|fF?qYfYN<<ΒmFgv{,fw#8B涑n_3.̾d&3ef#a#OGhۼ KL(3&/e8͒fGwvEddm"H4Q,jU:"涑ٟ/x84Kv9ڝ'ۓ,.2ގչmdg~Gfۑ{w%;̎'a442mdg~GfQQ+͒fG)vM" @qĴm#w 2D 28M#pD@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ F&&:V[$rbD{¾Dn-R޸$rE޸_n\EWxK%Ud%c+1;q9|֔[Ԕk"_e6d=|bt2?XReƅ*3qPe4D8Kwӗ8Nˌ/?g2{~LT*ܟIj U32{{@_˳L*3o@_FpPeeTe|;rܥ/sq-}L*8=/3q6.3T=2tE̝ecRe;D9Ω2:qAw0.K_2̗/#822Q3 e0_&*|`ǝe/ύ }?UFLq210.#82ewr\f~K_f2*/80_qڸenq8 2D@H " Ad$  2D@H " /Nߧ>/ES~'4Gxd m8meQ-s/.E&aOέ,:θVZt쑜90):.(f6{$g8,i v;F`аS1em:t=|V%QLdEgFdИ;p%a7(4c)V%Qt;^\nYGrڗ)&۰;,ݏ߉} 1[ް#8<1j^oX:-:kHp<>1k{M_m¾H9S-s|:^yzb|BΛ=3 )Y*vEm6H5 ^hUcܰ3xH:j=`VZ-:oHpe Q " Ad$ ZeRq.ԱkW5C/G+G#<ؘ#>^VN1vǑl_dKKGԬ?xvZ9<ݽ5tS،o \_7Grfx9v SگRXd;߭Q9f'%2K,Df4;yOco<_Ϟtg> =WYs$?xmdp̃g)2l'qmlIwP_=^=)md~`YL5~ԽjK﬿9{4ۭ}"D,7Gq WfFfɑl'ZĬT?Yf͑oo夑Yp΃gq\Y?A4~]9c 0yMf " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ 426I8p\E[$Z/o[$r|߿]/xʱE"n?trddk EM%Ud5p,2zM UfqN_Re&ş^7qLT˥̴LSevMוo Uf/2_nk"C_A_&Te)Ϸ2c~v|_滳wˬ9|{֏2-UfUe|eb2*/_pRUqǍ-ecTnSec׫2eh{9/+&\=Edy<6}2Ʀ_e49޹6 ~w>1 ꣬-_^ n&3k͖aw̤qa)+ѯ ,}:,ȱWw횷ۜU{>unп_С2[;cJQGU\bwӯ21w4Z؝ ͦɋۺ4BL74֪$q][pewwg22M<2EVtM;-|ui7&ݠ_ QMm5sw}j-{:(2Ct<4/,#׿+B*;vt]Kޗ sTnOm5m:=ڧ"#;v6*O>Qchwvf&j^gJdv-zQ͚l[mmi3gOE4M&sxOȸbZqLޜxyoq&s"dzGdZd*p !L8idvad?m{z{}oRiva&d>OޘběϕqlNxk#v3/YɎcsz[{;:5Ϲ>Oޚ3yl;޸\=~i-ݦr8~6iru"7.6._|qIˏ7.bDqIT*_jjw+KdUWɪm>nӵGtkm֔+UfAwPe4ۗbV[*c2Ǥi}A vPe2]凳LAY/3qcV2T`Uq*s 2S2З tPeT7yI]enӗa\A_&AwPe4ݗt>C_f;޶Lcew0./;20.8/|2*Le;D92}21̗Ytҗ_:/ UFpPeoߗ/`\A_&;D9wҗaLTAw}_2;eebLcq<2S2c5_&# " Ad$  2D@H " Ad$  2=m{EoTHoa[,O#S GMڜ`+n;r7_:ԑvUp+`[yhcH#3{sicԾA42G8,e-?'st֍m)F1YqObŭ/G z<"e5"'f>U9ҖV ʙ6pnQEvG+W#dcrGvL6J|hZtpX2y},(Vc 4C<~ұvP^U,^S9֔UfB9Ay)Lc)]?f8]_fco2xK9a_Ϫ_Sex*܏)Lҗ8-(>Le^A_21?/x?2?eAy)2ݾ4>C_f`\FK;2/pЗ wPӗ/ 3@1c2ego>eEZU(.28E5K7(Ci^88s;YG? epe[9,DNH "nad94zd_1./}%VASD%Z&pS"5$l 9¦ikM،ȸ! GMk{,9z ':^<2f>[SnZc&2Cl $&2~Ȏ?whd&L #Wd YwJS~ Qt~KVz#lh dޗ߹؛Mt&UȎ*;̇ɝwn]$:L+ڏUi:i c|\~ntC&wUPp74s IDATɱsN#T Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$ F&&:|eDD"~6mlU#Gu4֮"{dT?۸$r|6."DT6.׮2֔녪̟5e|֔kUG[Sk8Y롑Y32'QeTھ W 2ct1}=}UFL㤾r?&a㶠,ަ2e+KU22e|@_FpPe72e7Yޠ/ø*/8ceCg}AѠ/۸LWe ;n\ewЗw0.`\AѠ/`\e"/#82Weee"eT 20_eToU&e}2Q2}`2//}Awܸ0./8dMB;G82D@H " Ad$  2D@H " Ad$"o(śWǜQOpG$ofQSL ny8vp7dyOوp}dTTMv=1eeG94xjRw3awTI"({{SB#ӥ48n= WIwll3Ԏ2t`d/Sew y)*2{3`\}˟ӗq<ϤqlW/2{3` 8 we7`\28pHq 2D@H " Ad$  2D@H " 3sR} "a-ϚةT5)9H0[:qPYڎ$<3_CtXn)6Y9wQ= ?borDU%.2#q䑻q[;p8Gbf;|iqo]GČid_a( ol*ojYԣroL[;VOހvƞSևu|q4#}4GtДa-9Z\Vw4v#Sq3o̖c;4gxch:莠@sVF\*h`aǯgU`'fw{l~{ԟ|o#lV+X׷V7H; ~Vuй:W_~c6_46\9}q" 8пGPGPMn/&}tGM#Ӟ.42ys^*ǁ=:,7r2t]#pD@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@bl$F8p#cZm]q[MX\a-&sۤp"$[58w3~Mb]G~LR*$q׾>KXi 3ˬ28p\`\˼Aq/l<{k_qg9&}Wu82wq0.RU}D8LƸ 9VjXsK:˼qr82808w0_~~xU˼qr828`\&a2e^ȱRÚ[8p\`\˼Aq/l<{k_2/28p\`K;y)  2D@H " Ad$  2D@H " N?N>+S;T9tv#5vcr G~TE#S؆76)] `pY>#.2#@ⰧPW1 3M+ ܲ~:cx+h\/2lruiRc2}^dG@;v"SCw^m7z)qcQ ]*i{{dUuDfeK^6xJvAJidJUu=( w$7x|$:*G!O|[oLsȚ ȎOJDh.Ix<]@v4'z=[1hG+uS|b><2ՠo kۓmp{ ?/Skn'oAFǰfQMXe=B2|.lUpฦcWW*c/qUe9\xa"8p\aYb"~:L1!2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2d$1qUcEUÁ<2VzMb˺ZXR:6ju*Us8ڗeށ*G#?xqcjupr˜pPepk_Ƙe6>ϺPq[8p`\&qq2 T8$ڗ٪eie:̗y2T8$ڗ1q9rT82ю̗y)*]2qø;pPepq0_Fvn7`̛;T8$8pHH " Ad$  2D@H " Ad$  2afT)g",9աԊE㨺iǬH]arY|{n@dbsLdzGuTZFnLUbG s2S=Vy斜`u[F`32{k5=ED8= 򰶿l6{&A`EGƥ<=Ǭe)l-lMYe83eVM{YlXqFFq4Zm+{_?pj1&wʾV%Rq<-}v۸Jb#պXr?:yWud2wqRfQٗLVqhkK`%GeQF6N-moEk-ϝUGޞpwT׹-t=qO=]B#90t %Vr*kމ*ͺEZsM$;k\/2j{Ë=l,x:LS"9;须_7EWٰۚ~ Ɏu{zOFrdQ?Qd64wvv.2Ac VC5Gl:>Ȑyz5N8|na >?Qꟗ5?׷U 㮣%X"G;EY9DʿUȴ]sT_Á,2ys>*ɷpาòD&v<Wu@_qf_fq|*8̗Ix\|28pHЗ wlхwqPepx5qw`U 2Ꭽ6b̛8jU7s8/̗Ѡ!A_&ܱFAe޽28$e$  2D@H " Ad$  2D@HnA5aɅ*匊%Gv¶*M}<@;n+2jss|; YsFý K.20h|sHdGuHZ t~p#ۼʌ6#͆{p/=Gv&/b#(R$rmex6o'X#cσLa:-_)&F1ePUu-8B#83OhzLlG8څ,2nuӼ[;b@J:]m#Q֯[Hr̸;QG&s'{:fA`z8 @o((YˏCTGe>(VnCGfsQd/#o5\r,Mv\^,ird4Msg1M09Gr*EMқy(;ô%7(W˜~T F )OhQ_n^d~ЧUdg IDATs{V.6uUygȞ@]w WGn)('\ں|q-6;tO׷˺9Im͎$-kGH=oܯFfvrfW{5{M}+DžG8rZ+#f4r9F.ii\*^ _|TCa?S.iǪD֡ jKqFFWi5Q4m"ҫuuXCvoϊ#(8JFKձq˳ڒs [:.8@}i:2~kԇPcG:ۨW[GL_R< oMGpsm9 %dr# 4GxQG}=k1O"ж/_*j%4rErxGQWD&%۾8SYȎjq:N:Bѵ_ɱ.Q/[k*.Rdk1+lP\z9dG@uKԨCB-G4'MZ9I>uUFvs,ŹM.?i34GYVQcUFv:Ǝi,+`.ӧ{6%Eg:I2c,XpT)ǪDFј,8V_j Yj)h8Dfb* :|p牱сQ&⻱q8c3" Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " L*F806Qh/?sXm~~c%?_}_vyBՊ1(s_猪y$eec@صep\_F9f\)8pa2#3>|pzցrLGF80Xyq`Ϭ<: eg]o9 F8$λ.s3}kUq=+G:g*ּeוOw>}iПعB}GYY\[}N09Qj[cˏ,#)˭7xpy&W;}ƖfW{5 |%h G6F7lF&Χ (N:FEth/qz;ln Rq LqPQssj^d\\C?rN†'`昞NqgN-+py;GNQ"(pclu8\,N#.BZgT1EMɱmuq*D&a~+sך'Haȉ'/82/>ϗ:E@sSZcզɱhaYs+]~14+/8֎8<+/(2&nlYR3x}&vynP6 ;}{G 8BRUѮgf#/z9qp:6OvGZo^㨎&2}>yb qTGb=f,8 @H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H#=:Md#* :md_pO70!Q #9|0?ͱ3y~Tjcg0Ʒ2XL|ٱ>懆sig uv|b\s˼8C7`]FQ 2~|<,Qol˜r݇u80#] 28p`]2;e8|#_/N1`.9 eq.#(  " Ad$  2D@H " Ad$  2D@,21\u8tCl71`kUU#Td7k,2κAHUfⶠQIsqhSWڷcZj˺2QI?̽rxhOƻwn?qdћ=坻bѵ1;b;8r ZQȤtrN':FY\Ǯ^#O?pj[П;nK13BFqX\Md\Jˍcq2\ƕ!52phH׏͒#8YqguKAdT1Į#ma0Zk #ӏ' ~$RttӷtL"O^q؞,2@PH' զrۿ0s}*&rGh9. 9\H4GL##t:VQ (q8Ev$2Ns@m>g\sgc|;qTuc3Xesϭ>niY>.sw}8G8Z8 e~۱pI$Z9母Vy[a,K1[6qivO&f#I/)M?uBt$bɱ5s\*׏͒#CZ1N  /9J#x;=iVKF^,VKGĮ9Gr*EM}KGdClS+EFs&a00oM#J/$ZXs[cΚB2j{X3#GWs+EFs&D&m_< H:OɚcnJy(Lz#%‘Ϙ&RdDrteVqb-X󥦎Vdt8Mnz⺌.[G&ySs} P*GxhyQ-2颋AL8]Iڿ Ēcmk m æy _p̭ Q/2yg}b8Df][ڥQgz]貿)84M8+9ɱ.QG({ϵ/~Oe8pӱxʽ;z3Gu$6c]:{1MdwqT-f"D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@b1U8pal"Qhqq{53.?䈛FyjQ㬣2OkǣVͱ069㼣<5?pƘsq8ppenǁ#>5ϸw ;\p88\2e~ı\Y=]~-YGeX%\2e~ 03[g.s7xt/.=_q~!k🩫Xΐ=G +MI2}zעlcE'X9yvT>UX;G5 Ҳuԓj%02kn>7GqGG.gBHGNK~RF&?8F.Ę΅\ # pL8bl]P[42ZJjKa^ #K)㋳9%GQ2ZX.kKrY7lDO6exkӐG7¤1ޣ5GđN6*(5];GLkKm0 1M09[ۿ0s}>oMG0JzxF@PpQMvn fFsy1fS<>+qԗۣ/$2Nm6d*E档@;B%ME:v9yU%'y9$)?ҝq;Uw>EQ C5yGGu81q`.yGx6K{%v;2O};|-%IDAT<se>7j;qw˵<V}8pTve38ݺ9~\ & p1qQssϭ˄,ݹ{0.WƹGxy'eYu8$=ʜa.úʺy㼣y[<2yY888(s˼GueHOL,g]ep8(8ƺ̗//92gn]e4_QyGe>.ttg  " Ad$  2D@H " Ad$  2D@BLn@屯ncM965T}G?UZCL]Św9*e>՞O_;SW>z:tאַe] Ѡ׽5ˏ,#sg-r,c;w5Ѯc~fW{5 |M|/62iu>u]1saTPl'8Ɲ|r,P ec{wAm)zqirøgK|.#\~cs}q00edxRі7qw6{9?6:=WvlQhG qQ<<8sy 2糇:{ܣ8pyFkǽcX| s;w-ƹGe~quqp=qQv}h֎aߡ2C{.p-Gve`]s2˼w c]ep8(O9N.3}ܬ爃921mlcYep8(_s!qQuWa e;X)ljencwG3Z;~ q8ppe9Xk  2D@H " Ad$  2D@H " QﺮVH[KZ:tClXn5vfs5-+{[5J|rTEffGof;&uسu ׼]kwUWu56ݜK_sY'#HO[ ;wrϱس%4h#ָ#A{,mLOB::s!Raa:Qpʱp;=69c(gÅ2∱(ȸQ?}8b\ƕ]"P!9YrmM㙹|xyX0DP(-UG e'xGFKəW֫]Ms؏T#tZm/8{.(8 `~-/\=xKnsl34m"h9. 9VF#GǼhAg/͍'vzhۗ:޽DCLFrmƱxfXrj8Hl7Q " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@HudT1qT0qsR)w02G;cc(ˎUD"b}Oq(#wGuO8c2T}8Qc}<,_?6~&[F\f0ms|:/;6a]12Gpcqr2GuGu0`]Fr|u.sgy25/;N.sw,;P- ۹̰nwqeW2 ep(s9g,~Oq(uLΌ@Շ9ej8XGO_v|]fo9epsa;´O8\ut0qyY2˼x8`\Ό@Շ9v8Z8  " Ad$  2D@H " Ad$  2DNyͷEƻMrnnr(8ݶѠ s9loqg/dK}7czL\LE{k#6IROdfSWyO_qS?%+%^ˑ.]n޿r8j#7*e-3Gn7c[z<:;˭0^i).\"0ܹ0؅`ZB42#.9٤ՐnOo\,ǶD>-^!ť_1}n,/'l"Rﱓ| i$ 5Bw7s N8:^?6KjAǦDudԃ I}׭n_֑]y2e|iM j fFu!v5a?S):0[:6%蘾ll_>L3oL#Jbj?kh\0uJ9Ɔ2B2j{ĚUuGfnijŗ'vgb!9nZ8r'kf2c<%k^vIZާx;xx\1|K}_ 9᧑Rd:.dHUkWƨfg/1__~ݶy9YG&apq4^e$M򼶙#1@ѕ2Z96_1tXd /ȷ7LF^zObjon~/GFsyU Q|I+y^:\[˱iaK˯w˽l'letugK6]0է9t$]oxqnæy }_p})l˽x~^^/cq{Q 8pp|el"瓽'*S/c=fqx8Z8>2 @H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H " Ad$  2D@H#=o9@dzDnߏGTr#*9cD+l"zQ|Tr|Tr|Ԋ|pfGQ柛埕GoƖ7ebɝO"e22ŎOe~(S`2}7LǺ̿w2ia)v0M;X0;e&2ŎO2e~Fb߄Q߄Q(7a]߄Q(7a.S`]o(S`pLc3pQ(7a.S`]o(S`.S`]o(S`0)v.7a)v0Mee2F Lu ;@_@H " Ad$  2D@H " Ad$ ndʯo5sֻ:*񣎽_Cړ߄|!Fƻ}@d>#s_wx12_p~.DFO7ƈ.mp9vsK-Sbnnv/8;عbOM]sIb_ GvQ3_ykz+vVCq6qv=6Tj6~72]~yE:Eyb_*Gt,jf*]z4xk۲^0cudyS\Ww7O}ϑwS^so58WHX|_|ws\n<`|a?msgm5Osa>cO/8mկFr ]\3}_ D\137fׅ k_r`?Mt,jfӍى[ 絆V~\ o|1?vwoGUDzf"hבq|'pyts5?Opzl<*G& dL2~0|dJu:߃xd~ " # "s ^|4夑goؙl\<績 ;Op\\uMd*,p['>eO-sFf.Ni62m7巸s.^i92n}?9sd~r.ss7\'8id$#7w6.sl\S'̖՟G3՟G3՟G3՟G*D@H " Ad$  22B$`IENDB`PyChart-1.39/doc/pychart/scattertest.png0000644000175000017500000001740610352146635021763 0ustar santiagosantiago00000000000000PNG  IHDRZQZ$,FPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"IDATx흋* E_5-@gwlQ<B H M -iH $@Z$ IH@ -iH $@Z$ IH@ -iH $@Z$ IH@ Q^ѻ^,oAF ژe5hu)R g@Z1m8$۫KjP6wR_Vl_#?so5쟲~Zڮּ/Ugi)KgjfV٩]Z;[ @+-&-ǧ-_ihZZNҺ6"Ϩ,UiiI _vlr*C&)ÝgZ RJ'HZ?:*ժL k9yζ IDzp̐.?|-f5~x.oͱLUDj VtjHk׏1+]j{L̉UDg2^o+k!CJ3&7G:oVOKiWSU'utEIK !ײ|[#A$FR.ijh5v353X-Z\4jA-p+$H72:Ak@mkHK,W۟2E\a5[V&\&˒\@V?ѿ͈ܖR}u/2k9|TaW]F"bݯiDv_yl)}@kEҤ|J+ G]A.F_+E }Jb;fPSQiCuE hJթtNƦDG%VVa\}-G)-qnV]Z PVֹRu[Y(?(&륷 igk%04zo֤iSGFWε*I꒡-iu]ǓvFrZ!U תurFim[KenigߘgLT?CV:.WÜP?]ZWE]kٻ!B\!ٍXi}KkTƹb(E+׫U KIKuBY\mУI2JkqI+`wq k^-SX- [U[is{CjUeBR ~錇=,4t{oɘ;(sGsN)Z5 I3d4M%ǃfvpZ+tsH;_IMIO=ă4y B 5{n7/#ZkZzK*Fw#׀V \_K?وkiARÎҴ=J#k]ռM#jݤeGՂDCR}(izB[R3Rj1iQhN5hGYiM% rLi{3k3 '5߃%H}'~|soffw!L[]L1X+mGVj _K#ܽ`f3vu8rx$/³<6_qi1oZ*^[ސ5u2{a>\Z齮8Z??B^ث2,"|w-LZkN*pVh.'Dk"5B[MZaiNe !|#ƥŰ5&-k ךdoC_$- Isjn!ycyPZV<7iuKتa,uaHWC y9MZҧ ;LqyjLs9,-RV_Fxav_Z]Z3S^wkeQpuz!11˿_ѐ~82G$ar|J&Ay,`#ܲn`~%rc(7$ dq,!ct9|-{ IJ4 `y"} ekYEDM;2_u{,Қry66DV QzqLc 9VKp\+cl1ڳHf}RZ骎%czelޥrmTɐvFNB"EiqYgּPɵ$t><9TJuOJSwi)B9l}BJ;+n$?B޸Ikyد-+k/ue6\w,Һ.zL;c1Ϙ^^B\z$Q)[[Vc ֻ'N㿑vFP%%.BX#Rʚľ.1pmw;oӗ+]S7i=2v=P$iZa\KY-ߕ"ZVnr2\=YPע Eĵ<MZ]m?Gif~vVۍq>cx9+#עaSҘ> #, sVF>u O^A3g*k!7F!- #팘ł}$`@F~i"j),C.cǥ+^#K+zgPV^IZj Ei#BO@Zyvyj!ZÈk8`Xj+DiMqigRIԿ 3y J3ΤCj-JqФ$)kѤ5Z@$i i3R~ߑnISWi"qIrȲ8-K;'RQ6AZz/$2ޤl |&( *Oi!⊬ֹDijGVkXg%&35/IAV8ckŧkA ővFbAZ abH;#'!*/.\xI_a*| Z濻]WL)kkƶT4c 01V~,-q Ͼ|-T -qKkQnjJSe;L0_ @ i9q-aUY\k!ղyI ŵBn(,ff%bk_>A_3 AZ'ɑigd8UzoBqgv#e*n@Zylawڙ71_S]~ˆImc]l:޲EMZ||%1@Zy>7Ur86섯]Nm"v&SJWR5'= WڙwKc91S#xqbT]*Z}@ZV ?V/{ iŞc=C L;#FC-K'X}DǵBΈPʒk#8 ,-BDc+3b4ԪqKb4Ԛ^JH B}I -ԗH B}I -@ )ۭ@Cc/q#^dy>J&iR噴N)e㰃9Rݏ]w,Qa=p%mCymN 0^:kh]~?:Ґ^uhiZ!?g6eD:ߟ`]m}.>>顝vi M2א!&a1S *u\ZНvyNQF*_W.'hv ~3MyӴTų_xzœPDrimGe̟) ׏d;j_uQ7k~xG_µtϧcf0~p~H+ZP~ud O2S}2þM5~eĭgg\wۯE8ޓUjDN8 $$Nz:|;rM~>n֓סrRzi$ǵ:ej8C.BI/Cs$yo\K)J G ~q-q7"2S?SȘ.Bךk}`VAKd6d.l,raX&kUUq8 {$yJ 3(+Yi RU0$?P3*.o|=6h[ X:6+|F1i9"3ኊd೬KUT9>a:6|F)i9"3(P9CJg5\0Ca0Y~+zЬe$9Pw0+fl{"ꊟ؛Ud>GO!m:e?<=]29YE3Ik$_Bo!ma:eh{Sڬ2Z:|?lBÞu8~Ό!KwבS#qhigb^Uēfj$|FYi n1ļ n'Hby}>Le#C-nL,񥨴b^n>5ºl䕲}Ԏ@s#eÔoƍksn9$;%8F^)-rX>s#o@Z n,|_4i1X8Al@Z n 6 -N7+HG|HW`5 -iH $@Z$ IH@ -iH ${ -/g߁@B in v&e@Z !j4Wuux<H,-$uiZ}֗(q@ZNkoF ^Cg3_jux 11 Pie plots

    11 Pie plots

    class pie_plot.T
    Pie plots. Image pietest

    Sample pie chart

    Below is the source code that produces the above chart. ../demos/pietest.py

    from pychart import *
    import sys
    
    data = [("foo", 10),("bar", 20), ("baz", 30), ("ao", 40)]
    
    ar = area.T(size=(150,150), legend=legend.T(),
                x_grid_style = None, y_grid_style = None)
    
    plot = pie_plot.T(data=data, arc_offsets=[0,10,0,10],
                      shadow = (2, -2, fill_style.gray50),
                      label_offset = 25,
                      arrow_style = arrow.a3)
    ar.add_plot(plot)
    ar.draw()
    

    This class supports the following attributes:

    arc_offsets
    Type: list Default: None.

    You can draw each pie "slice" shifted off-center. This attribute, if non-None, must be a number sequence whose length is equal to the number of pie slices. The Nth value in arc_offsets specify the amount of offset (from the center of the circle) for the Nth slice. The value of None will draw all the slices anchored at the center.

    arrow_style
    Type: arrow.T ( see Section 19) Default: None.

    The style of arrow that connects a label to the corresponding "pie".

    center
    Type: (x,y) or None Default: None.

    The location of the center of the pie.

    data
    Type: any Default: None.

    Specifies the data points. See Section 5

    data_col
    Type: int Default: 1.

    The column, within "data", from which the data values are retrieved.

    fill_styles
    Type: list Default: ['fill_style.black', 'fill_style.gray70', 'fill_style.diag', 'fill_style.gray50', 'fill_style.white', 'fill_style.rdiag', 'fill_style.vert', 'fill_style.gray30', 'fill_style.gray20', 'fill_style.gray10', 'fill_style.diag2', 'fill_style.rdiag2', 'fill_style.diag3', 'fill_style.horiz', 'fill_style.gray90', 'fill_style.rdiag3', 'fill_style.wave', 'fill_style.vwave', 'fill_style.stitch', 'fill_style.lines', 'fill_style.diag_fine', 'fill_style.diag2_fine', 'fill_style.diag3_fine', 'fill_style.rdiag_fine', 'fill_style.rdiag2_fine', 'fill_style.rdiag3_fine', 'fill_style.horiz_fine', 'fill_style.vert_fine'].

    The fill style of each item. The length of the list should be equal to the length of the data.

    label_col
    Type: int Default: 0.

    The column, within "data", from which the labels of items are retrieved.

    label_fill_style
    Type: fill_style.T ( see Section 16) Default: fill_style.default.

    The fill style of the frame surrounding each label.

    label_format
    Type: printf format string Default: "%s".

    Format string of the label

    label_line_style
    Type: line_style.T ( see Section 14) Default: None.

    The style of the frame surrounding each label.

    label_offset
    Type: length in points ( See Section 4) Default: None.

    The distance from the center of each label.

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    The style of the outer edge of each pie slice.

    radius
    Type: length in points ( See Section 4) Default: None.

    The radius of the pie.

    shadow
    Type: (xoff,yoff,fill) Default: None.

    The value is either None or a tuple. When non-None, a drop-shadow is drawn beneath the object. X-off, and y-off specifies the offset of the shadow relative to the object, and fill specifies the style of the shadow ( see Section 16).

    start_angle
    Type: number Default: 90.

    The angle at which the first item is drawn.

    PyChart-1.39/doc/pychart/module-text-box.html0000644000175000017500000002201110352146646022621 0ustar santiagosantiago00000000000000 18 Annotation


    18 Annotation

    class text_box.T
    A text box is an optional element that adds a text box and arrows to a chart. This class supports the following attributes:

    bottom_fudge
    Type: length in points ( See Section 4) Default: 5.

    The amount of space below the last line

    fill_style
    Type: fill_style.T ( see Section 16) Default: fill_style.white.

    Specifies the fill style of the text box.

    left_fudge
    Type: length in points ( See Section 4) Default: 5.

    The amount of space left of the box

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    The line style of the surrounding frame.

    loc
    Type: tuple Default: (0, 0).

    The location of the text box.

    radius
    Type: length in points ( See Section 4) Default: 0.

    Radius of the four corners of the rectangle. If the value is zero, a sharp-cornered rectangle is drawn.

    right_fudge
    Type: length in points ( See Section 4) Default: 5.

    The amount of space right of the box

    shadow
    Type: (xoff,yoff,fill) Default: None.

    The value is either None or a tuple. When non-None, a drop-shadow is drawn beneath the object. X-off, and y-off specifies the offset of the shadow relative to the object, and fill specifies the style of the shadow ( see Section 16).

    text
    Type: str Default: "???".

    Text body. See Section 17

    top_fudge
    Type: length in points (See Section 4) Default: 0.

    The amount of space (in points) above the first line

    In addition to the above attributes, this class provides the following methods.

    add_arrow( tip, tail=None, arrow=arrow.default)
    This method adds a straight arrow that points to tip, which is a tuple of integers. Parameter tail specifies the starting point of the arrow. It is either None or a string consisting of the following letters:
    'l', 'c', 'r', 't', 'm,', 'b'

    Letters 'l', 'c', or 'r' means to start the arrow from the left, center, or right of the text box, respectively. Letters 't', 'm', or 'b' means to start the arrow from the top, middle or bottom of the text box. For example, when tail = 'tc' then arrow is drawn from top-center point of the text box. Parameter arrow specifies the style of the arrow.

    See Also:

    Section 19 for arrows.

    Image annotations

    Annotations example

    Below is the source code that produces the above chart. ../demos/annotations.py

    from pychart import *
    
    tb = text_box.T(loc=(100,100), text="Without frame")
    tb.add_arrow((50, 100))
    tb.add_arrow((180, 100))
    tb.draw()
    
    tb = text_box.T(loc=(100,130), text="/hCMulti\n/bLine")
    tb.add_arrow((50, 120))
    tb.add_arrow((180, 100))
    tb.draw()
    
    tb = text_box.T(loc=(100,160), text="Fat arrow", line_style=None)
    tb.add_arrow((180, 140), tail='rm', arrow = arrow.fat1)
    tb.draw()
    
    text_box.T(loc=(180, 100), text="/a90Funny background",
               fill_style = fill_style.gray70).draw()
    
    text_box.T(loc=(180, 140), text="/hL/20Big/oText\n/24/bHuge/oText",
               fill_style = None).draw()
    

    PyChart-1.39/doc/pychart/linetest.png0000644000175000017500000001140410352146635021235 0ustar santiagosantiago00000000000000PNG  IHDR3,PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"IDATx :"4{ScwgX#[YuX 1b!C @@ 1b!P.!C @@  /^AfIB Px%@7 WQ^B_"XP:#`!Lb1g%AV05L蟸 ="J !,b0D w̪; ]@ V}gE!A5D>, h]юvq:OP!0ɆIM̿Dg5w BV6EF`YAº0Kkբ}X] n!\oR^-:["bEN!ÓPX.a` QU-Gao0^!N-0‚Tp1X2Vo>:C8lͼO zQɛ 4O@n BWP BBU+C(h)`:SdP¾U cȟҍ)[𹊏k*x'AJ/+W 13lA4O)Qu@(mi W9Q!j@CB?ɔ79E$2( hi2((Q.1PC( 8IX!fyrw)gR(!tq;z޵NgP~. q;b9Oz.]Z|ʠLw恷2}Q;֭~eDG`p-zɳ \@esὔ" Rȍ0u׹BnL=C,A! ТJ_agyʨ)@"N+N!o ) >D-*³b S$Q4JBCx,B*BW'Q :4G~^ ᱊ tV0P / ~ 0߸KXIBU_!qElЂ]k : •B34(4p6ȘA:٭c{M:B;$(\! bB*QpFr`/O-Wk@nŻm A¾1ƀH:Ro!j 0)7@8r :n{$Vx fVD;Z*;,~3?uh~W Їp^VioBT\i!V͑h|lCxna!q%`يw^8L&kf=#Oӻ/6y>Iw2Y[Q/J!`.tU]V#i|!)aȋeSj0vB+;^Y;G!IVj6Z=:m~w?-GB!l  X?Ӭ#i-@,5zWKX&8ccWpiHtA~ٚ;0Gu!s+ea/x.C¨CK|% ҭ&f<1n5/+gΌhԳӲ ȯko B0FDJ63xD$t*|k)T#ն+U﶐L!Xq#&ZAl!DN HH$GxCTk)24MKd" R dB"yB{yN|d  {;>Dr|lhj"pB5|a-[o H B5|! Q2sPM$[H2YFd m\% B5L}ۂ1b!C @@ 1b!C @@ zR{u7E1vNϽ"ڍyX'$> :B;>(rH*]yDSdYʻqbeKi0gB#xC//3ulA f5c^FO0j'VI=;^L; )@@ (_IENDB`PyChart-1.39/doc/pychart/up.png0000644000175000017500000000110110352146643020022 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YPFy =p3f?0bKGD{lIDATx} D2+o?{Y'tj;`&tO˧xM"7v T㣤P5ahKZ쥕@{lEӦ]Am P[mdPMD.䒑}l%VLq>ZLL Nׄl-1wA4=r`?7cj&$ph,@xx 3LzTXtSoftwarexsPMLOMLLV033R7070TH.,.tȭ,.LK-K)-+KK^3zTXtSignaturex304L0JL4M4KI4H564LL444H40421vC[̓zTXtPagex360666 GwIENDB`PyChart-1.39/doc/pychart/arrows.png0000644000175000017500000000730410352146636020730 0ustar santiagosantiago00000000000000PNG  IHDR7dnPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" AIDATx흋8CGH5R}L]%$I$)^ $IrC$IJ_nto1`Ʒ0`"9Qx6F3Χ1XG` 0|!(c}z|P_h/j? o5I`dʍѝ#7\jDcr q Kq3S51]OQr{tϩbG؏ύSdz+7\jN.G>k (_50~~9؀\VnmƮ/v?Vczogfy 98ynʍjUʍTjY.5"±aA {f]nxXr#^)Fy?RnqlFUn`/Rn`O^z |0rة&  Sn >L\r 97 phSlVʍXVʍ+}sl)6rl)6c]'6ar繆~1 DֻN]r=A|_0"g.7h>O6BйaʍxA tpd0? 7 `AnPG<Ƥ܈CnLʍ{¼rln 1}s[sOh]>w`En=א"7hk3C+ڕ>3%ٍܨܨLweHݗnC0p@Xs2!"7 ijoINw\,%5&}ϭ`@v!6xʍm- )7o=pxprQ Qxcc*1Q^{Fiw?GN 2^u$øS N o+۞e3R\Fd׃2@3tt`<SE| گLBE0ьB1 =m܈Ɲr?nevJa3x@#)(<.s/C9s8ARZ/5*Qg*z%Z±I0^Nȍ_i\ðS d%+O~o<c΍}cޥcl]ǫWqbExFQ"e> ]`rԈavôS d%gJvƗ4ż0 2J(2 9h*zjHngq\co+d$3Ryrʍeԯu/#zc7ƣ7p!]}v.B00J (/;(>/c2޽B N 0;%0LƔ2LFR%ɍ׈8i{Xn|{zŹixq|]*1.Q"z7N 1&+İ N 0{&13!% z~2O$߉1-@z,;T.6J (-=P(.Է N 2`1;%4N 1{&)e#\cys=bǀxto˦ܐb[޵,.TP BϣP߁;%@Ƒa)yXwJp[L.#97i%˜Gdza LP I,Z FZVk\1$&kU3UkX?sZr!1e_ܨ[cƋ k/$}frC$IJrC$IJrC$IJrC$IJrC$IJrC$IJrC$IJrC$IJrC$IJC IENDB`PyChart-1.39/doc/pychart/next.png0000644000175000017500000000077710352146643020376 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YP =p3f]=bKGD=IDATx͓0Dc@ vͶ{MfrtF@ uQ@N ;:%فQ!XxmS1 ZOc*Tx< wqhA,Z~LzTXtSoftwarexsPMLOMLLV033R7070TH.,.tȭ,.LK-K)-+KK^3zTXtSignaturex3231L47374K11426NL3105L210HL3|nɾzTXtPagex360666 GwIENDB`PyChart-1.39/doc/pychart/module-rose-plot.html0000644000175000017500000002161410352146645023002 0ustar santiagosantiago00000000000000 12 Rose plots


    12 Rose plots

    class rose_plot.T
    Rose plot class is contributed by Kilian Hagemann. It's still experimental. Image roseplottest

    Sample rose plot

    Below is the source code that produces the above chart. ../demos/roseplottest.py

    from pychart import *
    
    theme.use_color = 1
    
    data1 = [ 0.27027027,  0.74324324,  0.          ,
              0.34459459  ,0.47297297  ,0.06756757,
              0.90540541  ,1.          ,0.40540541  ,
              0.33783784  ,0.33783784  ,0.16216216]
    data2 = [ 0.93333333,  0.46666667  ,0.26666667  ,
              0.60666667  ,0.6         ,0.73333333,
              0.22666667,  0.72        ,0.13333333  ,
              0.46666667  ,1.          ,0.29333333]
    data = [('/7Model', data1), ('/7Station', data2)]
            
    ar = area.T(legend=legend.T(loc=(100,-5), right_fudge=0, left_fudge=3))
    
    plot = rose_plot.T(data=data, sector_centred=True)
    ar.add_plot(plot)
    ar.draw()
    

    This class supports the following attributes:

    base_radius
    Type: number Default: None.

    center
    Type: (x,y) or None Default: None.

    data
    Type: any Default: None.

    Specifies the data points. See Section 5

    data_col
    Type: int Default: 1.

    The column, within "data", from which the data values are retrieved.

    dir_fill_style
    Type: fill_style.T ( see Section 16) Default: fill_style.default.

    dir_line_style
    Type: line_style.T ( see Section 14) Default: None.

    dir_offset
    Type: length in points ( See Section 4) Default: None.

    The distance between the directions and the outermost circle. Defaults fine for most cases

    fill_styles
    Type: list Default: ['fill_style.black', 'fill_style.gray70', 'fill_style.diag', 'fill_style.gray50', 'fill_style.white', 'fill_style.rdiag', 'fill_style.vert', 'fill_style.gray30', 'fill_style.gray20', 'fill_style.gray10', 'fill_style.diag2', 'fill_style.rdiag2', 'fill_style.diag3', 'fill_style.horiz', 'fill_style.gray90', 'fill_style.rdiag3', 'fill_style.wave', 'fill_style.vwave', 'fill_style.stitch', 'fill_style.lines', 'fill_style.diag_fine', 'fill_style.diag2_fine', 'fill_style.diag3_fine', 'fill_style.rdiag_fine', 'fill_style.rdiag2_fine', 'fill_style.rdiag3_fine', 'fill_style.horiz_fine', 'fill_style.vert_fine'].

    The fill style of each item. The length of the list should be equal to the length of the data.

    label_col
    Type: int Default: 0.

    The column, within "data", from which the labels of items are retrieved.

    line_style
    Type: line_style.T ( see Section 14) Default: linestyle: width=0.3, color=default, dash=None, cap=0, join=0.

    sector_centred
    Type: int Default: 1.

    Bool indicating whether the sectors should be centred on each sector_width(e.g. on 0)

    sector_width
    Type: int Default: None.

    shadow
    Type: (xoff,yoff,fill) Default: None.

    The value is either None or a tuple. When non-None, a drop-shadow is drawn beneath the object. X-off, and y-off specifies the offset of the shadow relative to the object, and fill specifies the style of the shadow ( see Section 16).

    start_angle
    Type: number Default: 90.

    PyChart-1.39/doc/pychart/module-line-style.html0000644000175000017500000001434410352146645023145 0ustar santiagosantiago00000000000000 14 Line styles

    14 Line styles

    class line_style.T
    This class defines the looks of line segments. This class supports the following attributes:

    cap_style
    Type: int Default: 0.

    Defines the style of the tip of the line segment. 0: butt cap (square cutoff, with no projection beyond), 1: round cap (arc), 2: projecting square cap (square cutoff, but the line extends half the line width). See also Postscript/PDF reference manual.

    color
    Type: color.T ( see Section 15) Default: color.black.

    The color of the line.

    dash
    Type: tuple Default: None.

    The value of None will draw a solid line. Otherwise, this attribute specifies the style of dashed lines. The 2N'th value specifies the length of the line (in points), and 2N+1'th value specifies the length of the blank.

    For example, the dash style of (3,2,4,1) draws a dashed line that looks like ---__----_---__----_....

    join_style
    Type: int Default: 0.

    Join style. 0: Miter join (sharp, pointed corners), 1: round join (rounded corners), 2: bevel join (flattened corners). See also Postscript/PDF reference manual.

    width
    Type: length in points ( See Section 4) Default: 0.4.

    Width of the line, in points.

    The below picture show standard line styles. These styles are referred to by names line_style.name, where name is the label below each item.

    Image linestyles

    PyChart-1.39/doc/pychart/node29.html0000644000175000017500000001362410352146646020676 0ustar santiagosantiago00000000000000 17.2 Procedures provided in the font module


    17.2 Procedures provided in the font module

    The font module defines several procedures and variables for manipulating texts and fonts:

    quotemeta( text)
    quoting - Quote letters with special meanings in pychart so that text will display as-is when passed to canvas.show().

    >>> font.quotemeta("foo/bar")
    "foo//bar"
    

    text_height( text)
    Return the total height of the text and the length from the base point to the top of the text box.

    text_width( text)
    Return the width of the text in points.

    get_dimension( text)
    Return the bounding box of the text, assuming that the left-bottom corner of the first letter of the text is at (0, 0). This procedure ignores /h, /v, and /a directives when calculating the boundingbox; it just returns the alignment specifiers as a part of the return value. The return value is a tuple (width, height, halign, valign, angle).

    PyChart-1.39/doc/pychart/categbar.png0000644000175000017500000000664610352146635021172 0ustar santiagosantiago00000000000000PNG  IHDR]P=PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" #IDATx흋v E1x|_00ҚƜH7Wz@R-4i]---------------------------}fS:5 gaN}^Qg~X3F0>Y~wúEԧs9]Cq}+s:u\i!lۖ:nfE6}W|Nk֏k+ xIY3g>j4XF>ݶQԇ]ݍh,mch ~[$+ƿ^>yi=;,AX0y%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'Ac IX|4%`'@ R> Y̝' |Γ>sdy0ˋ81YI51)Y°ƍ SWyo ?oXxIt BxnM^\>:JmXΰV:~Oʥ .SW|Zc `:`6,|*`v>eHZ ֪"r6:G9^$|R}nk2usH |}WD|כΓ>sɲ4&ga3w,x͝'ga>ka+ m\3,>lԷ|tcjlç5nD{gF|> u, =_:K'a9+/gavJ0=4w0 |}>| [8, v >]?|{R> C'> C'||sdygsdygʭh^uivekߞ~mϚygsdygsdygsdygsdygs Lq3e^ >g'>Sd=y%۞`AL@Ze^ZLէ3vR9^yg¼>-\2}^]LO-y'>Wx9F쿴k4t)v->?>}}g؉vSn>'m.|&;iҬ&wU떩7R,_Lwsb<Ӈr}oC|-apȊ: nYfI}>/;iC..ʴm3%n>/ QGKە po]Zs:/׸39g|ױl>^o䎍M5g<1],|&FL'xӾ?Nji#O"pZ+Ħ9?t4^>Yyby4^Uj/|C{^G{^Ummm!3g~Wuz3q1˵u>Rϸy}پoNܲt2a_Q'kݱn&.ܶ~)~[ya3I3O Od~r[H%(~떩ԓyKdžO,mu]ٿG)J?[v}ä80ѿɆ _7/d}R>L쏜r[afV,$|B֩gyqұ?>9ɴ}ܕ {b$Idk@s!hyDhtkǩO'ඐyLT6td}wW#xK>AA---------------kHׇ א‹DY!T^C,#|jakh7nܷcI{ ƍZ62Pԏ'57 j$HvK{U'5(I{ ψB[!>n|jٸQk51'g[g['VLIENDB`PyChart-1.39/doc/pychart/genindex.html0000644000175000017500000013146310352146644021377 0ustar santiagosantiago00000000000000 Index

    Index


    Symbols | a | b | c | d | e | f | g | h | i | j | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z | { | }

    Symbols

    -format option
    /, [Link]

    A

    add_arrow() (text_box.T method)
    add_plot() (area.T method)
    alignment (font)
    annotation
    arc_offsets (pie_plot.T attribute)
    area (extension module)
    area.T (class in area)
    arrow (extension module), [Link]
    arrow.T (class in arrow)
    arrow_style (pie_plot.T attribute)
    attribute
    setting default values
    author (setting - of chart)
    AvantGarde-Book (font)
    average (computing -)
    axis (extension module), [Link]
    axis.X (class in axis)
    axis.Y (class in axis)

    B

    b (color.T attribute)
    bar-plot (extension module)
    bar_plot.T (class in bar-plot)
    base_radius (rose_plot.T attribute)
    bcol (bar_plot.T attribute)
    bcol (interval_bar_plot.T attribute)
    Bezier curve
    bg_style (area.T attribute)
    bgcolor (fill_style.T attribute)
    bold (typeface)
    Bookman-Demi (font)
    border_line_style (area.T attribute)
    bottom_fudge (legend.T attribute)
    bottom_fudge (text_box.T attribute)
    bounding box
    bounding_box (in module theme)
    box_width (error_bar.error_bar4 attribute)
    box_width (error_bar.error_bar6 attribute)

    C

    canvas (default -), [Link]
    canvas (extension module)
    canvas.T (class in canvas), [Link]
    cap_style (line_style.T attribute)
    category axis
    category_coord.T (class in coord)
    center (pie_plot.T attribute)
    center (rose_plot.T attribute)
    center_line_style (error_bar.error_bar6 attribute)
    chart-data (extension module)
    chart-object (extension module)
    CJK
    clip() (canvas.T method)
    clip() (in module canvas)
    clip_ellipsis() (canvas.T method)
    clip_ellipsis() (in module canvas)
    clip_polygon() (canvas.T method)
    clip_polygon() (in module canvas)
    clipping
    close() (canvas.T method)
    cluster (bar_plot.T attribute)
    cluster (interval_bar_plot.T attribute)
    cluster_sep (bar_plot.T attribute)
    cluster_sep (interval_bar_plot.T attribute)
    color
    -ing charts
    -izing charts
    names, [Link]
    color (extension module)
    color (line_style.T attribute)
    color.T (class in color)
    comma-separated values (see CSV)
    command-line options, [Link]
    comments
    - in CSV files
    - in PS or PDF
    conversion
    CSV
    date
    coord (extension module)
    coord.T (class in coord)
    coordinate system, [Link], [Link]
    - with a gap
    linear
    logarithmic
    logarithmic (example)
    Courier (font)
    creator (setting - of chart)
    CSV
    curve() (canvas.T method)
    curve() (in module canvas)

    D

    dash (line_style.T attribute)
    data
    data (bar_plot.T attribute)
    data (interval_bar_plot.T attribute)
    data (line_plot.T attribute)
    data (pie_plot.T attribute)
    data (range_plot.T attribute)
    data (rose_plot.T attribute)
    data_col (pie_plot.T attribute)
    data_col (rose_plot.T attribute)
    data_label_format (bar_plot.T attribute)
    data_label_format (interval_bar_plot.T attribute)
    data_label_format (line_plot.T attribute)
    data_label_offset (bar_plot.T attribute)
    data_label_offset (interval_bar_plot.T attribute)
    data_label_offset (line_plot.T attribute)
    date
    conversion
    setting creation - of chart
    debug_level (in module theme)
    default_angle (in module theme)
    default_canvas() (in module canvas)
    default_font_family (in module theme)
    default_font_size (in module theme)
    default_halign (in module theme)
    default_line_height (in module theme)
    default_line_width (in module theme)
    default_valign (in module theme)
    delta_bounding_box (in module theme)
    dir_fill_style (rose_plot.T attribute)
    dir_line_style (rose_plot.T attribute)
    dir_offset (rose_plot.T attribute)
    direction (bar_plot.T attribute)
    direction (interval_bar_plot.T attribute)
    draw() (area.T method)
    draw() (arrow.T method)
    draw() (fill_style.Lines method)
    draw_tics_above (axis.X attribute)
    draw_tics_right (axis.Y attribute)
    drawing
    arbitrary objects on canvas
    multiple graphs
    plots on canvas
    texts

    E

    ellipsis() (canvas.T method)
    ellipsis() (in module canvas)
    Encapsulated PostScript
    see PostScript
    endclip() (canvas.T method)
    endclip() (in module canvas)
    environment variable
    error-bar (extension module)
    error_bar (bar_plot.T attribute)
    error_bar (line_plot.T attribute)
    error_bar.error_bar1 (class in error-bar)
    error_bar.error_bar2 (class in error-bar)
    error_bar.error_bar3 (class in error-bar)
    error_bar.error_bar4 (class in error-bar)
    error_bar.error_bar5 (class in error-bar)
    error_bar.error_bar6 (class in error-bar)
    error_bar.T (class in error-bar)
    error_minus_col (bar_plot.T attribute)
    error_plus_col (bar_plot.T attribute)
    escape character, [Link], [Link]
    extract_columns() (in module chart-data)
    extract_rows() (in module chart-data)

    F

    file
    generating multiple files
    read
    write, [Link], [Link]
    file name, [Link]
    file object
    fill-style (extension module)
    fill_style
    fill_style (bar_plot.T attribute)
    fill_style (error_bar.error_bar4 attribute)
    fill_style (error_bar.error_bar6 attribute)
    fill_style (range_plot.T attribute)
    fill_style (text_box.T attribute)
    fill_style (tick_mark.T attribute)
    fill_style.Diag (class in fill-style)
    fill_style.Horiz (class in fill-style)
    fill_style.Lines (class in fill-style)
    fill_style.Plain (class in fill-style)
    fill_style.Rdiag (class in fill-style)
    fill_style.Stitch (class in fill-style)
    fill_style.T (class in fill-style)
    fill_style.Vert (class in fill-style)
    fill_style.Vwave (class in fill-style)
    fill_style.Wave (class in fill-style)
    fill_styles (interval_bar_plot.T attribute)
    fill_styles (pie_plot.T attribute)
    fill_styles (rose_plot.T attribute)
    filter() (in module chart-data)
    font, [Link], [Link], [Link], [Link]
    family, [Link]
    gray scale
    height
    size, [Link], [Link]
    font (extension module)
    format
    read_csv
    read_str
    write
    format (axis.X attribute)
    format (axis.Y attribute)
    frame_fill_style (legend.T attribute)
    frame_line_style (legend.T attribute)
    func() (in module chart-data)

    G

    g (color.T attribute)
    get_canvas_pos() (coord.T method)
    get_data_range() (coord.T method)
    get_dimension() (in module font)
    get_options() (in module theme)
    get_tics() (coord.T method)
    ghostscript
    gray scale
    font
    grid lines

    H

    hcol (bar_plot.T attribute)
    hcol (interval_bar_plot.T attribute)
    head_color (arrow.T attribute)
    head_len (arrow.T attribute)
    head_style (arrow.T attribute)
    Helvetica (font), [Link]
    hline_style (error_bar.error_bar2 attribute)

    I

    init() (in module canvas)
    inter_col_sep (legend.T attribute)
    inter_row_sep (legend.T attribute)
    interval-bar-plot (extension module)
    interval_bar_plot.T (class in interval-bar-plot)
    italic (typeface)

    J

    join_style (line_style.T attribute)
    justification (font)

    L

    label (axis.X attribute)
    label (axis.Y attribute)
    label (bar_plot.T attribute)
    label (interval_bar_plot.T attribute)
    label (line_plot.T attribute)
    label (range_plot.T attribute)
    label_col (pie_plot.T attribute)
    label_col (rose_plot.T attribute)
    label_fill_style (pie_plot.T attribute)
    label_format (pie_plot.T attribute)
    label_line_style (pie_plot.T attribute)
    label_offset (axis.X attribute)
    label_offset (axis.Y attribute)
    label_offset (pie_plot.T attribute)
    Latin
    left_fudge (legend.T attribute)
    left_fudge (text_box.T attribute)
    legend (area.T attribute)
    legend (extension module)
    legend.T (class in legend)
    legend_fill_style (bar_plot.T attribute)
    legend_line_style (bar_plot.T attribute)
    line
    width
    line() (canvas.T method)
    line() (in module canvas)
    line break
    line plot
    line-plot (extension module)
    line-style (extension module)
    line_interval (fill_style.T attribute)
    line_plot.T (class in line-plot)
    line_style
    line_style (arrow.T attribute)
    line_style (axis.X attribute)
    line_style (axis.Y attribute)
    line_style (bar_plot.T attribute)
    line_style (error_bar.error_bar1 attribute)
    line_style (error_bar.error_bar3 attribute)
    line_style (error_bar.error_bar4 attribute)
    line_style (error_bar.error_bar5 attribute)
    line_style (error_bar.error_bar6 attribute)
    line_style (fill_style.T attribute)
    line_style (line_plot.T attribute)
    line_style (pie_plot.T attribute)
    line_style (range_plot.T attribute)
    line_style (rose_plot.T attribute)
    line_style (text_box.T attribute)
    line_style (tick_mark.T attribute)
    line_style.T (class in line-style)
    line_styles (interval_bar_plot.T attribute)
    linear
    scale, [Link]
    linear_coord.T (class in coord)
    loc (area.T attribute)
    loc (legend.T attribute)
    loc (text_box.T attribute)
    location (- of chart)
    log_coord.T (class in coord)
    logarithmic
    scale, [Link]

    M

    magnifying charts, [Link]
    see scale
    marquee
    max_col (range_plot.T attribute)
    mean (computing -)
    mean_samples() (in module chart-data)
    median() (in module chart-data)
    min_col (range_plot.T attribute)
    minor_tic_interval (axis.X attribute)
    minor_tic_interval (axis.Y attribute)
    minor_tic_len (axis.X attribute)
    minor_tic_len (axis.Y attribute)
    moving_average() (in module chart-data)

    N

    nr_rows (legend.T attribute)

    O

    oblique (typeface)
    offset (axis.X attribute)
    offset (axis.Y attribute)
    output_file (in module theme)
    output_format (in module theme)

    P

    Palatino (font)
    PDF, [Link], [Link]
    pie-plot (extension module)
    pie_plot.T (class in pie-plot)
    PNG
    points
    polygon() (canvas.T method)
    polygon() (in module canvas)
    PostScript, [Link], [Link], [Link], [Link]
    producer (setting - of chart)
    PYCHART_OPTIONS

    Q

    qerror_minus_col (bar_plot.T attribute)
    qerror_plus_col (bar_plot.T attribute)
    quotemeta() (in module font)

    R

    r (color.T attribute)
    radius (pie_plot.T attribute)
    radius (text_box.T attribute)
    range-plot (extension module)
    range_plot.T (class in range-plot)
    read
    file
    string
    read_csv() (in module chart-data)
    read_str() (in module chart-data)
    rectangle() (canvas.T method)
    rectangle() (in module canvas)
    redirecting output, [Link], [Link]
    reinitialize() (in module theme)
    rgb.txt
    right_fudge (legend.T attribute)
    right_fudge (text_box.T attribute)
    rose-plot (extension module)
    rose_plot.T (class in rose-plot)
    rotation (text)
    round_rectangle
    round_rectangle() (canvas.T method)
    round_rectangle() (in module canvas)

    S

    samples
    scale
    linear, [Link]
    logarithmic, [Link]
    logarithmic (example)
    scaling charts
    scale_factor (in module theme)
    scaling charts
    scanf
    scatter plot
    sector_centred (rose_plot.T attribute)
    sector_width (rose_plot.T attribute)
    set_author() (canvas.T method)
    set_creation_date() (canvas.T method)
    set_creator() (canvas.T method)
    set_defaults
    set_title() (canvas.T method)
    shadow (legend.T attribute)
    shadow (pie_plot.T attribute)
    shadow (rose_plot.T attribute)
    shadow (text_box.T attribute)
    show
    show() (canvas.T method)
    show() (in module canvas)
    size
    - interval bar plot
    - of area
    - of bar plot
    font, [Link]
    scaling charts (see scale)
    size (area.T attribute)
    size (tick_mark.T attribute)
    stack_on (bar_plot.T attribute)
    stack_on (interval_bar_plot.T attribute)
    standard deviation (computing -)
    start_angle (pie_plot.T attribute)
    start_angle (rose_plot.T attribute)
    stddev_samples() (in module chart-data)
    string
    read
    write
    StringIO
    SVG
    Symbol (font)

    T

    text
    see font
    text (text_box.T attribute)
    text-box (extension module)
    text_box.T (class in text-box)
    text_height() (in module font)
    text_width() (in module font)
    theme (extension module)
    thickness (arrow.T attribute)
    tic_interval (axis.X attribute)
    tic_interval (axis.Y attribute)
    tic_label_offset (axis.X attribute)
    tic_label_offset (axis.Y attribute)
    tic_len (axis.X attribute)
    tic_len (axis.Y attribute)
    tic_len (error_bar.error_bar1 attribute)
    tic_len (error_bar.error_bar2 attribute)
    tic_len (error_bar.error_bar4 attribute)
    tick-mark (extension module)
    tick_mark (line_plot.T attribute)
    tick_mark.T (class in tick-mark)
    time (see date)
    Times-Roman (font)
    title (setting - of chart)
    top_fudge (legend.T attribute)
    top_fudge (text_box.T attribute)
    transform() (in module chart-data)

    U

    Unicode
    unit of length
    use_color (in module theme)

    V

    variance (computing -)
    verbatim
    verbatim() (canvas.T method)
    verbatim() (in module canvas)
    vline_style (error_bar.error_bar2 attribute)

    W

    width
    - of bar plot
    - of interval bar plot
    line
    width (bar_plot.T attribute)
    width (interval_bar_plot.T attribute)
    width (line_style.T attribute)
    wind rose plot
    write
    file, [Link], [Link]
    format
    string
    write_csv() (in module chart-data)

    X

    X axis, [Link]
    X11
    x_axis (area.T attribute)
    x_axis2 (area.T attribute)
    x_coord (area.T attribute)
    x_grid_interval (area.T attribute)
    x_grid_over_plot (area.T attribute)
    x_grid_style (area.T attribute)
    x_pos() (area.T method)
    x_range (area.T attribute)
    xcol (line_plot.T attribute)
    xcol (range_plot.T attribute)

    Y

    Y axis, [Link]
    y_axis (area.T attribute)
    y_axis2 (area.T attribute)
    y_coord (area.T attribute)
    y_error_minus_col (line_plot.T attribute)
    y_error_plus_col (line_plot.T attribute)
    y_grid_interval (area.T attribute)
    y_grid_over_plot (area.T attribute)
    y_grid_style (area.T attribute)
    y_pos() (area.T method)
    y_qerror_minus_col (line_plot.T attribute)
    y_qerror_plus_col (line_plot.T attribute)
    y_range (area.T attribute)
    ycol (line_plot.T attribute)

    Z

    zap (extension module)
    zap marks
    zap.zap_horizontally() (in module zap)
    zap.zap_vertically() (in module zap)

    {

    {

    }

    }

    PyChart-1.39/doc/pychart/modules.png0000644000175000017500000000112610352146643021055 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YPFy =p3f?0bKGD{lIDATxr EbݦL{cs7|HEXhmt9Z̉g0 MIL+nOJ{ps^Av7{Wu}fO5a 9Ǿ}4ҠZsEMB$GXըc)zB C3/Oo,;fK>hF *eS@Q_ LzTXtSoftwarexsPMLOMLLV033R7070TH.,.tȭ,.LK-K)-+KK^3zTXtSignaturexK05K3K124H1266KJL3M54204I070.i zTXtPagex360666 GwIENDB`PyChart-1.39/doc/pychart/node30.html0000644000175000017500000001175210352146646020666 0ustar santiagosantiago00000000000000 17.3 Displaying Unicode strings


    17.3 Displaying Unicode strings

    Starting from version 1.39, PyChart can display single-byte Unicode characters (that is, code point below 256), such as European umlaut and accent characters. It still does not support composite fonts, including Chinese, Japanese, and Korean (volunteer contributions welcome!!). To display a Unicode text, pass a Python's unicode string to the text-drawing functions, such as canvas.show. Below is an example.

    Image unicodetest

    Unicode example

    Below is the source code that produces the above chart. ../demos/unicodetest.py

    # -*- coding: utf-8 -*-
    from pychart import *
    can = canvas.default_canvas()
    x, y = (100, 500)
    def show_text(str):
        global x, y
        can.show(x, y, str)
        can.show(x + 200, y, "/12/C" + font.quotemeta(str))
        y -= 20
    
    show_text(unicode('Zürich', 'utf-8'))
    show_text(unicode('X äöü Y', 'utf-8'))
    

    PyChart-1.39/doc/pychart/module-bar-plot.html0000644000175000017500000003502710352146644022600 0ustar santiagosantiago00000000000000 7 Bar plots


    7 Bar plots

    class bar_plot.T
    This class draws a bar plot.

    Image bartest

    Sample bar plot

    Below is the source code that produces the above chart. ../demos/bartest.py

    from pychart import *
    theme.get_options()
    
    data = [(10, 20, 30, 5), (20, 65, 33, 5),
            (30, 55, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3)]
    chart_object.set_defaults(area.T, size = (150, 120), y_range = (0, None),
                              x_coord = category_coord.T(data, 0))
    chart_object.set_defaults(bar_plot.T, data = data)
    
    # Draw the 1st graph. The Y upper bound is calculated automatically.
    ar = area.T(x_axis=axis.X(label="X label", format="/a-30{}%d"),
                y_axis=axis.Y(label="Y label", tic_interval=10))
    ar.add_plot(bar_plot.T(label="foo", cluster=(0, 3)),
                bar_plot.T(label="bar", hcol=2, cluster=(1, 3)),
                bar_plot.T(label="baz", hcol=3, cluster=(2, 3)))
    ar.draw()
    
    ar = area.T(legend = legend.T(), loc=(250,0),
                x_axis=axis.X(label="X label", format="/a-30{}%d"),
                y_axis=axis.Y(label="Y label", tic_interval=10))
    bar_plot.fill_styles.reset();
    plot1 = bar_plot.T(label="foo")
    plot2 = bar_plot.T(label="bar", hcol=2, stack_on = plot1)
    plot3 = bar_plot.T(label="baz", hcol=3, stack_on = plot2)
    ar.add_plot(plot1, plot2, plot3)
    ar.draw()
    

    Image bartest2

    Bar plot with error bars

    Below is the source code that produces the above chart. ../demos/bartest2.py

    from pychart import *
    theme.get_options()
    
    data = [(10, 20, 3.0), (20, 65, 2.5),
            (30, 55, 5.0), (40, 45, 3.0), (50, 25, 2.0)]
    
    ar = area.T(x_axis=axis.X(label="X", format="/a-30{}%d", tic_interval=20),
                y_axis = axis.Y())
    ar.add_plot(bar_plot.T(data=data,
                           line_style=None, fill_style = fill_style.gray50,
                           error_bar = error_bar.bar2, error_minus_col=2))
    ar.draw()
    

    The list the attributes understood by an bar_plot.T object follow:

    bcol
    Type: int Default: 0.

    Specifies the column from which base values (i.e., X values when attribute "direction" is "vertical", Y values otherwise) are extracted. The combination of "data", "bcol", and "hcol" attributes defines the set of boxes drawn by this chart. See the below example:

                  d = [[5,10], [7,22], [8,25]]
                  p = bar_plot.T(data = d, bcol = 1, hcol = 2)
    

    Here, three bars will be drawn. The X values of the bars will be 5, 7, and 8. The Y values of the bars will be 10, 22, and 25, respectively. (In practice, because the values of bcol and hcol defaults to 1 and 2, you can write the above example just as "p = bar_plot.T(data = d)".

    cluster
    Type: tuple Default: (0, 1).

    This attribute is used to cluster multiple bar plots side by side in a single chart. The value should be a tuple of two integers. The second value should be equal to the total number of bar plots in the chart. The first value should be the relative position of this chart; 0 places this chart the leftmost, and N-1 (where N is the 2nd value of this attribute) places this chart the rightmost. Consider the below example:

        a = area.T(...)
        p1 = bar_plot.T(data = [[1,20][2,30]], cluster=(0,2))
        p2 = bar_plot.T(data = [[1,25],[2,10]], cluster=(1,2))
        a.add_plot(p1, p2)
        a.draw()
    

    In this example, one group of bars will be drawn side-by-side at position x=1, one with height 20, the other with height 25. The other two bars will be drawn side by side at position x=2, one with height 30 and the other with height 10.

    cluster_sep
    Type: length in points ( See Section 4) Default: 0.

    The separation between clustered boxes.

    data
    Type: any Default: None.

    Specifies the data points. See Section 5

    data_label_format
    Type: printf format string Default: None.

    The format string for the label displayed besides each bar. It can be a `printf' style format string, or a two-parameter function that takes (x,y) values and returns a string. The appearance of the string produced here can be controlled using escape sequences. See Section 17

    data_label_offset
    Type: (x,y) or None Default: (0, 5).

    The location of data labels relative to the sample point. See also attribute data_label_format.

    direction
    Type: str Default: "vertical".

    The direction the growth of the bars. The value is either 'horizontal' or 'vertical'.

    error_bar
    Type: error_bar.T ( see Section 9.2) Default: None.

    Specifies the style of the error bar. See Section 9.2

    error_minus_col
    Type: int Default: -1.

    Specifies the column from which the depth of the errorbar is extracted. This attribute is meaningful only when error_bar != None.

    error_plus_col
    Type: int Default: -1.

    The depth of the errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None.

    fill_style
    Type: fill_style.T ( see Section 16) Default: The style is picked from standard styles round-robin..

    Defines the fill style of each box.

    hcol
    Type: int Default: 1.

    The column from which the height of each bar is extracted. See also the description of the 'bcol' attribute.

    label
    Type: str Default: "???".

    The label to be displayed in the legend. See Section 6.3, See Section 17

    legend_fill_style
    Type: fill_style.T (see Section 16) Default: None.

    The fill style used to draw a legend entry. Usually, the value is None, meaning that the value of "fill_style" attribute is used.

    legend_line_style
    Type: line_style.T ( see Section 14) Default: None.

    The line style used to draw a legend entry. Usually, the value is None, meaning that the value of "line_style" attribute is used.

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    The style of the outer frame of each box.

    qerror_minus_col
    Type: int Default: -1.

    The depth of the "quartile" errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None.

    qerror_plus_col
    Type: int Default: -1.

    The depth of the "quartile" errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None.

    stack_on
    Type: any Default: None.

    The value must be either None or bar_plot.T. If not None, bars of this plot are stacked on top of another bar plot.

    width
    Type: length in points ( See Section 4) Default: 5.

    Width of each box.

    PyChart-1.39/doc/pychart/bartest.png0000644000175000017500000001511410352146635021054 0ustar santiagosantiago00000000000000PNG  IHDRI`PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07"IDATx @{:gGk{af3%|y-`/fLxw8N`/29q[^Y8]pweo;Ͷfp9X|O]y(8^m{ً=_Nmy58;m}$bo{\O3c/(y-8#(y-8ػGPZpw0AkAq~q4$ɹuP[n|Ic߿Zn|Ic￿?loF{]Q`/,Ԣ7*{YnfjJa[`T03z}|Uwo;}o v'fJ۫FL<,c3&9[\Gjco%5.W޻&[Gjco% δ {Q_U'ӎZ6PN`}(Hm AwEPU!jKPU:@LqޑU7} ygo{Pbs{1?#[ `o-`/ /[ `o-`/|ҩ[DT@Z)U7!fTtc~Uax vu8)`/|a! AujU[:&}j,]FWr&+JJ:ވ0G~Q~P5ߋiL+*`y+7&z.%*6mӴ*{kAͥr.* Y+?{kzoboFތ`o-;ךތ`o-8sߋZ8?tߋZ`݊L{k{V$g2[ k"9U9RnnEr&uTcoӄ(p0+Uuu{?eLa|ol"9镱֨c%g22f>V]^d;[5S6fGW&g_ުw,n9+L6WF3 w i콒A {^uw [ ^I+ [ {/W&6`o-ld25z{iAb)sϙVѻL{7?Cbju^ io}ڏޕZww޻߻镡U+*_Mw~~H^yezeIvzBtϾYMdw ӆN״ꎪ%/{򎽰$za> UYe>cU:^c$6M&>Om g^׽h{woR#쭚O{8_(ӊ{+v^-9( n쭜;%+\^7ezy񥓞*uBeV3Ӫr6cU:^5^/٪a?_{[LOWUןYQF[ [ @MIViʩ W̿(P^޿b/S{Fag[DX{=y }[O>{#,7 ؋Fb7zmLׂҭǁ؛:d\oJGߛ:^+3~Uax {Xi1O{3qic_URg{_}O^yfmڦQjk`ofCЀiު3}Lnj9ɴkco(|yL;+LWl9+AUtVWߋڿ*ffcoNW(6/&;+j*]ʯ*f޾ޟ2Neڠ2P{3c>91$[@Zo0nicaof;i6ՃH}oXg n]Fo&բ_ho!vdN 'րKl(WػĖ;3R1{=%aw-}9sVg=aw-}9wGB%%Ym 9Ʊʷ@ػbmoLFf>W{ػK͞U7/؋{t6W;ݬĞ޴`/7 @bh{_gb?؋_m3tαk]ޟsػU54tα{GP{^c2_}U:{AEػXttػwmU:{AE .s .s .s .s .s .s .s~n*r|%"@x{rjo7\VIhM q{3s^YNϥ3wK؛S{u)gk~[o̸[l{Y+?1r6=-{cĞ޴8;V7j2͸nĖιmӮ7Zl4yf\X rn{B`o2;eQ\H{{w?tf]TIhn8Ͼmlu""ݐqu+{9w>Ca|3^o"Rhn7`oY{X,"ػĖ9ڹ/؋іna :j{7ڲ-{AG`/F[y/Fjl7I/[ g;krUNzZlc/b 'SmvqQt{ɲTl3Ja?1/xklzk ˢRrWOXYs=-zWպL{?װx{;WWsU9=߿toD7Oډs쭦ibN7]lco-ǽ^9r^XUl*]XYj Ž!uB:n<[^]({Ğz䜾X,I^s{>]~: s1cx9: rb{%^0ώ: ۛډ U˹V g: e_*]x97xʏ?K̳c: aP"{J 6^={M2pw&OyfE~' g)WSψe]Z{yx9޲XK,>/{ϋ-bnyFlEݭPv~8ψMyn3c;s _ YIgr`Ğ7vԱ7vk>Jz,wdܻ@ˇtd։ӉKX9%#`jq [M yIfooX:^K gHgDÒP+]3 U%˝Ϙ_M I=JܗrdTb~_18^\՛cÅ+-{y.#AGO ׽̜w' ڧxZ]e<ػ q݋yW<-.H\s^me8{R^`/T@*  H{R^`/T@*  HEKܵئ^yGY꩟tI{ų39ʹ3 6UMZyv&9m{?ʞ~bJتei57S8[W͝lըI ?[t4wD rnmO43] {_8Od6vjq9oV{L>rnmo#~ə[g!s ُҩ^^Ϸ`ȹd{[8cg09l|Ͱ^_3KTnG@?kUΜ\kV%ql߾n'@?k/^`/T>Ubt-.IENDB`PyChart-1.39/doc/pychart/module-tick-mark.html0000644000175000017500000001354310352146646022743 0ustar santiagosantiago00000000000000 9.1 Tick marks

    9.1 Tick marks

    class tick_mark.T
    Tick marks are used in conjunction with line plots ( see Section 9) to show where sample points are. Class tick_mark.T is an abstract base class, from which several built-in tick mark classes are derived. They are described later.

    Class tick_mark.T supports the following set of attributes.

    fill_style
    Type: fill_style.T ( see Section 16) Default: fill_style.white.

    The fill style.

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    The line style of the tick mark.

    size
    Type: length in points ( See Section 4) Default: 5.

    Size of the tick mark.

    Several types of tick marks are offered by PyChart as subclasses of tick_mark.T. They include: tick_mark.Circle, tick_mark.Square, tick_mark.Triangle, tick_mark.DownTriangle, tick_mark.X, tick_mark.Plus, tick_mark.Diamond, tick_mark.Star, tick_mark.Null. Specific instance of these classes are also defined for your convenience. Below is the list of such standard tick marks. They are referred to by as "tick_mark.name", where name is the labels below them.

    Image tickmarks

    PyChart-1.39/doc/pychart/failureannot.png0000644000175000017500000003172610352146635022106 0ustar santiagosantiago00000000000000PNG  IHDRf)PLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" IDATx E݀iD)z9PWfwP? @ 1@ 1@N:D P1@N:D P1@N:D P1@N:D P1@N:D P1@N:D P1@N:D P1@N:;Qjˌw1@Pdɛ t" H/SߏYtAiXSŸ^=tؿYf+ĠAq@#ĠzY7 J۱7}c"ycջF}sJkQ? M;. nDgEGgU49F;ue`-J7Fz"y'j8hŠ" ?*ڈ/ .kQU- nDgE3G <Ѽڠ6Gm}ƣ@DuL^\]8ɮnP`wBl1nXKL֨/i:/DyLGX*ݘS3cWuIu=0'ӇCqhtXc ҭsiER#0'S&^B*0Oz}Rl'%L#wZ;Ɩ1hNIE^t)YW ;ڎ8YKdy︱4Y?y CinnB'0u7rYd)~OyWcπPpJXf< a 9Ɔ/FuoFgE:O#2um ̷v#Н;0nf<OL$u`;;Ɔf.;"&·1h|3Lm.*mW*:0+ +n1(* ƫ>:`44(T`ipbi?ӕ aiUsE42 4{i0WtmaR\ZfSҿj^@){RWKr= <:Ҡ|4A[MZ3QACgT?AQ`S*J)ǿvu- 0^MtEGԀL!ԕEXgVE{ֱ:)+ uؕhtEsʞ"yfEţA~VrS8}usBv%Z6I.h68vF/ ",Dbd=XoZhn]_O=iIYhtStå__tnڱ =,À7 MY4ytB@6* EXҀ`u7zÀRB {1TOm ^Vfuǎ7@iYJ4XwXR!xip&aZY*\ڿzmY7J4MCWk!F=Er]hi\EeG2ݜuVֿv=̷P,@+tLxeM@3L} 0mAB)&, )aiUs҇>X. ]5gO=4>1pimu=SҠ4x6mžg{JXtL=ETR@Ao] ]q]DnO`eWt^ay9:tOBSl^i>wzEk=*J#% _AkҀxUDQ{*>R&`tTZP A1(ּ΄-x( oUM]7MPYW'##?$K= /VĠW'ʇfB+ UrS{2{DWY>^?5z.ߋ(V]e|͠+-3WaPy_̺PͣZbCv~gIpemp8 r{=O1s`*`ox_ mq5 |fʠ6@=IGo>Jy_ XV ,AHlb$U%B 2 ɿ,URW~7f]" * ͻloIz4H^ZAMŽkjD\ F4[pֵ wUF۠^j%s ( 3îb:b&cg1PY\tm% ÝJldz\{U7'ĵE;ȓ9U>a ڽRQ+/t> tCϪO pբ팹 7|]Լ9o W E09r3LSf9qtyS;K54Z"\Ϣtco(K&[)QЦN"h,T ,:|yݥ 0%oBkVC]CZ/HA&. 1pT] @)(biI_CG J+`c 15τ/#B "DپT1HC^—>\:RP# JAZgqdB'_To߰&tbʅd?+ vFU 1KL!:fbp%rUӆR"ZY1 !L.5a4kR!_u\N4e-h B JB.ZQҡ#7|Sfr!s0ƞTH!EJsR%80KbP8 C8Ə-8 8BpS0P>yz,/ 4cΓRv 9pM'8b 0[ntWj]aobK003n9#iF:{RN8"FAcпx@*(lT10P]BA/l}z ~@ɑ]֙xf1g8Q\6d2w*Gv8͍e.~ ӧ@gw& :`o5Iو=`GyT83ꆻcxsu P;t> S+H @H]s S}=d.ˢ(%Iɍ=4vVjэ%[V1Ir O>n#vqt8ܗL&z_flaP*ճG& jyy.Gmց GK~x4M׈ TV")^sɆ=l ħm9pM-h2$H8tu=]P[@wu('*E5Ԥna%D O``.C/1ˤnLv!O'0PO\4m =q/; 4ux1?0asnk>0#HTWpaVx:`F27 1@fQPヱMe˝vp9DjǧOnWW{71@db̴.5[4[ * 7Kf#p<љGNU]"_:03Lw6j;T1xFA:LP8!0}Q^B +3 vtK 1@ Sl1>bJ f3-ĠIX)z[rYY !  ~LA? f ĠA@3F#E•B PR}r$0t5S~zC .v# B F[8!ٍĠEbEiE PB``HbNu1hЂY0vvm @ 1%;S2#vF}_)P)R+'hˤY ) -ע:k:c ( 1 dmh*ES`0iq5Z۞<,J4{ip$"iu{_^ I<!Qy_t} =q&茶ZOB0h~ Y ̑{F=G!avm?3h) `Pxgo_Qka@lh >w^C $n a4#7w|!TW6<{yF`=E}ԫR4 g Znub*G ,lVˀcu61p;]Wvd`:Q`4* N`!ǠY1 o˵h-U:Q?JziB b2tj`A[*C/9(0\I?AS =r) R' SRI. 6~ eKs%o=-vc0Z ;BL(̬2*H Qϭ6OK`P ҿ`p t`€6븓IF x)7قtE9^c`?Ji ]﷙]^M仂A2 7[JcZ\% _;Xaϖto<> ;"z1Q+q-^`_Ma7} l mU#Gr}Q 18]y[ s"Vj63^v Alys'z{=$^DT,?J"!q`̶ц.&1| HiZ۠-p>TWvƋĠBcIe 1R/ :%e\͇SN`%!\0୤ss<*S:|ʟQ821P^3L0w^R֡@4J#C"4Dz}tׄ֡DY.{#:} JyY5>1SƂ uS`cRTy?Wu1kΜuhފ'֡ɱޠKp *E 3-XQ:4({yXezR&i3n/6&"9k:pEЀcpCiaTqu FT{8 QE%cAma€fd/ڪ4֡ǀmAY2VdH ٔ {IAMؒ9]8N, RbD2ۮ/$>Yn4Us֜Y eC%ؽg5fS=rK%ȍ>?rwΚ3eCA>Hj.h=*Eew rqn|oЙ7({`p A' rɖ!-qhW4MK)ߟ371g0"'P8\vL:mATc ~sq1xE1/m )tQ\K!yk$L&͵'L̓e5<;QK9v1ٚaϤQaϢqh r}L0{Ta /2LbP}EBp%̢,rnڽO(h1Cap_{?L| ₴B4HbA#ӹz]ԧ?EC<Qlʸd+B47Hc`9'N9prꙜNN,Wk{1nB'f/q=,8Aɡ&DpIF2;@ 1p!`DW^aN}VBFi "Ɂ]$̀A.0ZsO{r7/Kˎ3 6"V`"'`4 :8sT}˷ n.DˬH14@v>d 80%$odX}dMy^ #߿n.7r*) 3B4јl n0M$Pǩo]I ${'m ~cөEEP ;Ws*Q)*q!o ~=(\Hvw!TgRf!`p 4"-xeF]yŭًRu8{iBPh+ǠmizD@ pH1"N`0Hw^kTAx[c{%*m"4!q^91hajjQU!dpӉy'?6 G1Ia&q7MKX[ >:,D$407hHUl⊲WļR$ȶ@,0(;'[<0' k7mU]Hvs!| ؤ@s0ry: d18'j|*J1H̘; s$t,8o\B4 V^QyDN0Giˢn'VL۝><C%}i]9* ;d7M7n&[J}*D4>zϩo3dQ> 1ϿoX ` G |ZM3|&*ΟT0H:JHK&׶QMNm>JbW1K.?A䟃 *5bnx~X#VF 0.>_`-/~-%Az^B޷o0* yQ5+8Zy@E0L̤6 z*Aݥ鳿I$4fdyi۵?*t6Š2ε?ASB IĻ\pba[ARm={4aЋ,υF4wwe7'hqV0ޛ8 7==ocfq&!4bw vV& M D){7|0af )h;;` eש Mè@&SL\( j 1 FG4Ô|6Q΃k[$Tϼ}GIDAT B%s1*_^L\$0֗Y'$&ahXC0[򁤷T9=!Q3D}08-̶+ bFtnD_Re~<35 5`I>q$t9~ހ|x83h n;J$^b oK(Ġ& lo[aYx:.bM}5Mrhc^9vSDlxWS} ϩceݢ<0Z&YFϦE 3-NPA2f[Yyo9֧1H}]=IϺ aEͧ2</$o޿yI8D¿{AX\"uyE1+W+_5SU D3\2F_08n!bW>} axH Dp8U!0 2׵[F]tbL6x!J-ar hXL0w˿1xt3{JWN`ube6Q^J ϊ9ɓsnyZ ϊ$3uhOGNU!$Z&bI+ nX>648 \@* Ġ4)QF VӀM,𞢄[ӆh'ᳺka}_A^` g_PbM#϶/otvD7Čg(bB[$  fy0hE@XAb@ aM=D  $1c6`$xFV0QhLO'$8uӨSv܍Ѝc 1c J`7Č4⃰$62`J $1cA/@Io 1c>|Lo381@= 0p${ԯkHm+ "2C[5D\Io +m;!݀Lz@XAu"} FqG @3VPǶӯT;!Au(ԥz6IC@ P(ƀtݼvT9xNnt @j#@XA!ɭFG*`Hb 1FSH7w#y>kLz@XA+DKglԇOw=# +(ĀRUyُ2b۩SED70Q)SdG6ՐR( ٩| ꆘyOb_8 ~R;ۜ|Kl׏<ȣbK ȶAx`0RfJN*\:aL880jQ/kW1=Edcqz%6B3*߾zC@1 d_(  w5|Kq_@10?#R]|tS')-/8`/ &t>.@0u9|-^t'Ac|r8}b޸Q\>6B @析Oy֌~g =$Κ35c+ ^Jr~;33}8~6nq 'Mq}΃YLtcm֜ɳfbZ 6HAGT,&3qθsDk\b*Cn+@4*_HzFmb2u@/AޓS&ke S i!9VNv&50׳趁~429\a7>Y XBϽo91$^ņ)]@_hQ0o&}{m\#Jϓثd{Jߌ=PQy;{qL<wí;M,L//<}H?V/|\ϻIXnIKV5b)%i a0Ѝoe#;)@107gp[XT׍ΚLYXxl;s<ঘN!)X*@o+Lon`iClBixo0kL,I* DFI{וowQkVYߋ1>uޱY^Xvu2ЪDsa˳D_1R`ߢdcOe!f%e(\L3a/%CC!`coUڤ-u04o5ݴıO]+EL!}e/À:oլm&|\ g3CT`?7f@c|kt4K ߪ4 -u9Uⳙ_x#-f]h& x%:flε$kc"ϝ\xl:6 }^L3a k}Ui8B*>H4C|)rl[}A*}^CSaP3mȻl*g{lpga*QE>5+̐z54墪NDt\EW.y]+FiY 6߶]8DiY T7Ѯ{r4KƩzZAгj|zKh] {K/u1PCRZ¡g)txn-Aг:nv<̧+zB͎TU7;XKc0,Z3*bBRbB!(Ԫ *!(bB-RbB!(Ԛ J!(bB-RbBhPsi= 0@U 1@#U%1@P P'bB u"(ԹG~lJ+K1QZ ]dn(Okap%FG|Ug~YX| `[P4)*'< 'a#XWJ 4:Ԯ0m>'v1IQf@lv7BT]sr~C*Ma: Lأ%2@ JU|2[&Sai2 HlD4#6'7[ٗ&J kTÀ"r*0@%4|`cqz1jC.$ˆ*0}\&;Өm u`1bJh2 2@ˀԄSЬm1@i: 8;&NE(Zo󢹨I4Oc=!++E/Ih2 CO#vnU!I1@}l©AN 1@D P1@N:D P1@N:r$+IENDB`PyChart-1.39/doc/pychart/module-theme.html0000644000175000017500000003146410352146646022165 0ustar santiagosantiago00000000000000 13.1 theme - Defining the default behaviour of PyChart


    13.1 theme - Defining the default behaviour of PyChart

    You can change PyChart's behavior by setting variables in the module theme. After setting values, you must call theme.reinitialize() to reflect the changes to other parts of PyChart. Notice that these variables are meaningful only before the first call to area.T.draw() (see Section 6).

    theme.scale_factor = 3
    theme.reinitialize()
    

    The below are the list of variables in the theme module that you can modify.

    scale_factor
    This variable defines the scaling factor. The default value is 1.0, meaning that one point in PyChart actually means one PostScript point. Setting this value to 3.0, for example, makes PyChart draw everything three times larger.

    See Also:

    See Section 4 for how the length and the coordinate system are defined in PyChart.

    output_format
    This variable sets the encoding of the data produced by PyChart. The value of this variable must be one of the following strings.

    ps:
    eps:
    Encapsulated PostScript. This is the default.

    pdf:
    Adobe Page Description Format, or PDF.

    pdf-uncompressed:
    PDF without compression. This option should be used for a debugging purpose only.

    png:
    PNG graphics. You need to have ghostscript (gs) installed to use this option, because PyChart internally calls ghostscript to convert PostScript to PNG.

    See Also:

    http://www.ghostscript.com/
    See this web page for more information about Ghostscript.

    svg:
    Scalable vector graphics.

    See Also:

    http://www.w3.org/Graphics/SVG/
    See this web page for more information about SVG.

    x11:
    Interactive display on in X window. This format works on UNIX-based systems, but not on Windows. You need to have ghostscript installed to use this option.

    When this variable is not set (or is set to None), PyChart guesses the format from the file name (theme.output_file; see below). Failing that, PyChart will generate an encapsulated PostScript file.

    output_file
    Sets the output file name. Without this option, PyChart sends code to the standard output. If you want to produce multiple charts from a single Python source file, use canvas.init(file) (see Section 21).

    use_color
    The default value of this variable is False. If the value is True, PyChart colorizes some of the default objects. If the value is False, PyChart uses gray scale for the color of these objects. In particular:

    • The standard color list (colors.standards) will include all the colors listed in X's RGB file. So you can use something like "color.slate_blue"1. See Section 15 for more about colors.

    • The standard fill style list (fill_style.standards) will be colorized. Thus, if you create a bar plot without explicitly specifying its fill style, you will see colored bars on the canvas. See Section 16 for more about fill styles.

    • The standard line style list (line_style.standards) will be colorized. See Section 14 for more about line styles.

    default_font_family
    This variable sets the default font family used when drawing texts. The default is Helvetica. See Section 17.1.

    default_font_size
    This variable sets the font size used when drawing texts. The default is 9 points. See Section 17.1.

    default_halign
    Sets the default horizontal alignment of texts (Default value: /h). See Section 17.1.

    default_valign
    Sets the default vertical alignment of texts (Default value: /v). See Section 17.1.

    default_angle
    Default text-drawing angle (Default value: 0). See Section 17.1.

    default_line_height
    Defines the separation between two text lines. See Section 17.1.

    default_line_width
    Set the default line width, in points ( see Section 4). (Default value: 0.4) See Section 14.

    debug_level
    This variable controls the verbosity of messages from PyChart. The default value is 1, meaning that PyChart only displays error messages. The larger the value, the more verbose PyChart becomes.

    bounding_box
    This variable, if set, manually sets the bounding box of the chart(s) produced by PyChart. It is a four-tuple of numbers, i.e., (xmin, ymin, xmax, ymax). PyChart usually calculates the bounding box of a chart automatically. Thus, you set this variable only when you want to override the calculation by PyChart, or PyChart screws the calculation. The latter situation happens especially when you use really thick lines for drawing. See also delta_bounding_box, described next.

    delta_bounding_box
    This variable, if set, adjusts the size of the bounding box of the chart(s). It is a four-tuple of numbers (xmin, ymin, xmax, ymax). Each of the number is added to the bounding box computed by PyChart.

    If both bounding_box and delta_bounding_box are set, then delta_bounding_box is ignored.

    After changing any of the variables described so far, you must call the reinitialize function to reflect the change to the rest of PyChart:

    reinitialize( )
    This procedure must be called after setting variables in the theme module. This procedure propagates the new values of the theme variables to other modules that depend on their values.



    Footnotes

    ...color.slate_blue"1
    In fact, you can use these color names in gray-scale mode as well. They will appear in some gray color though.
    PyChart-1.39/doc/pychart/drawing-canvas.html0000644000175000017500000002260510352146643022476 0ustar santiagosantiago00000000000000 21.3 Drawing other objects on canvas


    21.3 Drawing other objects on canvas

    The objects of canvas.T class and its subclasses provides several methods that can be invoked manually to draw variety of things if you desire so. These methods take Postscript points as the unit of X and Y coordinates, as described in Section 4. (These methods obey the scaling-factor specifications).

    line( linestyle, x1, y1, x2, y2)

    # draw a line segment from (10,20) to (100, 200)
    can.line(line_style.blackdash1, 10, 20, 100, 200)
    

    polygon( linestyle, fillstyle, [(x1,y1), ..., (xn, yn)], shadow = None)

    Draw a polygon points, with linestyle ( see Section 14), and fill with fillstyle (see Section 16). Parameter points is a list of coordinates, e.g., ((10,10), (15,5), (20,8)). Value of linestyle can be None, in which case no line is drawn on the perimeter. Value of fillstyle can also be None, in which the internal of the polygon are left undrawn. Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle (see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

    can.polygon(line_style.default, fill_style.default,
                   [(10, 20), (100, 200), (300,300)])
    

    rectangle( linestyle, fillstyle, x1, y1, x2, y2, shadow=None)

    Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

    can.rectangle(line_style.default, fill_style.default, 10, 20, 300, 300)
    
    ellipsis( linestyle, fillstyle, x, y, radius, y_elongation=1, start=0, end=360, shadow=None)

    The start and end angles are specified in degrees; i.e., between 0 and 360. Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

    round_rectangle( linestyle, fillstyle, x1, y2, x2, y2, radius, shadow=None)
    Draw a rectangle with rounded four corners. Parameter radius specifies the radius of each corner.

    Parameter shadow is either None or tuple (xdelta, ydelta, shadowstyle). If non-None, a shadow of shadowstyle ( see Section 16) is drawn beneath the polygon at the offset (xdelta, ydelta).

    curve( linestyle, [(x1,y2), ..., (xn, yn)])
    Draw a Bezier curve.
    show( x, y, text)
    Draw a text on the canvas at location (x, y). Parameter text supports font manipulation, as described in See Section 17.

    verbatim( string)
    This procedure outputs an arbitrary string to the output file.

    PyChart-1.39/doc/pychart/contents.png0000644000175000017500000000121110352146643021235 0ustar santiagosantiago00000000000000PNG  IHDR D`PLTE|si_VLCv:m0c&YPFy =p3f?0bKGD{lIDATx͒ݒ  e1I7Mgg3xF>`|dydlO'>hGBaaV8 +V՗v/{R38wJh"Uo.i|M-I3S$e|Eo3v R,߬3.7w`ZjKvrAOPiE;JE:NpHG  uq",4Z`9Kpt9<}fvl0M-zX4- (, YLڎ/]k2@{zШFIX҅MHE2°H늹X *-ґ)]88; ͔'`)bQY\0mY'RE&0N(\z<.Ÿ*'fݘ\ȀRq;9paCg6Prwr'Tb]H.`&\zĒas8(6ˋT͘XLWJN+61*.X)$E{%M4MB/Fl)orɱb1Trی>$$\\pq~#-n{ A.2e25DK(cY Z\y=oBcA. <4Ĩ MŶAHXڗuCQtZs2F`i o2X$PlD~Q{ x$ 1'WMreC&sĨl9 =KlS dzkL=pgX(K4h*N@~&xZgdXZ ,Ԅr<8 Knt$d+DkHp<vac#o,Hşa g\7prV &uY^ Kˇn_R &A(xΏP?.ؖsE0zvבTҠR[y\TPTTP,& aeI`5uWY;F7zhB9W-#M yբo=Ѡ҄rkRN?] OgT`,RKqEFEX{ g`X,ΩXxr2[XJ.e!Rɶ)ǺL%K.j THX.c FX*(K2Z95m2%ӡwOJːkjbA(1$sCP;\T*XJ.;YXj&c;tPnc{eBk/F詔@EհK*T ,kN[Ӓ.Epb!mY8J\w%,':pK ƙ6;J)\\VBKֿI9ee^.c^d1.m 3ݯB*p7z2yXk O\.#Jk*Sa9Rr(Ok&q'Q B<v4ewBx07j]\X&ۍ41^es%,DiP=OFnө` urmJٔ2hXTN u6\M0R&Q CaTE2ObAM2 +=xd'yXxѱS{Xu,3RNҳ,OĒ?OevR}k9 #%gJX)u.4I .·ޕ$ᇹ KX\~z,[X,flo!#sXd"$Uys7"!L`K4V ر=r.]c ,rrknٮ~Bf.Pjo(`>(vlK^FD/aظZʁe-M]r5<%'?Zj)JzlĺR_6t2C(=, )+l#Qâ0 +_ -j[QYn?.CP;kİ $_>5%,,OXX*6kWz&ut$̛k _c)3˪e }*,^+DZXOc];H%tqԑX ]8jQW~9XTjf,}_{7,,`y4[ewPtɍˉCZf.daybj xĖ!gNaqUjսOҾhM'PKe'V}Ej|h}=BF?ւ..kQwv;˄hJжj+:^#n[V /_|}dٟX?g(&-X^{hy#֗o mScGZ`y󱷃k=-}BZò5cqVwjDc|MZ߈?˿&?ނֲ~X@amdhAaT54c/IENDB`PyChart-1.39/doc/pychart/module-line-plot.html0000644000175000017500000003062210352146645022760 0ustar santiagosantiago00000000000000 9 Line and scatter plots


    9 Line and scatter plots

    class line_plot.T
    This class raws a line plot. By specifying None to its line style, you can also draw a scatter plot.

    Image linetest3

    Sample line plot

    Below is the source code that produces the above chart. ../demos/linetest3.py

    from pychart import *
    theme.get_options()
    
    data = chart_data.read_csv("lines.csv")
    
    xaxis=axis.X(label="X", tic_interval=10)
    yaxis=axis.Y(label="Y", tic_interval=10)
    ar = area.T(x_range=(0,100), y_range=(0,100), x_axis=xaxis, y_axis=yaxis)
    eb = error_bar.error_bar2(tic_len=5, hline_style=line_style.gray50)
    ar.add_plot(line_plot.T(label="foo", data=data, error_bar=eb, y_error_minus_col=3),
                line_plot.T(label="bar", data=data, ycol=2, error_bar=eb, y_error_minus_col=3))
    ar.draw()
    
    tb = text_box.T(loc=(40, 130), text="This is\nimportant!", line_style=None)
    tb.add_arrow((ar.x_pos(data[6][0]), ar.y_pos(data[6][1])), "cb")
    tb.draw()
    
    ar = area.T(loc=(200, 0), x_range=(0,100), y_range=(0,100),
                x_axis=xaxis, y_axis=yaxis, legend=legend.T())
    ar.add_plot(line_plot.T(label="foo", data=data, data_label_format="/8{}%d"),
                line_plot.T(label="bar", data=data, ycol=2))
    ar.draw()
    
    Image scattertest

    Sample scatter plot

    Below is the source code that produces the above chart. ../demos/scattertest.py

    from pychart import *
    import random
    random.seed(0)
    
    def randomdata():
        data = []
        for i in range(0, 30):
            data.append((random.random() * 1000, random.random() * 1000))
        return data
    
    theme.get_options()
    chart_object.set_defaults(line_plot.T, line_style=None)
    
    tick1 = tick_mark.Circle(size=2)
    tick2 = tick_mark.Circle(size=2, fill_style=fill_style.black)
    xaxis = axis.X(label="foo", format="/a-60{}%d")
    yaxis = axis.Y(label="bar")
    
    ar = area.T(x_axis=xaxis, y_axis=yaxis,
                x_grid_interval=100, x_grid_style=line_style.gray70_dash3,
                legend = legend.T(loc=(350, 50)), loc = (0, 0))
    
    ar.add_plot(line_plot.T(label="plot1", data=randomdata(), tick_mark=tick1))
    ar.add_plot(line_plot.T(label="plot2", data=randomdata(), tick_mark=tick2))
    ar.draw()
    
    xaxis = axis.X(label="foo", format="/a-30{}%d")
    yaxis = axis.Y(label="bar")
    ar = area.T(x_axis=xaxis, y_axis=yaxis,
                x_coord=log_coord.T(), y_coord=log_coord.T(), loc = (200, 0),
                legend = None)
    
    ar.add_plot(line_plot.T(label="plot1", data=randomdata(), tick_mark=tick1))
    ar.add_plot(line_plot.T(label="plot2", data=randomdata(), tick_mark=tick2))
    ar.draw()
    

    data
    Type: any Default: None.

    Specifies the data points. See Section 5

    data_label_format
    Type: printf format string Default: None.

    The format string for the label printed beside a sample point. It can be a `printf' style format string, or a two-parameter function that takes the (x, y) values and returns a string. The appearance of the string produced here can be controlled using escape sequences. See Section 17

    data_label_offset
    Type: (x,y) or None Default: (0, 5).

    The location of data labels relative to the sample point. Meaningful only when data_label_format != None.

    error_bar
    Type: error_bar.T ( see Section 9.2) Default: None.

    The style of the error bar. See Section 9.2

    label
    Type: str Default: "???".

    The label to be displayed in the legend. See Section 6.3, See Section 17

    line_style
    Type: line_style.T (see Section 14) Default: By default, a style is picked from standard styles round-robin. See Section 14.

    The style of the line.

    tick_mark
    Type: tick_mark.T ( see Section 9.1) Default: None.

    Tick marks to be displayed at each sample point. See Section 9.1

    xcol
    Type: int Default: 0.

    The column, within attribute "data", from which the X values of sample points are extracted. See Section 5

    y_error_minus_col
    Type: int Default: 2.

    The column (within "data") from which the depth of the errorbar is extracted. Meaningful only when error_bar != None. See Section 9.2

    y_error_plus_col
    Type: int Default: -1.

    The column (within "data") from which the height of the errorbar is extracted. Meaningful only when error_bar != None. See Section 9.2

    y_qerror_minus_col
    Type: int Default: -1.

    See Section 9.2

    y_qerror_plus_col
    Type: int Default: -1.

    See Section 9.2

    ycol
    Type: int Default: 1.

    The column, within attribute "data", from which the Y values of sample points are extracted. See Section 5



    PyChart-1.39/doc/pychart/cliptest.png0000644000175000017500000001031010352146636021231 0ustar santiagosantiago00000000000000PNG  IHDRAkPLTE?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU pHYs  ~tEXtSoftwareGNU Ghostscript 7.07" EIDATx @7ƸLD JP ]IG(hMq`caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!\[Cd Yr~~O$ܲ[҃?Ҙe*?Mi;{]:DAJhIMޓ?xC#R>#YMV)PUš/f%Ys wϮ6䫾 %zڲ )3W[Y9_3,N <@?>O{"U~+#-l * ԱU@eEj$CVV L֏H}zЅN:oS +#A^•1 \lXJ[C:vDW'OHYfZ?ق74,!+Ԩ:)V /m JC0E}/˗ʢ>d~2fhbvM J.UC\m)dUɬ@CD{hXZp"d=,#Vl{ݣX,pPۼ%—o % Q,Nb gY\˂ZTq9- E,9HoJgԣ6]eUK8# $—:.#HVFಐ!j "+e.+o<[DJ9.^>6e-u7ߟ>ˇ!A1ϑSe7]Li~n ʄJyNP^̰)&Z줸wYKt~־k fF uMGmi٭v/N/70%:~P\uI_eaq;dI&k w/-KF 9dsLq|6湼\IHJlȊ:a8o5䈤̮KgYOaөηlztYBs]tgf|~RR1 XSB78EeHPRx$6CLlC,Ae DݠZ;d#{8tY꒹!&zS7D>vY"leg|OsVUeq#be]sak(;%)ɲmer󕥡,xVP=RpW춢ܴNWa#1OJz{Ac/G$*Ueu瀜O)>Ag W0]Hjq%ZTWC2O>5bx/G# O,lpE 6dY0rZ:]V wv4-bkZgY}ƛ=3~+WӺ˺}Ĺ=y"WlIVxɿ|1(!ޛJ-9*eWY1Y1#\%'k\*9{ DWr:چ\d0Wie7fZ"k͌ʇ!kӦ/t J{AMťd`Q8nd/~ Y+c:&+fS:J,l=l mnYeJ&bWc dE&K̲/(0YY ".?MVM4m9A "p˪omL"8dU'C ,z!E7+FY c7h]hbxA ,d)Mc%aAe\ZY$0jESowYpː7 0Y?=u0rC~7*| /k+FۂV8VEIIdy㳭\ID|p̂U hpae{і+&?X}a`,,Wg^hkxD,mPjmxA y5R]$ @/zVB|Rlr՞+)0Y DԲ#d遶f/خ,U?veɪk1&KthpxA ݃cU6&KdU>ƙ.^4gDe宠me9dˢ/Q9Y~ :vYghҕfYKS ,᎔M )&kS,kRAV}{^dED"\ߤ5MVP9vڹn8&rob߱,&DF}u0~/:!km 4&xuݲÐy <&(1uT$sIdQ"+MH`seuAYlU@㞣Il>XBǬ¶ִBy!:6q5?;rLV~M*8gsp io/j 5nI'Lt$۵D&*Xkw/A;f`1ɴޟoB֯X1exM4̄<(68KM,~y |XOVr5-+>Owwd'Lt -mlSp/ NI1 -maw(LtDBhyH |t]*Uh#98)9`Ϸy@,cْle4h$6t7Wo" C0#zA+$WɲL(W$L,WMbK,Ohl>t[Dr% c7cdm~qN:1.-Y|gO,C),%qO^B!Fز,>M9Թ زE\Q,nPovJXP q݇`&o|%D'Cw%՟eYB#mg 9ߍϲGڒ5_iOްERP*_"#ld'WREdi(3:PlC 0L%Fjei]WWgX[X+TUZ*PTԂ /RHhWCKhPjoUj5CW%r%DBkit&VYJY(]uO3;kVʂ35Ȫ^F<u͢^wǓA7{޾uUdAݵߒp¾nnY"Br}ZYGL""E/uinIENDB`PyChart-1.39/doc/pychart/module-axis.html0000644000175000017500000003002310352146644022013 0ustar santiagosantiago00000000000000 6.2 Axes


    6.2 Axes

    Module axis defines the look of an axis as well as grid lines. Two classes, axis.X and axis.Y, are provided by this module.

    class axis.X
    This class is draws an X (horizontal) axis.

    draw_tics_above
    Type: int Default: 0.

    If true, tick lines and labels are drawn above the axis line.

    format
    Type: printf format string Default: "%s".

    The format string for tick labels. It can be a `printf' style format string, or a single-parameter function that takes an X (or Y) value and returns a string. The appearance of the string produced here can be controlled using escape sequences. See Section 17

    label
    Type: str Default: "axis label".

    The descriptive string displayed below (or to the left of) the axis. See Section 17.

    label_offset
    Type: (x,y) or None Default: (None, None).

    The location for drawing the axis label, relative to the middle point of the axis. If the value is None, the label is displayed below (or to the left of) of axis at the middle.

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    Specifies the style of axis and tick lines.

    minor_tic_interval
    Type: number or function Default: None.

    When the value is a number, it specifies the interval at which minor tick marks are drawn. Otherwise, the value must be a function that takes two arguments, min and max X (or Y) values. It must return a list of numbers that specify the X or Y points at which minor tick marks are drawn.

    minor_tic_len
    Type: length in points ( See Section 4) Default: 3.

    The length of minor tick marks. The value can be negative, in which case the tick lines are drawn right of (or above) the axis.

    offset
    Type: length in points ( See Section 4) Default: 0.

    The location of the axis. The value of 0 draws the axis at the left (for the Y axis) or bottom (for the X axis) edge of the drawing area.

    tic_interval
    Type: number or function Default: None.

    When the value is a number, it specifies the interval at which tick marks are drawn. Otherwise, the value must be a function that takes two arguments, min and max X (or Y) values. It must return a list of numbers that specify the X or Y points at which tick marks are drawn.

    tic_label_offset
    Type: (x,y) or None Default: (0, 0).

    The location for drawing tick labels, relative to the tip of the tick line.

    tic_len
    Type: length in points ( See Section 4) Default: 6.

    The length of tick lines. The value can be negative, in which case the tick lines are drawn right of (or above) the axis.

    class axis.Y
    This class is draws a Y (vertical) axis.

    draw_tics_right
    Type: int Default: 0.

    If true, tick lines and labels are drawn right of the axis line.

    format
    Type: printf format string Default: "%s".

    The format string for tick labels. It can be a `printf' style format string, or a single-parameter function that takes an X (or Y) value and returns a string. The appearance of the string produced here can be controlled using escape sequences. See Section 17

    label
    Type: str Default: "axis label".

    The descriptive string displayed below (or to the left of) the axis. See Section 17.

    label_offset
    Type: (x,y) or None Default: (None, None).

    The location for drawing the axis label, relative to the middle point of the axis. If the value is None, the label is displayed below (or to the left of) of axis at the middle.

    line_style
    Type: line_style.T ( see Section 14) Default: line_style.black.

    Specifies the style of axis and tick lines.

    minor_tic_interval
    Type: number or function Default: None.

    When the value is a number, it specifies the interval at which minor tick marks are drawn. Otherwise, the value must be a function that takes two arguments, min and max X (or Y) values. It must return a list of numbers that specify the X or Y points at which minor tick marks are drawn.

    minor_tic_len
    Type: length in points ( See Section 4) Default: 3.

    The length of minor tick marks. The value can be negative, in which case the tick lines are drawn right of (or above) the axis.

    offset
    Type: length in points ( See Section 4) Default: 0.

    The location of the axis. The value of 0 draws the axis at the left (for the Y axis) or bottom (for the X axis) edge of the drawing area.

    tic_interval
    Type: number or function Default: None.

    When the value is a number, it specifies the interval at which tick marks are drawn. Otherwise, the value must be a function that takes two arguments, min and max X (or Y) values. It must return a list of numbers that specify the X or Y points at which tick marks are drawn.

    tic_label_offset
    Type: (x,y) or None Default: (0, 0).

    The location for drawing tick labels, relative to the tip of the tick line.

    tic_len
    Type: length in points ( See Section 4) Default: 6.

    The length of tick lines. The value can be negative, in which case the tick lines are drawn right of (or above) the axis.

    PyChart-1.39/doc/Makefile0000644000175000017500000000144010354321416016657 0ustar santiagosantiago00000000000000PYCHART_DIR=.. PYTHON_DOC_DIR=$(HOME)/Python-2.4.2/Doc all: pychart examples pychart: pychart.tex $(PYTHON_DOC_DIR)/tools/mkhowto --html pychart.tex $(MAKE) markup pychart.pdf: pychart.tex $(PYTHON_DOC_DIR)/tools/mkhowto --pdf pychart.tex pychart.tex: template.tex doc.py make -C$(PYCHART_DIR)/demos colorpng PYTHONPATH=$(PYCHART_DIR):$(PYCHART_DIR)/demos python doc.py --pychart-dir=$(PYCHART_DIR) template.tex >$@ markup: for f in pychart/*.html; do echo $$f; python markuphtml.py <$$f >foo.html; mv foo.html $$f; done clean: rm -f *.pyc *~ *.html *.info tmp.texi *.png *.eps pychart.tex rm -rf examples html demos demo: PYTHONPATH=..:../demos python demodoc.py examples: examples.py $(wildcard ../demos/*.py) python examples.py index.html: index.html $(GIFFILES) gtml index.gtml PyChart-1.39/doc/README0000644000175000017500000000036210354321345016102 0ustar santiagosantiago00000000000000Compiling python.tex requires following packages: - The Python source package. Download it from www.python.org and set its Docs directory in PYTHON_DOC_DIR. - LaTeX (TeX). It's most likely to be knows as 'tetex' on Linux. - Linux2html. PyChart-1.39/doc/examples.py0000644000175000017500000000326710354321374017423 0ustar santiagosantiago00000000000000import sys sys.path.append("..") sys.path.append("../demos") import pychart.doc_support from pychart import * import list_sources import re import dircache import os import posixpath target_dir="examples" cwd = os.getcwd() python_path = "python" if sys.platform == "win32": python_path = "c:/Python22/python" try: os.mkdir(target_dir) except: pass index_fp = open(target_dir + "/index.html", "w") index_fp.write("pychart Samples\n\n") for file in list_sources.list_sources("../demos"): mo = re.match("^(.*).py$", file) assert mo basename = mo.group(1) pngFile = "%s/%s/%s.png" % (cwd, target_dir, basename) smallPngFile = "%s/%s/%s-small.png" % (cwd, target_dir, basename) src_file = "%s/%s/%s" % (cwd, target_dir, file) os.environ["PYTHONPATH"] = "..:" + os.environ.get("PYTHONPATH", "") if not os.access(pngFile, os.R_OK): print "Creating ", pngFile os.environ["PYCHART_OPTIONS"] = "color=yes scale=3 output=%s" % pngFile os.chdir("../demos") os.system(python_path + " " + file) os.chdir(cwd) if not os.access(smallPngFile, os.R_OK): print "Creating ", smallPngFile os.environ["PYCHART_OPTIONS"] = "color=yes scale=0.6 output=%s" % smallPngFile os.chdir("../demos") os.system(python_path + " " + file) os.chdir(cwd) if not os.access(src_file, os.R_OK): os.system("cp ../demos/%s %s" % (file, src_file)) index_fp.write("

    \n" % (basename, basename)) index_fp.write("

    Source code") index_fp.write("\n") index_fp.close() PyChart-1.39/doc/doc.py0000644000175000017500000001366110354321416016346 0ustar santiagosantiago00000000000000from pychart import * import pychart.doc_support import optik import string import sys import re parser = optik.OptionParser() parser.add_option("-S", "--ps", action="store_true", default=None) parser.add_option("-D", "--pdf", action="store_true", default=None) parser.add_option("-X", "--pychart-dir", action="store", default=None) opt, argv = parser.parse_args(sys.argv[1:]) ftype = "png" pychart_dir = ".." if opt.ps: ftype="pdf" elif opt.pdf: ftype="eps" if opt.pychart_dir: pychart_dir = opt.pychart_dir def resubfunc(mo): typename = re.sub("_", "-", mo.group(1)) return "\\xref{module-%s}" % typename def xxx(mo): xx = "var" return "\\" + xx + "{" + mo.group(1) + "}" def format_doc_string(str): str = re.sub("<<([^>]+)>>", resubfunc, str) str = re.sub("<([^>]+)>", xxx, str) str = re.sub("\|([^|]+)\|", "\\code{\\1}", str) str = str.replace("#", "\\#") str = str.replace("%", "\\%") str = str.replace("@pxref", "\\pxref") str = str.replace("@xref", "\\xref") str = str.replace("@code", "\\code") str = str.replace("@samp", "\\code") str = str.replace("@var", "\\var") str = str.replace("@example", "\\begin{verbatim}") str = str.replace("@end example", "\\end{verbatim}") str = re.sub("@cindex ([^\n]+)", "\\index{\\1}", str) return str def outputClassAttrs(moduleName, className): x = pychart.doc_support.modules[moduleName] v = x[className] keys = v.keys.keys() keys.sort() for key in keys: if key[0] == '_': continue val = v.keys[key] type_str = pychart.doc_support.stringify_type(val[0]) print "\\begin{memberdesc}{%s}\n\\textbf{Type:} %s" % (key, type_str) if False: print "\\label{%s.%s.%s}" % (moduleName.replace("_","-"), className.replace("_","-"), key.replace("_", "-")) mm = re.match("(.*)\\.T$", str(type_str)) if mm: print "(\\pxref{module-%s})" % re.sub("_", "-", mm.group(1)) if len(val) > 3: print "\\textbf{Default:} %s." % format_doc_string(val[3]), else: print "\\textbf{Default:} %s." % format_doc_string(str(pychart.doc_support.stringify_value(val[1]))), print "" print "" if len(val) > 2: print format_doc_string(val[2]) print "\\end{memberdesc}" #print "@end multitable"; def copy_file(src, dest): sys.stderr.write("%s->%s\n" % (src, dest)) infp = open(src, "rb") outfp = open(dest, "wb") outfp.writelines(infp.readlines()) infp.close() outfp.close() nodeNames = [] nodeReplaces = [] demoDir = pychart_dir + "/demos/" def scan_nodes(fp): global nodeNames for line in fp.readlines(): mo_node = re.match("^@node ([^,]*)", line) if mo_node: nodeNames.append(re.compile("\\b(" + mo_node.group(1) + ")\\b")) def include_text_file(file): fp = open(file, "r") print "\\noindent\\bfcode{%s}\n\n" % file print "\\begin{verbatim}" line = fp.readline() if line.startswith('#'): # Skip the first comment block. It's usually a copyright statement. while True: line = fp.readline() assert line if not line.startswith('#'): break print line, for line in fp.readlines(): line = string.expandtabs(line) print line, fp.close() print "\\end{verbatim}" def format_doc(str): out = "" empty_line_found = False in_example = None for line in string.split(str, "\n"): if empty_line_found and len(line) > 0 and line[0] != ' ': if not in_example: out = out + "\\begin{verbatim}\n" in_example = True out = out + line + "\n" else: if line == "": empty_line_found = True if in_example: out = out + line + "\n\\end{verbatim}\n" else: # Do some formatting. line = format_doc_string(line) out = out + line + "\n" in_example = None if in_example: out = out + "\n\end{verbatim}\n" return out fp = open(argv[0], "r") scan_nodes(fp) fp.seek(0) while True: line = fp.readline() if line == "": break mo7 = re.match("@xximage\\{(.*),\\}", line) line = line.replace("@chart{}", "PyChart") line = line.replace("@shadow", "Parameter \\var{shadow} is either None or tuple (\\var{xdelta, ydelta, shadowstyle}). If non-None, a shadow of \\var{shadowstyle} (\\pxref{module-fill-style}) is drawn beneath the polygon at the offset (\\var{xdelta, ydelta}).") mo = re.match("^%%([^.]+)\\.(.*)", line) if mo: outputClassAttrs(mo.group(1), mo.group(2)) continue mo = re.match("^@samplechartandcode\{([^,]*),(.*)\}", line) if mo: basename = mo.group(1) description = mo.group(2) for ext in ["png", "eps", "pdf"]: copy_file("%s%s-c.%s" % (demoDir, basename, ext), "%s.%s" % (basename, ext)) print "\\includegraphics{%s}\n" % (basename) print description, "\n" print "Below is the source code that produces the above chart." include_text_file(demoDir + basename + ".py") continue mo = re.match("^@samplecode\{(.*)\}", line) if mo: basename = mo.group(1) include_text_file(demoDir + basename + ".py") continue mo = re.match("^@samplechart\{(.*)\}", line) if mo: basename = mo.group(1) for ext in ["png", "eps", "pdf"]: copy_file("%s%s-c.%s" % (demoDir, basename, ext), "%s.%s" % (basename, ext)) print "\\includegraphics{%s}\n" % (basename) continue mo = re.match("^@pydescribe\{(.*)\}", line) if mo: obj_name = mo.group(1) obj = eval(obj_name) print format_doc(str(obj.__doc__)), "\n" continue print line, PyChart-1.39/doc/template.tex0000644000175000017500000014355710354321416017574 0ustar santiagosantiago00000000000000\documentclass{howto} \usepackage{ltxmarkup} \usepackage{graphicx} \title{PyChart} \author{Yasushi Saito} \date{July 2, 2005} \authoraddress{ Email: \email{yasushi@cs.washington.edu} } \makeindex \newcommand{\pychart}{PyChart} \newcommand{\pyversion}{1.34} \newcommand{\secref}[1]{Section~\ref{#1}} \newcommand{\xref}[1]{See Section~\ref{#1}} \newcommand{\pxref}[1]{see Section~\ref{#1}} \begin{document} \maketitle \section{Introduction}\label{introduction} This document describes \pychart{} Version \pyversion{}, a Python library designed for drawing professional-quality charts. It produces line plots, bar plots, range-fill plots, pie charts, and wind-rose charts in PostScript, PDF, PNG, or SVG. \pychart{} is distributed under the General Public License (GPL). \begin{seealso*} \seeurl{http://www.gnu.org/copyleft/gpl.html}{Follow this link for more information about GPL.} \end{seealso*} The following examples illustrate uses of \pychart{}. \subsection{Line plot} \index{line plot} @samplechart{linetest} This example draws a simple line plot. Below is the source code needed to produce this chart. @samplecode{linetest} To produce a PostScript chart, just feed the file to Python. \begin{verbatim} % python linetest.py >linetest.eps \end{verbatim} \index{redirecting output} Or, to produce a PDF chart, run python like below \begin{verbatim} % python linetest.py --format=pdf >linetest.pdf \end{verbatim} \index{PDF} \index{\texttt{--format} option} To handle command-line options such as \code{--format=pdf}, you need to put \code{theme.get_options()} in the beginning of your file. \pychart{} also supports PNG, SVG, and interactive X11 display. \begin{seealso} \secref{options} for more information about output control. \end{seealso} Every \pychart{} program starts with line "\code{from pychart import *}" to import classes and objects provided by \pychart{}. Each chart is represented by an \code{area} object (\pxref{module-area}), which defines the size , the coordinate system (linear, log, etc; \pxref{module-coord}), and plots to be drawn. The final line of a program should end with \code{area.draw()}, which draws all the components of the chart to the standard output. \subsection{Bar plot} @samplechart{bartestv} The below program generates this chart. @samplecode{bartestv} \section{Anatomy of a chart}\label{anatomy} A chart comprises a set of \dfn{components}. Each component belongs to a certain class, from which an instance tailored for a particular chart is generated. The below picture shows example of a chart and its components. @samplechart{failureannot} The standard set of component classes follow: \begin{description} \item[\code{area.T}:] This class defines the size, the location, and the coordinate system (linear, logarithmic, etc) of a chart (\pxref{module-area}). It also contains axes, plots, and legends, as described below. At least one Area must be created in any chart. \item[\code{axis.X}:] \item[\code{axis.Y}:] The axis class defines the look of an axis. You can specify, for example, the interval and the style of tick marks and grid lines (\pxref{module-axis}). \pychart{} provides two types of axes, \code{axis.X} and \code{axis.Y}, corresponding to horizontal and vertical axes. \item[\code{bar_plot.T}:] \item[\code{line_plot.T}:] \item[\code{pie_plot.T}:] \item[\code{range_plot.T}:] \item[\code{interval_plot.T}:] \item[\code{rose_plot.T}:] These classes actually plot a chart. You can draw multiple plots in a single chart, and most of the times you can even mix different types of plots, e.g., line plots and bar plots. \item[\code{legend.T}:] The class draws an optional rectangular box that describes what each plot means (\pxref{module-legend}). \item[\code{text_box.T}:] This class draws an optional rectangular box that contains arbitrary text. It can also contain arrows (\pxref{module-text-box}). \item[\code{canvas.T}:] The \code{canvas} is a "virtual paper" that defines graph-drawing primitives, such as lines, rectangles, and texts. One canvas corresponds to one output file. Canvas is used by other components in the graph and is usually not manipulated by users directly. It's handy, however, if you want to draw a line/circle/text/etc, directly on the PostScript or PDF file. \xref{module-canvas}. \end{description} \section{Attributes}\label{attribute} \index{attribute} The look of a component of a chart (\pxref{anatomy}) is defined by a collection of \dfn{attributes}. For example, an X or Y axis includes an integer \code{tic_len} attribute that defines the length of "tick" lines drawn perpendicular to the axis (\pxref{module-axis}). It also has an integer \code{tic_interval} attribute that defines the separation between tick lines. \xref{module-axis} for the full list of Axis's attributes. Attributes are usually specified by named arguments during component creation: \begin{verbatim} ax = axis.X(tic_len = 3, tic_interval = 50) \end{verbatim} \noindent Attributes can also be changed after a component is created, but before \code{area.T.draw()}, the main drawing procedure (\pxref{module-area}), is called. The below example has the same effect as the above. \begin{verbatim} ax = axis.X() ax.tic_len = 3 ax.tic_interval = 50 \end{verbatim} \index{attribute!setting default values} Each attribute has a default value that supposedly gives you a standard look to the chart. You can change the default values through \code{chart_object} module. For example, the below example has the same effect as the above, except that all X axes created in the future will have the new default values. \declaremodule{extension}{chart-object} \index{set_defaults} \begin{verbatim} chart_object.set_defaults(axis.X, tic_len=3, tic_interval=50) ax = axis.X() \end{verbatim} \section{Unit of length and the coordinate System}\label{unit} \index{unit of length} \index{PostScript} \index{points} \index{coordinate system} In \pychart{}, the X axis grows to the right, and the Y axis grows up (the same as PostScript, but different from X and Windows). The length is measured in ``PostScript points'', which coincides with \TeX{} points. Usually, one point is equal to 1/72 inch. Several variables and functions are provided to manipulate lengths. Chart magnification can be changed by setting variable \code{theme.scale_factor}. One can convert a sample data value to a canval coordinate by calling two methods, \code{x_pos} and \code{y_pos} in \code{area.T} object. \index{scaling charts} \index{magnifying charts} \begin{seealso} \xref{module-theme} for the \module{theme} module. \xref{module-area} for the \module{area} mobule. \end{seealso} \section{Reading CSV files and transforming data} \declaremodule{extension}{chart-data} \index{data} \index{samples} The basic function of \pychart{} is to plot sample data in a variety of ways. Sample data are simply a \emph{sequence} of \emph{sequences}, where the term "sequence" is a Python jargon for either a tuple (comma-separated numbers or strings enclosed in parenthesis, e.g., \code{(5, 10, 15)}) or a list (comma-separated numbers or strings enclosed in square brackets, e.g., \code{[5, 10, 15]}). Data are given to plots through the "\code{data}" attribute of a plot object: \begin{verbatim} l = line_plot.T(data=[(10,20), (11,38), (12,29)], xcol=0, ycol=1) \end{verbatim} \noindent In the above example, three sample points will be drawn along with line segments that connect them: (10, 20) - (11, 38) - (12, 29). Attribute \code{xcol} tells the locations of X values within data (the first column of each sample in \code{data}), and \code{ycol} similarly tell the locations of Y values (the last column of each sample in \code{data}). A sample point can contain None, in which case it is ignored. \begin{verbatim} data = [(10, 20, 21), (11, 38, 22), (13, None, 15), (12, 29, 30)] l1 = line_plot.T(data=data, xcol=0, ycol=1) l2 = line_plot.T(data=data, xcol=0, ycol=2) \end{verbatim} \noindent The above example is equivalent to: \begin{verbatim} l1 = line_plot.T(data=[(10, 20), (11, 38), (12, 29)], xcol=0, ycol=1) l2 = line_plot.T(data=[(10, 21), (11, 22), (13, 15), (12, 30)], xcol=0, ycol=1) \end{verbatim} Module \code{chart_data} provides several functions for generating, reading, or transforming samples. \index{conversion!CSV} \index{CSV} \index{comma-separated values (see CSV)} \begin{funcdesc}{read_csv}{path, delim = ','} \index{scanf} \index{format!read_csv} \index{comments!- in CSV files} @pydescribe{chart_data.read_csv} \indexii{file}{read} \end{funcdesc} \begin{funcdesc}{read_str}{delim, lines} @pydescribe{chart_data.read_str} \index{format!read_str} \indexii{string}{read} \end{funcdesc} \begin{funcdesc}{write_csv}{path, data} @pydescribe{chart_data.write_csv} \indexii{file}{write} \end{funcdesc} \begin{funcdesc}{func}{f, from, to, step} @pydescribe{chart_data.func} \end{funcdesc} \begin{funcdesc}{filter}{f, data} @pydescribe{chart_data.filter} \end{funcdesc} \begin{funcdesc}{extract_rows}{data, rows...} @pydescribe{chart_data.extract_rows} \end{funcdesc} \begin{funcdesc}{extract_columns}{data, cols...} @pydescribe{chart_data.extract_columns} \end{funcdesc} \begin{funcdesc}{moving_average}{data, xcol, ycol, width} \index{average (computing -)} \index{mean (computing -)} @pydescribe{chart_data.moving_average} \end{funcdesc} \begin{funcdesc}{median}{data, freq_col=1} @pydescribe{chart_data.median} \end{funcdesc} \begin{funcdesc}{mean_samples}{data, xcol, ycollist} @pydescribe{chart_data.mean_samples} \end{funcdesc} \begin{funcdesc}{stddev_samples}{data, xcol, ycollist, delta} \index{standard deviation (computing -)} \index{variance (computing -)} @pydescribe{chart_data.stddev_samples} \end{funcdesc} \begin{funcdesc}{transform}{func, data} @pydescribe{chart_data.transform} \end{funcdesc} One of the frequent uses of \code{transform} is to convert a date string to number and back to some other string for display. The next example does this: it takes the input for date in the format of "10/5/1983", and displays the graph in the format of "Oct 5, 1983". \indexii{conversion}{date} \index{time (see date)} @samplecode{date} @samplechart{date} \section{Area} \declaremodule{extension}{area} \begin{classdesc*}{area.T} Class \code{area.T} defines the location and size of a chart. It also defines the coordinate system (linear, log, or enumeration) of the X and Y axes. \indexii{scale}{logarithmic} \indexii{scale}{linear} \index{category axis} The X (or Y) coordinate system is defined by attribute \code{x_coord} (or \code{y_coord}), which takes an object of type \code{coord.T}. Class \code{coord.T} defines how an X (or a Y) value is mapped to a display (canvas) location. \pychart{} provides three standard coordinate systems: \code{linear_coord.T} (for linear mapping; this is the default), \code{log_coord.T} (for logarithmic mapping), and \code{category_coord.T} (enumeration of values). Most charts will do ok by instantiating one of these pre-defined coordinate classes, but you can also define your own wacky coordinate system. \begin{seealso} \xref{module-coord} for more about the coordinate system. \end{seealso} For log and linear coordinate systems, the minimum and maximum displayable values in the area are computed automatically from the plots unless they are defined explicitly via attribute \code{x_range}. In the next example, the X axis is drawn with a logarithmic scale. The minimum value will be 10, and the maximum value will be computed from the values given to plots. \begin{verbatim} ar = area.T(x_coord = log_coord.T(), x_range = (10, None), ...) \end{verbatim} In the below example of a category coordinate system, the X axis will list three strings, ``apple'', ``orange'', and ``blueberry''. \begin{verbatim} samples = [("apple", 10), ("orange", 30), ("blueberry", 20)], ar = area.T(x_coord = category_coord(samples, 0)) ar.add_plot(bar_plot.T(data = samples)) \end{verbatim} \end{classdesc*} We now list the attributes understood by an \code{area.T} object. %%area.T An object of \code{area.T} also provides several methods: \begin{methoddesc}{add_plot}{plot, ...} Add plots to the area. Each \var{plot} must be a plot object. \xref{module-line-plot}, \secref{module-bar-plot}, \secref{module-pie-plot}, \secref{module-range-plot}. \end{methoddesc} \begin{methoddesc}{draw}{canvas = None} Draw plots, axes, and the legend. This procedure must be called at the end of every \pychart{} application. Parameter \var{canvas} is an optional parameter that specifies the output. If omitted, the default canvas is used. \begin{seealso} Section~\ref{module-canvas} for more about canvas. \end{seealso} \end{methoddesc} \begin{methoddesc}{x_pos}{xval} Converts \var{xval} to a coordinate on the canvas (\pxref{module-canvas}). \xref{unit}. \end{methoddesc} \index{PostScript} \begin{methoddesc}{y_pos}{yval} Converts \var{yval} to a coordinate on the canvas (\pxref{module-canvas}). \xref{unit}. \end{methoddesc} \begin{verbatim} ar = area.T(loc=(50, 50), size=(100, 100), xrange=(0,200), yrange=(0, 1000)) px = ar.x_pos(50) py = ar.y_pos(100) \end{verbatim} \noindent In the above example, the chart is drawn in the area defined by rectangle (50, 50) - (150, 150). The point (\code{px, py}) will be at (75, 60), which is the screen location at which the point (50, 100) would be drawn (i.e., 50 + 100 * 50/200 = 75, 50 + 100 * 100 / 1000 = 60). \index{coordinate system} \index{X axis} \index{Y axis} \index{axis (extension module)} \subsection{Specifying the coordinate system} \declaremodule{extension}{coord} \index{coordinate system} \indexii{scale}{linear} \indexii{scale}{logarithmic} \index{coordinate system!linear} \index{coordinate system!logarithmic} Attributes \code{x_coord} and \code{y_coord} specify the coordinate systems for the area's X and Y axes. The values of these attributes must of type \code{coord.T}. \pychart{} provides three popular subclasses of \code{coord}. Both \code{x_coord} and \code{y_coord} defaults to \code{linear_coord.T()}. \begin{classdesc*}{linear_coord.T} This class creates a linear coordinate system. \begin{verbatim} ar = area.T(x_coord = linear_coord.T(), y_coord = linear_coord.T(), ...) \end{verbatim} \end{classdesc*} \begin{classdesc*}{log_coord.T} This class displays a logarithmic coordinate system. \end{classdesc*} \begin{classdesc}{category_coord.T}{data, col} This class defines a ``categorical'' coordinate system, in which the axis only takes discrete values. This class takes two constructors: \var{data} (\pxref{module-chart-data}) and column \var{col} from which the axis values are extracted from the data. See the following example: @samplecode{categbar} The output will look like the below: @samplechart{categbar} \end{classdesc} \index{zap marks} All the classes described so far are derived from the \code{coord.T} class: \begin{classdesc}{coord.T}{} This is an abstract base class that defines methods for calculating the mapping between sample values and coordinates. Every \code{coord.T} object must implement the following three methods: \end{classdesc} \begin{methoddesc}{get_data_range}{dmin, dmax, interval} This method should compute the minimum and maximum values that are to be displayed on the canvas. \var{dmin}, \var{dmax} are the minimum and maximum values found in the sample data given to the plots. \var{interval} is the value of the area's \code{x_grid_interval} (or \code{y_grid_interval}) attribute (\pxref{module-area}), or \code{None} if the attribute is omitted by the user. This method should return tuple (MIN, MAX, INTERVAL), where MIN, MAX are the minimum and maximum values to be displayed, and INTERVAL is the interval with which label and tick lines are drawn. \end{methoddesc} \begin{methoddesc}{get_canvas_pos}{size, val, range} This method converts a data value (\var{val}) to canvas location. Parameter \var{size} is the size of the axis, either X or Y, and \var{range} is the minimum and maximum sample values obtained by calling \code{self.get_data_range}. \end{methoddesc} \begin{methoddesc}{get_tics}{range, interval} This method should return the list of values (not canvas locations) at which labels and ``tick'' lines are drawn. Parameters \var{range} and \var{interval} are the values returned by get_data_range. \end{methoddesc} \index{coordinate system!- with a gap} You can create fancier coordinate systems by subtyping \code{coord.T}. The below example shows how you can create a chart with ``zap'' marks. @samplechart{zaptest} @samplecode{zaptest} \subsection{Axes} \declaremodule{extension}{axis} \index{X axis} \index{Y axis} Module \code{axis} defines the look of an axis as well as grid lines. Two classes, \code{axis.X} and \code{axis.Y}, are provided by this module. \begin{classdesc*}{axis.X} This class is draws an X (horizontal) axis. %%axis.X \end{classdesc*} \begin{classdesc*}{axis.Y} This class is draws a Y (vertical) axis. %%axis.Y \end{classdesc*} \subsection{Legends} \declaremodule{extension}{legend} \begin{classdesc*}{legend.T} A legend is a subcomponent of area that draws a rectangular box with the description of each plots. \end{classdesc*} This class supports the following attributes: %%legend.T \section{Bar plots} \declaremodule{extension}{bar-plot} \begin{classdesc*}{bar_plot.T} This class draws a bar plot. @samplechartandcode{bartest,Sample bar plot} @samplechartandcode{bartest2, Bar plot with error bars} \end{classdesc*} The list the attributes understood by an \code{bar_plot.T} object follow: %%bar_plot.T \section{Interval bar plots} \declaremodule{extension}{interval-bar-plot} \begin{classdesc*}{interval_bar_plot.T} An interval bar plot is a special kind of bar plot that draws an alternating sequence of bars. @samplechartandcode{intvlbartestv, Sample interval bar chart} \end{classdesc*} The list the attributes understood by an \code{interval_bar_plot.T} object: %%interval_bar_plot.T \section{Line and scatter plots} \declaremodule{extension}{line-plot} \index{scatter plot} \begin{classdesc*}{line_plot.T} This class raws a line plot. By specifying None to its line style, you can also draw a scatter plot. @samplechartandcode{linetest3, Sample line plot} @samplechartandcode{scattertest, Sample scatter plot} \index{scale!logarithmic (example)} \index{coordinate system!logarithmic (example)} \end{classdesc*} %%line_plot.T \subsection{Tick marks} \declaremodule{extension}{tick-mark} \begin{classdesc*}{tick_mark.T} Tick marks are used in conjunction with line plots (\pxref{module-line-plot}) to show where sample points are. Class \code{tick_mark.T} is an abstract base class, from which several built-in tick mark classes are derived. They are described later. \end{classdesc*} Class \code{tick_mark.T} supports the following set of attributes. %%tick_mark.T Several types of tick marks are offered by \pychart{} as subclasses of \code{tick_mark.T}. They include: tick_mark.Circle, tick_mark.Square, tick_mark.Triangle, tick_mark.DownTriangle, tick_mark.X, tick_mark.Plus, tick_mark.Diamond, tick_mark.Star, tick_mark.Null. Specific instance of these classes are also defined for your convenience. Below is the list of such standard tick marks. They are referred to by as "\code{tick_mark.}\var{name}", where \var{name} is the labels below them. @samplechart{tickmarks} \subsection{Error bars} \declaremodule{extension}{error-bar} \begin{classdesc*}{error_bar.T} Error bars are used in conjunction with line, scatter, or bar plots to show the confidence interval of each sample value. \xref{module-bar-plot}. Class \code{error_bar.T} is an abstract base class. Actual drawing is done by its subclasses, described next. \end{classdesc*} @samplechart{errorbars} \begin{classdesc*}{error_bar.error_bar1} This class supports the following attributes: %%error_bar.error_bar1 \end{classdesc*} \begin{classdesc*}{error_bar.error_bar2} This class supports the following attributes: %%error_bar.error_bar2 \end{classdesc*} \begin{classdesc*}{error_bar.error_bar3} This class supports the following attributes: %%error_bar.error_bar3 \end{classdesc*} \begin{classdesc*}{error_bar.error_bar4} This class supports the following attributes: %%error_bar.error_bar4 \end{classdesc*} \begin{classdesc*}{error_bar.error_bar5} This class supports the following attributes: %%error_bar.error_bar5 \end{classdesc*} \begin{classdesc*}{error_bar.error_bar6} This class supports the following attributes: %%error_bar.error_bar6 \end{classdesc*} \section{Range plots} \declaremodule{extension}{range-plot} \begin{classdesc*}{range_plot.T} A range plot is similar to line plots (\pxref{module-line-plot}), but it fills regions, instead of drawing line. @samplechartandcode{rangetest,Sample range plot} \end{classdesc*} This class supports the following attributes: %%range_plot.T \section{Pie plots} \declaremodule{extension}{pie-plot} \begin{classdesc*}{pie_plot.T} Pie plots. @samplechartandcode{pietest, Sample pie chart} \end{classdesc*} This class supports the following attributes: %%pie_plot.T \section{Rose plots} \declaremodule{extension}{rose-plot} \index{wind rose plot} \begin{classdesc*}{rose_plot.T} Rose plot class is contributed by Kilian Hagemann. It's still experimental. @samplechartandcode{roseplottest, Sample rose plot} \end{classdesc*} This class supports the following attributes: %%rose_plot.T \section{PyChart options}\label{options} \index{command-line options} \index{redirecting output} The behavior of \pychart{} can be changed in three ways, by setting variables in module \code{theme}, via command-line options, and via environment variable \code{PYCHART_OPTIONS}. \subsection{\module{theme} -- Defining the default behaviour of PyChart} \declaremodule{extension}{theme} You can change \pychart{}'s behavior by setting variables in the module \code{theme}. After setting values, you \emph{must} call \code{theme.reinitialize()} to reflect the changes to other parts of \pychart{}. Notice that these variables are meaningful only before the first call to area.T.draw() (\pxref{module-area}). \begin{verbatim} theme.scale_factor = 3 theme.reinitialize() \end{verbatim} The below are the list of variables in the \module{theme} module that you can modify. \index{magnifying charts} \begin{datadesc}{scale_factor} This variable defines the scaling factor. The default value is 1.0, meaning that one point in \pychart{} actually means one PostScript point. Setting this value to 3.0, for example, makes \pychart{} draw everything three times larger. \begin{seealso} \xref{unit} for how the length and the coordinate system are defined in \pychart{}. \end{seealso} \end{datadesc} \begin{datadesc}{output_format} \indexii{write}{format} This variable sets the encoding of the data produced by \pychart{}. The value of this variable must be one of the following strings. \begin{description} \item[\code{ps}:] \item[\code{eps}:] \index{PostScript} \index{Encapsulated PostScript!see \textit{PostScript}} Encapsulated PostScript. This is the default. \item[\code{pdf}:] \index{PDF} Adobe Page Description Format, or PDF. \item[\code{pdf-uncompressed}:] PDF without compression. This option should be used for a debugging purpose only. \item[\code{png}:] \index{PNG} PNG graphics. You need to have ghostscript (\code{gs}) installed to use this option, because \pychart{} internally calls ghostscript to convert PostScript to PNG. \begin{seealso} \seeurl{http://www.ghostscript.com/}{See this web page for more information about Ghostscript.} \end{seealso} \item[\code{svg}:] \index{SVG} Scalable vector graphics. \begin{seealso} \seeurl{http://www.w3.org/Graphics/SVG/}{See this web page for more information about SVG.} \end{seealso} \item[\code{x11}:] \index{X11} \index{ghostscript} Interactive display on in X window. This format works on UNIX-based systems, but not on Windows. You need to have ghostscript installed to use this option. \end{description} When this variable is not set (or is set to \code{None}), \pychart{} guesses the format from the file name (\code{theme.output_file}; see below). Failing that, \pychart{} will generate an encapsulated PostScript file. \end{datadesc} \begin{datadesc}{output_file} \indexii{write}{file} \index{file name} Sets the output file name. Without this option, \pychart{} sends code to the standard output. If you want to produce multiple charts from a single Python source file, use \code{canvas.init(\var{file})} (\pxref{module-canvas}). \end{datadesc} \begin{datadesc}{use_color} \index{gray scale} \index{color!-ing charts} The default value of this variable is \code{False}. If the value is \code{True}, \pychart{} colorizes some of the default objects. If the value is \code{False}, \pychart{} uses gray scale for the color of these objects. In particular: \begin{itemize} \item The standard color list (\code{colors.standards}) will include all the colors listed in X's RGB file. So you can use something like "\code{color.slate_blue}"\footnote{In fact, you can use these color names in gray-scale mode as well. They will appear in some gray color though.}. \xref{module-color} for more about colors. \index{color!names} \item The standard fill style list (\code{fill_style.standards}) will be colorized. Thus, if you create a bar plot without explicitly specifying its fill style, you will see colored bars on the canvas. \xref{module-fill-style} for more about fill styles. \index{fill_style} \item The standard line style list (\code{line_style.standards}) will be colorized. \xref{module-line-style} for more about line styles. \index{line_style} \end{itemize} \end{datadesc} \begin{datadesc}{default_font_family} This variable sets the default font family used when drawing texts. The default is Helvetica. \xref{escape-sequence}. \index{font!family} \index{Helvetica (font)} \end{datadesc} \begin{datadesc}{default_font_size} This variable sets the font size used when drawing texts. The default is 9 points. \xref{escape-sequence}. \indexii{font}{size} \end{datadesc} \begin{datadesc}{default_halign} Sets the default horizontal alignment of texts (Default value: \code{/h}). \xref{escape-sequence}. \end{datadesc} \begin{datadesc}{default_valign} Sets the default vertical alignment of texts (Default value: \code{/v}). \xref{escape-sequence}. \end{datadesc} \begin{datadesc}{default_angle} Default text-drawing angle (Default value: 0). \xref{escape-sequence}. \end{datadesc} \begin{datadesc}{default_line_height} Defines the separation between two text lines. \xref{escape-sequence}. \index{font!height} \end{datadesc} \begin{datadesc}{default_line_width} \indexii{line}{width} Set the default line width, in points (\pxref{unit}). (Default value: 0.4) \xref{module-line-style}. \end{datadesc} \begin{datadesc}{debug_level} This variable controls the verbosity of messages from \pychart{}. The default value is 1, meaning that \pychart{} only displays error messages. The larger the value, the more verbose \pychart{} becomes. \end{datadesc} \begin{datadesc}{bounding_box} This variable, if set, manually sets the bounding box of the chart(s) produced by \pychart{}. It is a four-tuple of numbers, i.e., (\var{xmin, ymin, xmax, ymax}). \pychart{} usually calculates the bounding box of a chart automatically. Thus, you set this variable only when you want to override the calculation by \pychart{}, or \pychart{} screws the calculation. The latter situation happens especially when you use really thick lines for drawing. See also \code{delta_bounding_box}, described next. \end{datadesc} \begin{datadesc}{delta_bounding_box} This variable, if set, adjusts the size of the bounding box of the chart(s). It is a four-tuple of numbers (\var{xmin}, \var{ymin}, \var{xmax}, \var{ymax}). Each of the number is added to the bounding box computed by \pychart{}. If both \code{bounding_box} and \code{delta_bounding_box} are set, then \code{delta_bounding_box} is ignored. \end{datadesc} After changing any of the variables described so far, you \emph{must} call the \code{reinitialize} function to reflect the change to the rest of \pychart{}: \begin{funcdesc}{reinitialize}{} @pydescribe{theme.reinitialize} \end{funcdesc} \subsection{Changing the default behavior via command-line options}\label{command-line-options} \index{command-line options} The variables in the \module{theme} module can also be set from the command line. To do this, the program that imports \pychart{} must call \code{theme.get_options} in the beginning, because \pychart{} itself is just a library. Below is an example. \begin{funcdesc}{get_options}{ARGV = sys.argv[1:]} @pydescribe{theme.get_options} \end{funcdesc} \subsection{Changing the default behavior via environment variable PYCHART_OPTIONS}\label{PYCHART-OPTIONS} \index{environment variable} \index{PYCHART_OPTIONS} The variables in the \module{theme} module can also be set via environment variable \code{PYCHART_OPTIONS}. The value of this variable, if set, should be a sequence of \code{var=val}, separated by space. For instance, the below example tells \pychart{} to write to file \file{foo.pdf} and use Times-Roman as the default font. \begin{verbatim} % PYCHART_OPTIONS="output=foo.pdf font-family=Times" % export PYCHART_OPTIONS \end{verbatim} The summary of attributes that can be set via \code{PYCHART_OPTIONS} follows. \begin{description} \item[font-family=\var{name}:] \index{font}{family} Same as setting \code{theme.default_font_family} variable. \item[font-size=\var{size}:] \index{font}{size} Same as setting \code{theme.default_font_size} variable. \item[line-width=\var{points}:] Same as setting \code{theme.default_line_width} variable. \item[scale=\var{n}:] \index{scale!scaling charts} \index{size!scaling charts (see \textit{scale})} \index{magnifying charts!see \textit{scale}} Same as setting \code{theme.scale_factor} variable. \item[color=[yes|no]:] \index{color!-izing charts} Same as setting \code{theme.use_color} variable. \item[debug-level=\var{N}:] Same as setting \code{theme.debug_level} variable. \item[bbox=\var{LEFT},\var{BOTTOM},\var{RIGHT},\var{TOP}:] \index{bounding box} This option sets \code{theme.bounding_box} and/or \code{theme.delta_bounding_box}. The value of this option is a sequence of four values, separated by commas. Each value is of the form, \code{+}\var{num}, \code{-}\var{num}, or \var{num}. \code{+}\var{num} and \code{-}\var{num} adds to or subtracts from the bounding-box value computed by \pychart{} (the unit is PostScript points; \xref{unit}.) \var{num} sets the bounding box at that value. For example, \begin{verbatim} bbox=-10,0,+10,100 \end{verbatim} Extends the bounding box 10 points to both left and right, and sets the vertical stretch from 0 to 100. \end{description} \section{Line styles} \declaremodule{extension}{line-style} \begin{classdesc*}{line_style.T} This class defines the looks of line segments. This class supports the following attributes: \end{classdesc*} %%line_style.T The below picture show standard line styles. These styles are referred to by names \code{line_style.}\var{name}, where \var{name} is the label below each item. @samplechart{linestyles} \section{Colors} \declaremodule{extension}{color} \begin{classdesc*}{color.T} This class determines the color. \end{classdesc*} This class supports the following attributes: %%color.T \index{rgb.txt} \index{color!names} For example, \code{color.T(r=1, g=1, b=1)} will produce white. The color of \code{color.T(r=1, g=0, b=1)} will produce purple. You can use all the colors defined in X rgb.txt (usually at \file{/usr/X11R6/lib/X11/rgb.txt}). The below shows some of the standard colors defined in the module. They are refereed to by the names \code{color.}\var{name} (e.g., \code{color.gray1}). @samplechart{colors} \section{Fill styles} \declaremodule{extension}{fill-style} \begin{classdesc*}{fill_style.T} This class determines the color and the pattern of the background of a region. Class \code{fill_style.T} itself is an abstract base class; actual drawing functions are provided by its subclassess, which are described later. \end{classdesc*} This class supports the following attributes: %%fill_style.T \begin{classdesc*}{fill_style.Plain} @pydescribe{fill_style.Plain} \end{classdesc*} \begin{classdesc*}{fill_style.Diag} @pydescribe{fill_style.Diag} \end{classdesc*} \begin{classdesc*}{fill_style.Rdiag} Fills the region with diagonal lines, but tilted in the opposite direction from \code{fill_style.Diag}. \end{classdesc*} \begin{classdesc*}{fill_style.Vert} Fills the region with vertical lines. \end{classdesc*} \begin{classdesc*}{fill_style.Horiz} Fills the region with horizontal lines. \end{classdesc*} \begin{classdesc*}{fill_style.Stitch} Fills the region with horizontal and vertical lines. \end{classdesc*} \begin{classdesc*}{fill_style.Wave} Fills the region with horizontal wavy lines. \end{classdesc*} \begin{classdesc*}{fill_style.Vwave} Fills the region with vertical wavy lines. \end{classdesc*} \begin{classdesc*}{fill_style.Lines} Fills the region with a series of short line segments. \end{classdesc*} The below picture shows the standard set of fill styles. They are named like \code{fill_style.}\var{name}, where \var{name} are the labels shown in the picture. @samplechart{fillstyles} Just for your information, the "rdiag3" style shown in the picture can be created manually by the following code: \begin{verbatim} rdiag3 = fill_style.Rdiag(line_style=line_style.T(width=3, color=color.gray5), line_interval=6) \end{verbatim} You can create your own fill style by subtyping \code{fill_style.T}. It should provide the following public method: \begin{methoddesc}{draw}{self, can, x1, y1, x2, y2} This method is called to fill a rectangular region in a canvas. Parameter \var{can} is a canvas (\pxref{module-canvas}), and region (\var{x1,y1})-(\var{x2,y2}) specifies the region to be filled. \end{methoddesc} Just for your information, below is how the Rdiag class is implemented. \begin{verbatim} class Rdiag(fill_style.T): """Fills the region with diagonal lines, but tilted in the opposite direction from fill_style.Diag.""" def draw(self, can, x1, y1, x2, y2): line_width = self.line_style.width interval = self.line_interval * 1.414 x1 -= line_width y1 -= line_width x2 += line_width y2 += line_width len = max(y2 - y1, x2 - x1) while curx in range(x1, x2 + len, interval): can.line(self.line_style, curx, y1, curx-len, y1+len) \end{verbatim} \section{Drawing texts} \index{drawing!texts} \index{text!see \textit{font}} \index{font} \index{show} \declaremodule{extension}{font} You can display text strings in chart as a part of axis labels, plot labels, legends, etc. You can also display an arbitrary text in an arbitrary location using annotations (\pxref{module-text-box}) or \code{canvas.show} function (\pxref{module-canvas}). \begin{seealso} \secref{options} for a variety of ways to set default text attributes. \end{seealso} \subsection{Escape sequences}\label{escape-sequence} \index{escape character} A text string may contain escape characters that control its appearance. The escape sequences all start with the letter ``\code{/}''. Thus, to display ``\code{/}'' itself, you must write ``\code{//}''. \begin{quote} \textbf{Restrictions}: \code{/h}, \code{/v}, and \code{/a} \emph{must} appear in the beginning of a string. \end{quote} \index{/} \index{alignment (font)} \index{justification (font)} \begin{description} \item[\code{/a\var{dd}}] Specifies the angle of the text. Parameter \var{dd} is a number between -360 to 360. Value 0 means left-to-right text, 90 means bottom-to-up, etc. If you want to print numbers right after an angle specification, put \code{\{} between the angle and the number. For example, the below code shows string "\code{"100"}" at a 60-degree angle. \begin{verbatim} "/a60{}100" \end{verbatim} \index{rotation (text)} \item[\code{/h}\var{A}:] Specifies horizontal alignment of the text. \var{A} is one of "\code{L}" (left alignment), "\code{R}" (right alignment), or "\code{C}" (center alignment). \item[\code{/v}\var{A}:] Specifies vertical alignment of the text. \var{A} is one of "\code{B}" (bottom), "\code{T}" (top), or "\code{M}" (middle). \item[\code{/T}]: Switch to Times font family. \index{Times-Roman (font)} \item[\code{/H}:] Switch to Helvetica font family. \index{Helvetica (font)} \item[\code{/C}:] Switch to Courier font family. \index{Courier (font)} \item[\code{/B}:] Switch to Bookman-Demi font family. \index{Bookman-Demi (font)} \item[\code{/A}:] Switch to AvantGarde-Book font family. \index{AvantGarde-Book (font)} \item[\code{/P}:] Switch to Palatino font family. \index{Palatino (font)} \item[\code{/S}:] Switch to Symbol font family. \index{Symbol (font)} \item[\code{/F\{\var{family}\}}:] Switch to \var{family} font family. The below example draws string "Funny" using ZapfDingbat font (which produces some meaningless output). \index{font!family} \begin{verbatim} canvas.show(100, 200, "/F{ZapfDingbat}Funny") \end{verbatim} The list of available fonts are the following: \begin{quote} Bookman-Demi Bookman-Light Courier AvantGarde-Book AvantGarde-Demi Helvetica Helvetica-Narrow Palatino NewCenturySchlbk Times Symbol ZapfChancery-MediumItalic ZapfChancery-Medium-Italic ZapfDingbats \end{quote} \item[\code{/b}:] Switch to bold typeface. \index{bold (typeface)} \item[\code{/i}:] Switch to italic typeface. \index{italic (typeface)} \item[\code{/o}:] Switch to oblique typeface. \index{oblique (typeface)} \item[\code{/}\var{dd}:] Set font size to \var{dd} points. \indexii{size}{font} \index{font!size} \begin{verbatim} "/20{}2001 space odyssey!" \end{verbatim} \item[\code{/c}\var{dd}:] Set gray-scale to 0.\var{dd}. Gray-scale of 0 means black, 1 means white. \indexii{gray scale}{font} \item[\code{//}, \code{/\{}, \code{/\}}:] Display `/', `\}', or `\{'. \item[\code{\{ ... \}}:] Limit the scope of escape sequences. For example, \code{"\{/10\{/20Big text\} and small text\}"} will display \code{"Big Text"} using a 20-point font, and \code{"and small text"} using a 10-point font. \index{\{} \index{\}} \index{/} \item[\code{$\backslash$n}:] Break the line. \index{line break} \end{description} @samplechartandcode{fonttest, Font usage example} \subsection{Procedures provided in the \module{font} module} \index{escape character} \index{font} The \module{font} module defines several procedures and variables for manipulating texts and fonts: \begin{funcdesc}{quotemeta}{text} \index{escape character}{quoting -} @pydescribe{font.quotemeta} \end{funcdesc} \begin{funcdesc}{text_height}{text} @pydescribe{font.text_height} \end{funcdesc} \begin{funcdesc}{text_width}{text} @pydescribe{font.text_width} \end{funcdesc} \begin{funcdesc}{get_dimension}{text} @pydescribe{font.get_dimension} \end{funcdesc} \section{Annotation} \index{arrow (extension module)} \index{annotation} \declaremodule{extension}{text-box} \begin{classdesc*}{text_box.T} A text box is an optional element that adds a text box and arrows to a chart. This class supports the following attributes: \end{classdesc*} %%text_box.T In addition to the above attributes, this class provides the following methods. \begin{methoddesc}{add_arrow}{tip, tail=None, arrow=arrow.default} This method adds a straight arrow that points to \var{tip}, which is a tuple of integers. Parameter \var{tail} specifies the starting point of the arrow. It is either None or a string consisting of the following letters: \begin{quote} 'l', 'c', 'r', 't', 'm,', 'b' \end{quote} Letters 'l', 'c', or 'r' means to start the arrow from the left, center, or right of the text box, respectively. Letters 't', 'm', or 'b' means to start the arrow from the top, middle or bottom of the text box. For example, when \code{tail = 'tc'} then arrow is drawn from top-center point of the text box. Parameter \var{arrow} specifies the style of the arrow. \begin{seealso} Section~\ref{module-arrow} for arrows. \end{seealso} \end{methoddesc} @samplechartandcode{annotations, Annotations example} \section{Arrows} \declaremodule{extension}{arrow} \begin{classdesc*}{arrow.T} Arrow is an optional component of a chart that draws line segments with an arrowhead. To draw an arrow, one creates an arrow.T object, and calls its "draw" method usually after area.draw() is called (otherwise, area.draw() may overwrite the arrow). For example, the below code draws an arrow from (10,10) to (20,30). \begin{verbatim} ar = area.T(...) a = arrow.T(head_style = 1) ar.draw() a.draw([(10,10), (20,30)]) \end{verbatim} \end{classdesc*} This class supports the following attributes: %%arrow.T An arrow object exports a single public method, \code{draw}. \begin{methoddesc}{draw}{points} @pydescribe{arrow.T.draw} \end{methoddesc} @samplechart{arrows} \section{Zap marks} \declaremodule{extension}{zap} A zapping symbol is a zig-zag symbol that indicates that a certain region of a plot is cut out due to space constraints. It's usually used in conjunction with non-linear/non-logarithmic coordinate system. \xref{module-coord}, for an sample of zap symbols. \begin{funcdesc}{zap.zap_horizontally}{canvas, style, fill_style, x1, y1, x2, y2, xsize, ysize} @pydescribe{zap.zap_horizontally} \end{funcdesc} \begin{funcdesc}{zap.zap_vertically}{canvas, style, fill_style, x1, y1, x2, y2, xsize, ysize} @pydescribe{zap.zap_vertically} \end{funcdesc} \section{\module{canvas} -- Controlling output and format} \declaremodule{extension}{canvas} \index{canvas (default -)} \begin{classdesc*}{canvas.T} Canvas is an object that corresponds to a single output file. It provides a set of methods for drawing lines, polygons, texts, and other things in a manner independent of the file's format. Canvas is usually hidden from the user, as \pychart{} creates a \emph{default canvas} when it starts up and implicitly writes all charts on the default canvas (unless the user specifies otherwise; more on that later). There are some occasions, however, in which you might want to manipulate a canvas explicitly, e.g., when you want to create multiple plots from a single file, or you just want to add lines and texts directly. Class \code{canvas.T} is an abstract base class. \pychart{} provides several subclasses that correspond to specific file formats. For example, \code{pscanvas.T} implements methods for PostScript output. Class \code{pdfcanvas.T} implements methods for PDF output. \index{PostScript} \index{PDF} \index{file}{format} \end{classdesc*} \subsection{Creating a canvas}\label{creating-canvas} \index{canvas.T (class in canvas)} \index{redirecting output} \indexii{write}{file} \index{file name} A new canvas is created by calling the class static method \code{canvas.init}. It is closed by calling the \code{close()} method of the canvas object. \begin{funcdesc}{init}{fname=None format=None} @pydescribe{canvas.init} \end{funcdesc} \begin{methoddesc}{close}{} @pydescribe{basecanvas.T.close} \end{methoddesc} \subsection{Drawing plots on canvas}\label{drawing-graph-canvas} \index{drawing!plots on canvas} \pychart{} creates a new canvas object when "\code{area.T.draw()}" (\pxref{module-area}) is called for the first time, and no canvas is yet created at that moment. You can thus use you own canvas by creating a canvas \emph{before} calling the first \code{area.T.draw()}, like below: \begin{verbatim} can = canvas.init("foo.pdf") ... ar = area.T(...) ar.draw() \end{verbatim} You can also achieve the same effect by passing the canvas object to the \code{area.T.draw()} method explicitly: \begin{verbatim} can = canvas.init("foo.pdf") ... ar = area.T(...) ar.draw(can) \end{verbatim} You can also pass a file object (or file-like object, such as \code{StringIO}) to canvas.init. In this case, you need to define the output format via the second argument. \index{file object} \index{StringIO} \indexii{string}{write} \begin{verbatim} fd = file("foo.pdf", "w") can = canvas.init(fd, "pdf") ... ar.draw(can) \end{verbatim} \index{drawing!multiple graphs} \index{file!generating multiple files} Naturally, you can write to multiple files by passing multiple \code{canvas} objects to different \code{area.T.draw()}. For example, the below example draws the first chart to \file{graph1.pdf} and the next chart to \file{graph2.pdf}. @samplecode{twographs} \subsection{Drawing other objects on canvas}\label{drawing-canvas} \index{drawing!arbitrary objects on canvas} The objects of \code{canvas.T} class and its subclasses provides several methods that can be invoked manually to draw variety of things if you desire so. These methods take Postscript points as the unit of X and Y coordinates, as described in \secref{unit}. (These methods obey the scaling-factor specifications). \begin{methoddesc}{line}{linestyle, x1, y1, x2, y2} \begin{verbatim} # draw a line segment from (10,20) to (100, 200) can.line(line_style.blackdash1, 10, 20, 100, 200) \end{verbatim} \index{line} \end{methoddesc} \begin{methoddesc}{polygon}{linestyle, fillstyle, [(x1,y1), ..., (xn, yn)], shadow = None} Draw a polygon \var{points}, with \var{linestyle} (\pxref{module-line-style}), and fill with \var{fillstyle} (\pxref{module-fill-style}). Parameter \var{points} is a list of coordinates, e.g., ((10,10), (15,5), (20,8)). Value of \var{linestyle} can be None, in which case no line is drawn on the perimeter. Value of \var{fillstyle} can also be None, in which the internal of the polygon are left undrawn. @shadow \begin{verbatim} can.polygon(line_style.default, fill_style.default, [(10, 20), (100, 200), (300,300)]) \end{verbatim} \end{methoddesc} \begin{methoddesc}{rectangle}{linestyle, fillstyle, x1, y1, x2, y2, shadow=None} @shadow \begin{verbatim} can.rectangle(line_style.default, fill_style.default, 10, 20, 300, 300) \end{verbatim} \end{methoddesc} \begin{methoddesc}{ellipsis}{linestyle, fillstyle, x, y, radius, y_elongation=1, start=0, end=360, shadow=None} The start and end angles are specified in degrees; i.e., between 0 and 360. @shadow \end{methoddesc} \begin{methoddesc}{round_rectangle}{linestyle, fillstyle, x1, y2, x2, y2, radius, shadow=None} \index{marquee} \index{round_rectangle} @pydescribe{basecanvas.T.round_rectangle} @shadow \end{methoddesc} \index{Bezier curve} \begin{methoddesc}{curve}{linestyle, [(x1,y2), ..., (xn, yn)]} Draw a Bezier curve. \end{methoddesc} \begin{methoddesc}{show}{x, y, text} Draw a \var{text} on the canvas at location (\var{x, y}). Parameter \var{text} supports font manipulation, as described in \xref{module-font}. \end{methoddesc} \begin{methoddesc}{verbatim}{string} This procedure outputs an arbitrary \var{string} to the output file. \index{PostScript} \index{verbatim} \end{methoddesc} \subsection{Clipping}\label{clipping-canvas} \index{clipping} A rectangle, polygon, or ellipsis can be used to define a clipping region. Any drawing commands (\pxref{module-canvas}) issued afterward are confined in the region. You can even nest multiple clipping regions, in which case, drawings will be clipped to the intersection of the regions. \code{canvas.endclip()} ends the clipping. Clipping commands and \code{endclip()} must nest properly. @samplechartandcode{cliptest, Clipping test} The following \code{canvas.T} methods are used to control clipping: \begin{methoddesc}{clip}{x1, y1, x2, y2} @pydescribe{basecanvas.T.clip} \end{methoddesc} \begin{methoddesc}{clip_ellipsis}{x, y, radius, y_elongation} @pydescribe{basecanvas.T.clip_ellipsis} \end{methoddesc} \begin{methoddesc}{clip_polygon}{[(x1,y2),(x2,y2), ..., (xn, yn)]} @pydescribe{basecanvas.T.clip_polygon} \end{methoddesc} \begin{methoddesc}{endclip}{} @pydescribe{basecanvas.T.endclip} \end{methoddesc} \subsection{Setting canvas properties}\label{property-canvas} A \code{canvas.T} object provides the following methods to define the information about the output file. \begin{verbatim} can = canvas.init("foo.pdf") ar = area.T(...) can.set_author("Charles Dickens") can.set_title("A tale of two cities") ar.draw(can) \end{verbatim} \begin{methoddesc}{set_title}{str} \index{title (setting - of chart)} @pydescribe{basecanvas.T.set_title} \end{methoddesc} \begin{methoddesc}{set_author}{str} \index{author (setting - of chart)} @pydescribe{basecanvas.T.set_author} \end{methoddesc} \begin{methoddesc}{set_creator}{str} \index{creator (setting - of chart)} \index{producer (setting - of chart)} @pydescribe{basecanvas.T.set_creator} \end{methoddesc} \begin{methoddesc}{set_creation_date}{str} \index{date!setting creation - of chart} @pydescribe{basecanvas.T.set_creation_date} \end{methoddesc} \subsection{Shortcut functions for the default canvas}\label{default-canvas} For the default canvas (\pxref{drawing-canvas}), you can call the following functions provided in the \code{canvas} module directly: \begin{funcdesc}{line}{linestyle, x1, y1, x2, y2} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{polygon}{linestyle, fillstyle, [(x1,y1), ..., (xn, yn)]} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{rectangle}{linestyle, fillstyle, x1, y1, x2, y2, shadow=None} Calls the method with the same name on the default canvas object. @shadow \end{funcdesc} \begin{funcdesc}{ellipsis}{linestyle, fillstyle, x, y, radius, y_elongation=1, start=0, end=360, shadow=None} Calls the method with the same name on the default canvas object. @shadow \end{funcdesc} \begin{funcdesc}{round_rectangle}{linestyle, fillstyle, x1, y2, x2, y2,radius, shadow=None} Calls the method with the same name on the default canvas object. @shadow \end{funcdesc} \begin{funcdesc}{curve}{linestyle, [(x1,y2), ..., (xn, yn)]} Calls the method with the same name on the default canvas object. \end{funcdesc} \index{font} \begin{funcdesc}{show}{x, y, text} Calls the method with the same name on the default canvas object. \end{funcdesc} \index{comments!- in PS or PDF} \begin{funcdesc}{verbatim}{str} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{default_canvas}{} Return the default canvas. \end{funcdesc} \index{canvas (default -)} \begin{funcdesc}{clip}{x1, y1, x2, y2} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{clip_ellipsis}{x, y, radius, y_elongation} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{clip_polygon}{[(x1,y2),(x2,y2), ..., (xn, yn)]} Calls the method with the same name on the default canvas object. \end{funcdesc} \begin{funcdesc}{endclip}{} Calls the method with the same name on the default canvas object. \end{funcdesc} \input{pychart.ind} \end{document} PyChart-1.39/doc/markuphtml.py0000644000175000017500000000345210354321374017765 0ustar santiagosantiago00000000000000import re import sys pats = ( ("theme.get_options()", "options"), ("area.T", "module-area"), ("interval_bar_plot.T", "module-interval-bar-plot"), ("bar_plot.T", "module-bar-plot"), ("line_plot.T", "module-line-plot"), ("range_plot.T", "module-range-plot"), ("pie_plot.T", "module-pie-plot"), ("color\\.", "module-color"), ("line_style\\.", "module-line-style"), ("fill_style\\.", "module-fill-style"), ("tick_mark\\.", "module-tick-mark"), ("log_coord\\.T", "module-coord"), ("linear_coord\\.T", "module-coord"), ("category_coord\\.T", "module-coord"), ("error_bar\\.", "module-error-bar"), ("text_box\\.T", "module-text-box"), ("arrow\\.T", "module-arrow"), ("axis\\.", "module-axis"), ("chart_data\\.", "module-chart-data"), ("legend\\.", "module-legend"), ("theme\\.", "options"), ("canvas\\.", "module-canvas"), ("zap\\.", "module-zap"), ) re_pats = {} for pat, repl in pats: re_pats[re.compile("(" + pat + ")")] = repl def hackimgref(mo): path = mo.group(1) i = path.rfind("/") path2 = path[(i+1):] print >>sys.stderr, "PATH=", path, path2 return 'SRC="%s"' % path2 in_example = False for l in sys.stdin.readlines(): l = re.sub('SRC="(/nfs[^\"]+)"', hackimgref, l) if re.match(".*]*>", l): in_example = True elif l.find("") >= 0: in_example = False if not in_example: l = re.sub("", """\n""", l) print l, continue for str, ref in pats: l = re.sub("(" + str + ")", "\\1" % ref, l) #l = re.sub(str, "\\1" % ref, l) print l, PyChart-1.39/pychart/0000755000175000017500000000000010352125055016124 5ustar santiagosantiago00000000000000PyChart-1.39/pychart/afm/0000755000175000017500000000000010352125056016670 5ustar santiagosantiago00000000000000PyChart-1.39/pychart/afm/Helvetica.py0000644000175000017500000000270710354321374021157 0ustar santiagosantiago00000000000000# AFM font Helvetica (path: /usr/share/fonts/afms/adobe/phvr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 355, 556, 556, 889, 667, 222, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 222, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 191, 333, 556, 333, 333, 500, 500, 500, 556, 556, 556, 278, 500, 537, 350, 222, 333, 333, 556, 1000, 1000, 500, 611, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 370, 500, 500, 500, 500, 556, 778, 1000, 365, 500, 500, 500, 500, 500, 889, 500, 500, 500, 278, 500, 500, 222, 611, 944, 611, ) PyChart-1.39/pychart/afm/Helvetica_Bold.py0000644000175000017500000000272010354321374022112 0ustar santiagosantiago00000000000000# AFM font Helvetica-Bold (path: /usr/share/fonts/afms/adobe/phvb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 333, 474, 556, 556, 889, 722, 278, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 278, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 238, 500, 556, 333, 333, 611, 611, 500, 556, 556, 556, 278, 500, 556, 350, 278, 500, 500, 556, 1000, 1000, 500, 611, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 370, 500, 500, 500, 500, 611, 778, 1000, 365, 500, 500, 500, 500, 500, 889, 500, 500, 500, 278, 500, 500, 278, 611, 944, 611, ) PyChart-1.39/pychart/afm/Palatino_BoldItalic.py0000644000175000017500000000273210354321374023106 0ustar santiagosantiago00000000000000# AFM font Palatino-BoldItalic (path: /usr/share/fonts/afms/adobe/pplbi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Palatino-BoldItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 500, 500, 500, 889, 833, 278, 333, 333, 444, 606, 250, 389, 250, 315, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 250, 606, 606, 606, 444, 833, 722, 667, 685, 778, 611, 556, 778, 778, 389, 389, 722, 611, 944, 778, 833, 667, 833, 722, 556, 611, 778, 667, 1000, 722, 611, 667, 333, 606, 333, 606, 500, 278, 556, 537, 444, 556, 444, 333, 500, 556, 333, 333, 556, 333, 833, 556, 556, 556, 537, 389, 444, 389, 556, 556, 833, 500, 556, 500, 333, 606, 333, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 500, 500, 167, 500, 500, 556, 500, 250, 500, 500, 333, 333, 611, 611, 500, 500, 556, 556, 250, 500, 556, 606, 250, 500, 500, 500, 1000, 1000, 500, 444, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 556, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 944, 500, 333, 500, 500, 500, 500, 611, 833, 944, 333, 500, 500, 500, 500, 500, 738, 500, 500, 500, 333, 500, 500, 333, 556, 778, 556, ) PyChart-1.39/pychart/afm/Utopia_Regular.py0000644000175000017500000000271710354321374022176 0ustar santiagosantiago00000000000000# AFM font Utopia-Regular (path: /usr/share/fonts/afms/adobe/putr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Utopia-Regular"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 225, 242, 458, 530, 530, 838, 706, 278, 350, 350, 412, 570, 265, 392, 265, 460, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 265, 265, 570, 570, 570, 389, 793, 635, 646, 684, 779, 606, 580, 734, 798, 349, 350, 658, 568, 944, 780, 762, 600, 762, 644, 541, 621, 791, 634, 940, 624, 588, 610, 330, 460, 330, 570, 500, 278, 523, 598, 496, 598, 514, 319, 520, 607, 291, 280, 524, 279, 923, 619, 577, 608, 591, 389, 436, 344, 606, 504, 768, 486, 506, 480, 340, 228, 340, 570, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 242, 530, 530, 150, 530, 530, 554, 530, 278, 458, 442, 257, 257, 610, 610, 500, 500, 504, 488, 265, 500, 555, 409, 278, 458, 458, 442, 1000, 1208, 500, 389, 500, 400, 400, 400, 400, 400, 400, 400, 400, 500, 400, 400, 500, 400, 400, 400, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 876, 500, 390, 500, 500, 500, 500, 574, 762, 1025, 398, 500, 500, 500, 500, 500, 797, 500, 500, 500, 291, 500, 500, 294, 577, 882, 601, ) PyChart-1.39/pychart/afm/NewCenturySchlbk_Roman.py0000644000175000017500000000274010354321374023636 0ustar santiagosantiago00000000000000# AFM font NewCenturySchlbk-Roman (path: /usr/share/fonts/afms/adobe/pncr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["NewCenturySchlbk-Roman"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 296, 389, 556, 556, 833, 815, 204, 333, 333, 500, 606, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 606, 606, 606, 444, 737, 722, 722, 722, 778, 722, 667, 778, 833, 407, 556, 778, 667, 944, 815, 778, 667, 778, 722, 630, 667, 815, 722, 981, 704, 704, 611, 333, 606, 333, 606, 500, 204, 556, 556, 444, 574, 500, 333, 537, 611, 315, 296, 593, 315, 889, 611, 500, 574, 556, 444, 463, 389, 611, 537, 778, 537, 537, 481, 333, 606, 333, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 296, 556, 556, 167, 556, 556, 500, 556, 204, 389, 426, 259, 259, 611, 611, 500, 556, 500, 500, 278, 500, 606, 606, 204, 389, 389, 426, 1000, 1000, 500, 444, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 334, 500, 500, 500, 500, 667, 778, 1000, 300, 500, 500, 500, 500, 500, 796, 500, 500, 500, 315, 500, 500, 315, 500, 833, 574, ) PyChart-1.39/pychart/afm/Courier_BoldOblique.py0000644000175000017500000000272610354321374023145 0ustar santiagosantiago00000000000000# AFM font Courier-BoldOblique (path: /usr/share/fonts/afms/adobe/pcrbo8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Courier-BoldOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 500, 600, 500, 500, 500, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 600, 500, 500, 500, 600, 500, 500, 600, 600, 600, 600, ) PyChart-1.39/pychart/afm/Palatino_Roman.py0000644000175000017500000000271710354321374022157 0ustar santiagosantiago00000000000000# AFM font Palatino-Roman (path: /usr/share/fonts/afms/adobe/pplr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Palatino-Roman"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 278, 371, 500, 500, 840, 778, 278, 333, 333, 389, 606, 250, 333, 250, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 250, 606, 606, 606, 444, 747, 778, 611, 709, 774, 611, 556, 763, 832, 337, 333, 726, 611, 946, 831, 786, 604, 786, 668, 525, 613, 778, 722, 1000, 667, 667, 667, 333, 606, 333, 606, 500, 278, 500, 553, 444, 611, 479, 333, 556, 582, 291, 234, 556, 291, 883, 582, 546, 601, 560, 395, 424, 326, 603, 565, 834, 516, 556, 500, 333, 606, 333, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 500, 500, 167, 500, 500, 500, 500, 208, 500, 500, 331, 331, 605, 608, 500, 500, 500, 500, 250, 500, 628, 606, 278, 500, 500, 500, 1000, 1144, 500, 444, 500, 333, 333, 333, 333, 333, 333, 250, 333, 500, 333, 333, 500, 380, 313, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 944, 500, 333, 500, 500, 500, 500, 611, 833, 998, 333, 500, 500, 500, 500, 500, 758, 500, 500, 500, 287, 500, 500, 291, 556, 827, 556, ) PyChart-1.39/pychart/afm/Helvetica_LightOblique.py0000644000175000017500000000274110354321374023625 0ustar santiagosantiago00000000000000# AFM font Helvetica-LightOblique (path: /usr/share/fonts/afms/adobe/phvlo8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-LightOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 333, 278, 556, 556, 889, 667, 222, 333, 333, 389, 660, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 660, 660, 660, 500, 800, 667, 667, 722, 722, 611, 556, 778, 722, 278, 500, 667, 556, 833, 722, 778, 611, 778, 667, 611, 556, 722, 611, 889, 611, 611, 611, 333, 278, 333, 660, 500, 222, 556, 611, 556, 611, 556, 278, 611, 556, 222, 222, 500, 222, 833, 556, 556, 611, 611, 333, 500, 278, 556, 500, 722, 500, 500, 500, 333, 222, 333, 660, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 222, 389, 556, 389, 389, 500, 500, 500, 500, 556, 556, 278, 500, 650, 500, 222, 389, 389, 556, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 334, 500, 500, 500, 500, 556, 778, 1000, 334, 500, 500, 500, 500, 500, 889, 500, 500, 500, 222, 500, 500, 222, 556, 944, 500, ) PyChart-1.39/pychart/afm/Bookman_Light.py0000644000175000017500000000271610354321374021770 0ustar santiagosantiago00000000000000# AFM font Bookman-Light (path: /usr/share/fonts/afms/adobe/pbkl8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Bookman-Light"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 320, 300, 380, 620, 620, 900, 800, 220, 300, 300, 440, 600, 320, 400, 320, 600, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 320, 320, 600, 600, 600, 540, 820, 680, 740, 740, 800, 720, 640, 800, 800, 340, 600, 720, 600, 920, 740, 800, 620, 820, 720, 660, 620, 780, 700, 960, 720, 640, 640, 300, 600, 300, 600, 500, 220, 580, 620, 520, 620, 520, 320, 540, 660, 300, 300, 620, 300, 940, 660, 560, 620, 580, 440, 520, 380, 680, 520, 780, 560, 540, 480, 280, 600, 280, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 300, 620, 620, 140, 620, 620, 520, 620, 220, 400, 360, 240, 240, 620, 620, 500, 500, 540, 540, 320, 500, 600, 460, 220, 400, 400, 360, 1000, 1280, 500, 540, 500, 340, 340, 420, 440, 440, 460, 260, 420, 500, 320, 320, 500, 380, 320, 420, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1260, 500, 420, 500, 500, 500, 500, 600, 800, 1240, 420, 500, 500, 500, 500, 500, 860, 500, 500, 500, 300, 500, 500, 320, 560, 900, 660, ) PyChart-1.39/pychart/afm/Times_Roman.py0000644000175000017500000000271010354321374021462 0ustar santiagosantiago00000000000000# AFM font Times-Roman (path: /usr/share/fonts/afms/adobe/ptmr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Times-Roman"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 408, 500, 500, 833, 778, 333, 333, 333, 500, 564, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 564, 564, 564, 444, 921, 722, 667, 667, 722, 611, 556, 722, 722, 333, 389, 722, 611, 889, 722, 722, 556, 722, 667, 556, 611, 722, 722, 944, 722, 722, 611, 333, 278, 333, 469, 500, 333, 444, 500, 444, 500, 444, 333, 500, 500, 278, 278, 500, 278, 778, 500, 500, 500, 500, 333, 389, 278, 500, 500, 722, 500, 500, 444, 480, 200, 480, 541, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 500, 500, 167, 500, 500, 500, 500, 180, 444, 500, 333, 333, 556, 556, 500, 500, 500, 500, 250, 500, 453, 350, 333, 444, 444, 500, 1000, 1000, 500, 444, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 889, 500, 276, 500, 500, 500, 500, 611, 722, 889, 310, 500, 500, 500, 500, 500, 667, 500, 500, 500, 278, 500, 500, 278, 500, 722, 500, ) PyChart-1.39/pychart/afm/Courier.py0000644000175000017500000000267510354321374020667 0ustar santiagosantiago00000000000000# AFM font Courier (path: /usr/share/fonts/afms/adobe/pcrr8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Courier"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 500, 600, 500, 500, 500, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 600, 500, 500, 500, 600, 500, 500, 600, 600, 600, 600, ) PyChart-1.39/pychart/afm/Bookman_Demi.py0000644000175000017500000000271510354321374021576 0ustar santiagosantiago00000000000000# AFM font Bookman-Demi (path: /usr/share/fonts/afms/adobe/pbkd8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Bookman-Demi"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 340, 360, 420, 660, 660, 940, 800, 320, 320, 320, 460, 600, 340, 360, 340, 600, 660, 660, 660, 660, 660, 660, 660, 660, 660, 660, 340, 340, 600, 600, 600, 660, 820, 720, 720, 740, 780, 720, 680, 780, 820, 400, 640, 800, 640, 940, 740, 800, 660, 800, 780, 660, 700, 740, 720, 940, 780, 700, 640, 300, 600, 300, 600, 500, 320, 580, 600, 580, 640, 580, 380, 580, 680, 360, 340, 660, 340, 1000, 680, 620, 640, 620, 460, 520, 460, 660, 600, 800, 600, 620, 560, 320, 600, 320, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 360, 660, 660, 120, 660, 660, 600, 660, 240, 540, 400, 220, 220, 740, 740, 500, 500, 440, 380, 340, 500, 800, 460, 320, 540, 540, 400, 1000, 1360, 500, 660, 500, 400, 400, 500, 480, 460, 500, 320, 500, 500, 340, 360, 500, 440, 320, 500, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1140, 500, 400, 500, 500, 500, 500, 640, 800, 1220, 400, 500, 500, 500, 500, 500, 880, 500, 500, 500, 360, 500, 500, 340, 620, 940, 660, ) PyChart-1.39/pychart/afm/ZapfDingbats.py0000644000175000017500000000272510354321374021627 0ustar santiagosantiago00000000000000# AFM font ZapfDingbats (path: /usr/share/fonts/afms/adobe/pzdr.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["ZapfDingbats"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 974, 961, 974, 980, 719, 789, 790, 791, 690, 960, 939, 549, 855, 911, 933, 911, 945, 974, 755, 846, 762, 761, 571, 677, 763, 760, 759, 754, 494, 552, 537, 577, 692, 786, 788, 788, 790, 793, 794, 816, 823, 789, 841, 823, 833, 816, 831, 923, 744, 723, 749, 790, 792, 695, 776, 768, 792, 759, 707, 708, 682, 701, 826, 815, 789, 789, 707, 687, 696, 689, 786, 787, 713, 791, 785, 791, 873, 761, 762, 762, 759, 759, 892, 892, 788, 784, 438, 138, 277, 415, 392, 392, 668, 668, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 732, 544, 544, 910, 667, 760, 760, 776, 595, 694, 626, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 788, 894, 838, 1016, 458, 748, 924, 748, 918, 927, 928, 928, 834, 873, 828, 924, 924, 917, 930, 931, 463, 883, 836, 836, 867, 867, 696, 696, 874, 500, 874, 760, 946, 771, 865, 771, 888, 967, 888, 831, 873, 927, 970, 918, ) PyChart-1.39/pychart/afm/Helvetica_Oblique.py0000644000175000017500000000273010354321374022633 0ustar santiagosantiago00000000000000# AFM font Helvetica-Oblique (path: /usr/share/fonts/afms/adobe/phvro8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Oblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 355, 556, 556, 889, 667, 222, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 222, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 191, 333, 556, 333, 333, 500, 500, 500, 556, 556, 556, 278, 500, 537, 350, 222, 333, 333, 556, 1000, 1000, 500, 611, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 370, 500, 500, 500, 500, 556, 778, 1000, 365, 500, 500, 500, 500, 500, 889, 500, 500, 500, 278, 500, 500, 222, 611, 944, 611, ) PyChart-1.39/pychart/afm/ZapfChancery_MediumItalic.py0000644000175000017500000000274310354321374024256 0ustar santiagosantiago00000000000000# AFM font ZapfChancery-MediumItalic (path: /usr/share/fonts/afms/adobe/pzcmi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["ZapfChancery-MediumItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 220, 280, 220, 440, 440, 680, 780, 240, 260, 220, 420, 520, 220, 280, 220, 340, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 260, 240, 520, 520, 520, 380, 700, 620, 600, 520, 700, 620, 580, 620, 680, 380, 400, 660, 580, 840, 700, 600, 540, 600, 600, 460, 500, 740, 640, 880, 560, 560, 620, 240, 480, 320, 520, 500, 240, 420, 420, 340, 440, 340, 320, 400, 440, 240, 220, 440, 240, 620, 460, 400, 440, 400, 300, 320, 320, 460, 440, 680, 420, 400, 440, 240, 520, 240, 520, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 280, 440, 440, 60, 440, 440, 420, 440, 160, 340, 340, 240, 260, 520, 520, 500, 500, 460, 480, 220, 500, 500, 600, 180, 280, 360, 380, 1000, 960, 500, 400, 500, 220, 300, 340, 440, 440, 440, 220, 360, 500, 300, 300, 500, 400, 280, 340, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 740, 500, 260, 500, 500, 500, 500, 580, 660, 820, 260, 500, 500, 500, 500, 500, 540, 500, 500, 500, 240, 500, 500, 300, 440, 560, 420, ) PyChart-1.39/pychart/afm/Helvetica_Narrow_BoldOblique.py0000644000175000017500000000275110354321374024767 0ustar santiagosantiago00000000000000# AFM font Helvetica-Narrow-BoldOblique (path: /usr/share/fonts/afms/adobe/phvbo8an.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Narrow-BoldOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 228, 273, 389, 456, 456, 729, 592, 228, 273, 273, 319, 479, 228, 273, 228, 228, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 273, 273, 479, 479, 479, 501, 800, 592, 592, 592, 592, 547, 501, 638, 592, 228, 456, 592, 501, 683, 592, 638, 547, 638, 592, 547, 501, 592, 547, 774, 547, 547, 501, 273, 228, 273, 479, 456, 228, 456, 501, 456, 501, 456, 273, 501, 501, 228, 228, 456, 228, 729, 501, 501, 501, 501, 319, 456, 273, 501, 456, 638, 456, 456, 410, 319, 230, 319, 479, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 273, 456, 456, 137, 456, 456, 456, 456, 195, 410, 456, 273, 273, 501, 501, 500, 456, 456, 456, 228, 500, 456, 287, 228, 410, 410, 456, 820, 820, 500, 501, 500, 273, 273, 273, 273, 273, 273, 273, 273, 500, 273, 273, 500, 273, 273, 273, 820, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 820, 500, 303, 500, 500, 500, 500, 501, 638, 820, 299, 500, 500, 500, 500, 500, 729, 500, 500, 500, 228, 500, 500, 228, 501, 774, 501, ) PyChart-1.39/pychart/afm/Courier_Bold.py0000644000175000017500000000270710354321374021623 0ustar santiagosantiago00000000000000# AFM font Courier-Bold (path: /usr/share/fonts/afms/adobe/pcrb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Courier-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 500, 600, 500, 500, 500, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 600, 500, 500, 500, 600, 500, 500, 600, 600, 600, 600, ) PyChart-1.39/pychart/afm/Helvetica_Narrow_Oblique.py0000644000175000017500000000274110354321374024165 0ustar santiagosantiago00000000000000# AFM font Helvetica-Narrow-Oblique (path: /usr/share/fonts/afms/adobe/phvro8an.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Narrow-Oblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 228, 228, 291, 456, 456, 729, 547, 182, 273, 273, 319, 479, 228, 273, 228, 228, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 228, 228, 479, 479, 479, 456, 832, 547, 547, 592, 592, 547, 501, 638, 592, 228, 410, 547, 456, 683, 592, 638, 547, 638, 592, 547, 501, 592, 547, 774, 547, 547, 501, 228, 228, 228, 385, 456, 182, 456, 456, 410, 456, 456, 228, 456, 456, 182, 182, 410, 182, 683, 456, 456, 456, 456, 273, 410, 228, 456, 410, 592, 410, 410, 410, 274, 213, 274, 479, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 273, 456, 456, 137, 456, 456, 456, 456, 157, 273, 456, 273, 273, 410, 410, 500, 456, 456, 456, 228, 500, 440, 287, 182, 273, 273, 456, 820, 820, 500, 501, 500, 273, 273, 273, 273, 273, 273, 273, 273, 500, 273, 273, 500, 273, 273, 273, 820, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 820, 500, 303, 500, 500, 500, 500, 456, 638, 820, 299, 500, 500, 500, 500, 500, 729, 500, 500, 500, 228, 500, 500, 182, 501, 774, 501, ) PyChart-1.39/pychart/afm/Bookman_LightItalic.py0000644000175000017500000000273210354321374023114 0ustar santiagosantiago00000000000000# AFM font Bookman-LightItalic (path: /usr/share/fonts/afms/adobe/pbkli8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Bookman-LightItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 300, 320, 360, 620, 620, 800, 820, 280, 280, 280, 440, 600, 300, 320, 300, 600, 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, 300, 300, 600, 600, 600, 540, 780, 700, 720, 720, 740, 680, 620, 760, 800, 320, 560, 720, 580, 860, 720, 760, 600, 780, 700, 640, 600, 720, 680, 960, 700, 660, 580, 260, 600, 260, 600, 500, 280, 620, 600, 480, 640, 540, 340, 560, 620, 280, 280, 600, 280, 880, 620, 540, 600, 560, 400, 540, 340, 620, 540, 880, 540, 600, 520, 360, 600, 380, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 320, 620, 620, 20, 620, 620, 620, 620, 200, 440, 300, 180, 180, 640, 660, 500, 500, 620, 620, 300, 500, 620, 460, 320, 480, 440, 300, 1000, 1180, 500, 540, 500, 340, 320, 440, 440, 440, 440, 260, 420, 500, 300, 320, 500, 340, 260, 440, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1220, 500, 440, 500, 500, 500, 500, 580, 760, 1180, 400, 500, 500, 500, 500, 500, 880, 500, 500, 500, 280, 500, 500, 340, 540, 900, 620, ) PyChart-1.39/pychart/afm/dir.py0000644000175000017500000000001410354321374020016 0ustar santiagosantiago00000000000000afm = {} PyChart-1.39/pychart/afm/NewCenturySchlbk_BoldItalic.py0000644000175000017500000000275110354321374024572 0ustar santiagosantiago00000000000000# AFM font NewCenturySchlbk-BoldItalic (path: /usr/share/fonts/afms/adobe/pncbi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["NewCenturySchlbk-BoldItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 287, 333, 400, 574, 574, 889, 889, 259, 407, 407, 500, 606, 287, 333, 287, 278, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 287, 287, 606, 606, 606, 481, 747, 741, 759, 759, 833, 741, 704, 815, 870, 444, 667, 778, 704, 944, 852, 833, 741, 833, 796, 685, 722, 833, 741, 944, 741, 704, 704, 407, 606, 407, 606, 500, 259, 667, 611, 537, 667, 519, 389, 611, 685, 389, 370, 648, 389, 944, 685, 574, 648, 630, 519, 481, 407, 685, 556, 833, 574, 519, 519, 407, 606, 407, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 574, 574, 167, 574, 574, 500, 574, 287, 481, 481, 278, 278, 685, 685, 500, 500, 500, 500, 287, 500, 650, 606, 259, 481, 481, 481, 1000, 1167, 500, 481, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 889, 500, 412, 500, 500, 500, 500, 704, 833, 963, 356, 500, 500, 500, 500, 500, 815, 500, 500, 500, 389, 500, 500, 389, 574, 852, 574, ) PyChart-1.39/pychart/afm/Helvetica_Light.py0000644000175000017500000000272210354321374022303 0ustar santiagosantiago00000000000000# AFM font Helvetica-Light (path: /usr/share/fonts/afms/adobe/phvl8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Light"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 333, 278, 556, 556, 889, 667, 222, 333, 333, 389, 660, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 660, 660, 660, 500, 800, 667, 667, 722, 722, 611, 556, 778, 722, 278, 500, 667, 556, 833, 722, 778, 611, 778, 667, 611, 556, 722, 611, 889, 611, 611, 611, 333, 278, 333, 660, 500, 222, 556, 611, 556, 611, 556, 278, 611, 556, 222, 222, 500, 222, 833, 556, 556, 611, 611, 333, 500, 278, 556, 500, 722, 500, 500, 500, 333, 222, 333, 660, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 222, 389, 556, 389, 389, 500, 500, 500, 500, 556, 556, 278, 500, 650, 500, 222, 389, 389, 556, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 334, 500, 500, 500, 500, 556, 778, 1000, 334, 500, 500, 500, 500, 500, 889, 500, 500, 500, 222, 500, 500, 222, 556, 944, 500, ) PyChart-1.39/pychart/afm/Palatino_Bold.py0000644000175000017500000000272010354321374021755 0ustar santiagosantiago00000000000000# AFM font Palatino-Bold (path: /usr/share/fonts/afms/adobe/pplb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Palatino-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 278, 402, 500, 500, 889, 833, 278, 333, 333, 444, 606, 250, 333, 250, 296, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 250, 606, 606, 606, 444, 747, 778, 667, 722, 833, 611, 556, 833, 833, 389, 389, 778, 611, 1000, 833, 833, 611, 833, 722, 611, 667, 778, 778, 1000, 667, 667, 667, 333, 606, 333, 606, 500, 278, 500, 611, 444, 611, 500, 389, 556, 611, 333, 333, 611, 333, 889, 611, 556, 611, 611, 389, 444, 333, 611, 556, 833, 500, 556, 500, 310, 606, 310, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 500, 500, 167, 500, 500, 500, 500, 227, 500, 500, 389, 389, 611, 611, 500, 500, 500, 500, 250, 500, 641, 606, 333, 500, 500, 500, 1000, 1000, 500, 444, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 438, 500, 500, 500, 500, 611, 833, 1000, 488, 500, 500, 500, 500, 500, 778, 500, 500, 500, 333, 500, 500, 333, 556, 833, 611, ) PyChart-1.39/pychart/afm/Utopia_BoldItalic.py0000644000175000017500000000272610354321374022603 0ustar santiagosantiago00000000000000# AFM font Utopia-BoldItalic (path: /usr/share/fonts/afms/adobe/putbi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Utopia-BoldItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 210, 285, 455, 560, 560, 896, 752, 246, 350, 350, 500, 600, 280, 392, 280, 260, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 280, 280, 600, 600, 600, 454, 828, 634, 680, 672, 774, 622, 585, 726, 800, 386, 388, 688, 586, 921, 741, 761, 660, 761, 681, 551, 616, 776, 630, 920, 630, 622, 618, 350, 460, 350, 600, 500, 246, 596, 586, 456, 609, 476, 348, 522, 629, 339, 333, 570, 327, 914, 635, 562, 606, 584, 440, 417, 359, 634, 518, 795, 516, 489, 466, 340, 265, 340, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 285, 560, 560, 100, 560, 560, 568, 560, 246, 455, 560, 360, 360, 651, 652, 500, 500, 514, 490, 280, 500, 580, 465, 246, 455, 455, 560, 1000, 1297, 500, 454, 500, 400, 400, 400, 400, 400, 400, 402, 400, 500, 400, 400, 500, 400, 350, 400, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 890, 500, 444, 500, 500, 500, 500, 592, 761, 1016, 412, 500, 500, 500, 500, 500, 789, 500, 500, 500, 339, 500, 500, 339, 562, 811, 628, ) PyChart-1.39/pychart/afm/AvantGarde_BookOblique.py0000644000175000017500000000274210354321374023561 0ustar santiagosantiago00000000000000# AFM font AvantGarde-BookOblique (path: /usr/share/fonts/afms/adobe/pagko8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["AvantGarde-BookOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 277, 295, 309, 554, 554, 775, 757, 351, 369, 369, 425, 606, 277, 332, 277, 437, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 277, 277, 606, 606, 606, 591, 867, 740, 574, 813, 744, 536, 485, 872, 683, 226, 482, 591, 462, 919, 740, 869, 592, 871, 607, 498, 426, 655, 702, 960, 609, 592, 480, 351, 605, 351, 606, 500, 351, 683, 682, 647, 685, 650, 314, 673, 610, 200, 203, 502, 200, 938, 610, 655, 682, 682, 301, 388, 339, 608, 554, 831, 480, 536, 425, 351, 672, 351, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 295, 554, 554, 166, 554, 554, 615, 554, 198, 502, 425, 251, 251, 487, 485, 500, 500, 553, 553, 277, 500, 564, 606, 354, 502, 484, 425, 1000, 1174, 500, 591, 500, 378, 375, 502, 439, 485, 453, 222, 369, 500, 332, 324, 500, 552, 302, 502, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 992, 500, 369, 500, 500, 500, 500, 517, 868, 1194, 369, 500, 500, 500, 500, 500, 1157, 500, 500, 500, 200, 500, 500, 300, 653, 1137, 554, ) PyChart-1.39/pychart/afm/Palatino_Italic.py0000644000175000017500000000272210354321374022304 0ustar santiagosantiago00000000000000# AFM font Palatino-Italic (path: /usr/share/fonts/afms/adobe/pplri8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Palatino-Italic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 500, 500, 500, 889, 778, 278, 333, 333, 389, 606, 250, 333, 250, 296, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 250, 606, 606, 606, 500, 747, 722, 611, 667, 778, 611, 556, 722, 778, 333, 333, 667, 556, 944, 778, 778, 611, 778, 667, 556, 611, 778, 722, 944, 722, 667, 667, 333, 606, 333, 606, 500, 278, 444, 463, 407, 500, 389, 278, 500, 500, 278, 278, 444, 278, 778, 556, 444, 500, 463, 389, 389, 333, 556, 500, 722, 500, 500, 444, 333, 606, 333, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 500, 500, 167, 500, 500, 500, 500, 333, 500, 500, 333, 333, 528, 545, 500, 500, 500, 500, 250, 500, 500, 500, 278, 500, 500, 500, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 941, 500, 333, 500, 500, 500, 500, 556, 778, 1028, 333, 500, 500, 500, 500, 500, 638, 500, 500, 500, 278, 500, 500, 278, 444, 669, 500, ) PyChart-1.39/pychart/afm/Times_Bold.py0000644000175000017500000000271210354321374021270 0ustar santiagosantiago00000000000000# AFM font Times-Bold (path: /usr/share/fonts/afms/adobe/ptmb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Times-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 555, 500, 500, 1000, 833, 333, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 930, 722, 667, 722, 722, 667, 611, 778, 778, 389, 500, 778, 667, 944, 722, 778, 611, 778, 722, 556, 667, 722, 722, 1000, 722, 722, 667, 333, 278, 333, 581, 500, 333, 500, 556, 444, 556, 444, 333, 500, 556, 278, 333, 556, 278, 833, 556, 500, 556, 556, 444, 389, 333, 556, 500, 722, 500, 500, 444, 394, 220, 394, 520, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 500, 500, 167, 500, 500, 500, 500, 278, 500, 500, 333, 333, 556, 556, 500, 500, 500, 500, 250, 500, 540, 350, 333, 500, 500, 500, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 300, 500, 500, 500, 500, 667, 778, 1000, 330, 500, 500, 500, 500, 500, 722, 500, 500, 500, 278, 500, 500, 278, 500, 722, 556, ) PyChart-1.39/pychart/afm/Helvetica_BoldOblique.py0000644000175000017500000000273710354321374023443 0ustar santiagosantiago00000000000000# AFM font Helvetica-BoldOblique (path: /usr/share/fonts/afms/adobe/phvbo8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-BoldOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 333, 474, 556, 556, 889, 722, 278, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 278, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 556, 556, 238, 500, 556, 333, 333, 611, 611, 500, 556, 556, 556, 278, 500, 556, 350, 278, 500, 500, 556, 1000, 1000, 500, 611, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1000, 500, 370, 500, 500, 500, 500, 611, 778, 1000, 365, 500, 500, 500, 500, 500, 889, 500, 500, 500, 278, 500, 500, 278, 611, 944, 611, ) PyChart-1.39/pychart/afm/Helvetica_Narrow.py0000644000175000017500000000272010354321374022502 0ustar santiagosantiago00000000000000# AFM font Helvetica-Narrow (path: /usr/share/fonts/afms/adobe/phvr8an.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Narrow"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 228, 228, 291, 456, 456, 729, 547, 182, 273, 273, 319, 479, 228, 273, 228, 228, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 228, 228, 479, 479, 479, 456, 832, 547, 547, 592, 592, 547, 501, 638, 592, 228, 410, 547, 456, 683, 592, 638, 547, 638, 592, 547, 501, 592, 547, 774, 547, 547, 501, 228, 228, 228, 385, 456, 182, 456, 456, 410, 456, 456, 228, 456, 456, 182, 182, 410, 182, 683, 456, 456, 456, 456, 273, 410, 228, 456, 410, 592, 410, 410, 410, 274, 213, 274, 479, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 273, 456, 456, 137, 456, 456, 456, 456, 157, 273, 456, 273, 273, 410, 410, 500, 456, 456, 456, 228, 500, 440, 287, 182, 273, 273, 456, 820, 820, 500, 501, 500, 273, 273, 273, 273, 273, 273, 273, 273, 500, 273, 273, 500, 273, 273, 273, 820, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 820, 500, 303, 500, 500, 500, 500, 456, 638, 820, 299, 500, 500, 500, 500, 500, 729, 500, 500, 500, 228, 500, 500, 182, 501, 774, 501, ) PyChart-1.39/pychart/afm/NewCenturySchlbk_Bold.py0000644000175000017500000000273510354321374023446 0ustar santiagosantiago00000000000000# AFM font NewCenturySchlbk-Bold (path: /usr/share/fonts/afms/adobe/pncb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["NewCenturySchlbk-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 287, 296, 333, 574, 574, 833, 852, 241, 389, 389, 500, 606, 278, 333, 278, 278, 574, 574, 574, 574, 574, 574, 574, 574, 574, 574, 278, 278, 606, 606, 606, 500, 747, 759, 778, 778, 833, 759, 722, 833, 870, 444, 648, 815, 722, 981, 833, 833, 759, 833, 815, 667, 722, 833, 759, 981, 722, 722, 667, 389, 606, 389, 606, 500, 241, 611, 648, 556, 667, 574, 389, 611, 685, 370, 352, 667, 352, 963, 685, 611, 667, 648, 519, 500, 426, 685, 611, 889, 611, 611, 537, 389, 606, 389, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 296, 574, 574, 167, 574, 574, 500, 574, 241, 481, 500, 333, 333, 685, 685, 500, 500, 500, 500, 278, 500, 747, 606, 241, 481, 481, 500, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 981, 500, 367, 500, 500, 500, 500, 722, 833, 1000, 367, 500, 500, 500, 500, 500, 870, 500, 500, 500, 370, 500, 500, 352, 611, 907, 611, ) PyChart-1.39/pychart/afm/NewCenturySchlbk_Italic.py0000644000175000017500000000274110354321374023770 0ustar santiagosantiago00000000000000# AFM font NewCenturySchlbk-Italic (path: /usr/share/fonts/afms/adobe/pncri8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["NewCenturySchlbk-Italic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 333, 400, 556, 556, 833, 852, 204, 333, 333, 500, 606, 278, 333, 278, 606, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 606, 606, 606, 444, 747, 704, 722, 722, 778, 722, 667, 778, 833, 407, 611, 741, 667, 944, 815, 778, 667, 778, 741, 667, 685, 815, 704, 926, 704, 685, 667, 333, 606, 333, 606, 500, 204, 574, 556, 444, 611, 444, 333, 537, 611, 333, 315, 556, 333, 889, 611, 500, 574, 556, 444, 444, 352, 611, 519, 778, 500, 500, 463, 333, 606, 333, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 556, 556, 167, 556, 556, 500, 556, 278, 389, 426, 333, 333, 611, 611, 500, 500, 500, 500, 278, 500, 650, 606, 204, 389, 389, 426, 1000, 1000, 500, 444, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 870, 500, 422, 500, 500, 500, 500, 667, 778, 981, 372, 500, 500, 500, 500, 500, 722, 500, 500, 500, 333, 500, 500, 333, 500, 778, 556, ) PyChart-1.39/pychart/afm/Courier_Oblique.py0000644000175000017500000000271610354321374022343 0ustar santiagosantiago00000000000000# AFM font Courier-Oblique (path: /usr/share/fonts/afms/adobe/pcrro8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Courier-Oblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 600, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 500, 600, 600, 600, 600, 600, 600, 600, 600, 500, 600, 600, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 600, 500, 600, 500, 500, 500, 500, 600, 600, 600, 600, 500, 500, 500, 500, 500, 600, 500, 500, 500, 600, 500, 500, 600, 600, 600, 600, ) PyChart-1.39/pychart/afm/Bookman_DemiItalic.py0000644000175000017500000000273210354321374022723 0ustar santiagosantiago00000000000000# AFM font Bookman-DemiItalic (path: /usr/share/fonts/afms/adobe/pbkdi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Bookman-DemiItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 340, 320, 380, 680, 680, 880, 980, 320, 260, 260, 460, 600, 340, 280, 340, 360, 680, 680, 680, 680, 680, 680, 680, 680, 680, 680, 340, 340, 620, 600, 620, 620, 780, 720, 720, 700, 760, 720, 660, 760, 800, 380, 620, 780, 640, 860, 740, 760, 640, 760, 740, 700, 700, 740, 660, 1000, 740, 660, 680, 260, 580, 260, 620, 500, 320, 680, 600, 560, 680, 560, 420, 620, 700, 380, 320, 700, 380, 960, 680, 600, 660, 620, 500, 540, 440, 680, 540, 860, 620, 600, 560, 300, 620, 300, 620, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 320, 680, 680, 120, 680, 680, 620, 680, 180, 520, 380, 220, 220, 820, 820, 500, 500, 420, 420, 340, 500, 680, 360, 300, 520, 520, 380, 1000, 1360, 500, 620, 500, 380, 340, 480, 480, 480, 460, 380, 520, 500, 360, 360, 500, 560, 320, 480, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 1140, 500, 440, 500, 500, 500, 500, 640, 760, 1180, 440, 500, 500, 500, 500, 500, 880, 500, 500, 500, 380, 500, 500, 380, 600, 920, 660, ) PyChart-1.39/pychart/afm/AvantGarde_Book.py0000644000175000017500000000272310354321374022237 0ustar santiagosantiago00000000000000# AFM font AvantGarde-Book (path: /usr/share/fonts/afms/adobe/pagk8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["AvantGarde-Book"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 277, 295, 309, 554, 554, 775, 757, 351, 369, 369, 425, 606, 277, 332, 277, 437, 554, 554, 554, 554, 554, 554, 554, 554, 554, 554, 277, 277, 606, 606, 606, 591, 867, 740, 574, 813, 744, 536, 485, 872, 683, 226, 482, 591, 462, 919, 740, 869, 592, 871, 607, 498, 426, 655, 702, 960, 609, 592, 480, 351, 605, 351, 606, 500, 351, 683, 682, 647, 685, 650, 314, 673, 610, 200, 203, 502, 200, 938, 610, 655, 682, 682, 301, 388, 339, 608, 554, 831, 480, 536, 425, 351, 672, 351, 606, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 295, 554, 554, 166, 554, 554, 615, 554, 198, 502, 425, 251, 251, 487, 485, 500, 500, 553, 553, 277, 500, 564, 606, 354, 502, 484, 425, 1000, 1174, 500, 591, 500, 378, 375, 502, 439, 485, 453, 222, 369, 500, 332, 324, 500, 552, 302, 502, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 992, 500, 369, 500, 500, 500, 500, 517, 868, 1194, 369, 500, 500, 500, 500, 500, 1157, 500, 500, 500, 200, 500, 500, 300, 653, 1137, 554, ) PyChart-1.39/pychart/afm/AvantGarde_DemiOblique.py0000644000175000017500000000274210354321374023545 0ustar santiagosantiago00000000000000# AFM font AvantGarde-DemiOblique (path: /usr/share/fonts/afms/adobe/pagdo8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["AvantGarde-DemiOblique"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 280, 280, 360, 560, 560, 860, 680, 280, 380, 380, 440, 600, 280, 420, 280, 460, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 280, 280, 600, 600, 600, 560, 740, 740, 580, 780, 700, 520, 480, 840, 680, 280, 480, 620, 440, 900, 740, 840, 560, 840, 580, 520, 420, 640, 700, 900, 680, 620, 500, 320, 640, 320, 600, 500, 280, 660, 660, 640, 660, 640, 280, 660, 600, 240, 260, 580, 240, 940, 600, 640, 660, 660, 320, 440, 300, 600, 560, 800, 560, 580, 460, 340, 600, 340, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 280, 560, 560, 160, 560, 560, 560, 560, 220, 480, 460, 240, 240, 520, 520, 500, 500, 560, 560, 280, 500, 600, 600, 280, 480, 480, 460, 1000, 1280, 500, 560, 500, 420, 420, 540, 480, 420, 480, 280, 500, 500, 360, 340, 500, 700, 340, 540, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 900, 500, 360, 500, 500, 500, 500, 480, 840, 1060, 360, 500, 500, 500, 500, 500, 1080, 500, 500, 500, 240, 500, 500, 320, 660, 1080, 600, ) PyChart-1.39/pychart/afm/Utopia_Bold.py0000644000175000017500000000271110354321374021447 0ustar santiagosantiago00000000000000# AFM font Utopia-Bold (path: /usr/share/fonts/afms/adobe/putb8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Utopia-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 210, 278, 473, 560, 560, 887, 748, 252, 365, 365, 442, 600, 280, 392, 280, 378, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 280, 280, 600, 600, 600, 456, 833, 644, 683, 689, 777, 629, 593, 726, 807, 384, 386, 707, 585, 918, 739, 768, 650, 768, 684, 561, 624, 786, 645, 933, 634, 617, 614, 335, 379, 335, 600, 500, 252, 544, 605, 494, 605, 519, 342, 533, 631, 316, 316, 582, 309, 948, 638, 585, 615, 597, 440, 446, 370, 629, 520, 774, 522, 524, 483, 365, 284, 365, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 560, 560, 100, 560, 560, 566, 560, 252, 473, 487, 287, 287, 639, 639, 500, 500, 510, 486, 280, 500, 552, 455, 252, 473, 473, 487, 1000, 1289, 500, 456, 500, 430, 430, 430, 430, 430, 430, 430, 430, 500, 430, 430, 500, 430, 430, 430, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 879, 500, 405, 500, 500, 500, 500, 591, 768, 1049, 427, 500, 500, 500, 500, 500, 806, 500, 500, 500, 316, 500, 500, 321, 585, 866, 662, ) PyChart-1.39/pychart/afm/AvantGarde_Demi.py0000644000175000017500000000272310354321374022223 0ustar santiagosantiago00000000000000# AFM font AvantGarde-Demi (path: /usr/share/fonts/afms/adobe/pagd8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["AvantGarde-Demi"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 280, 280, 360, 560, 560, 860, 680, 280, 380, 380, 440, 600, 280, 420, 280, 460, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 280, 280, 600, 600, 600, 560, 740, 740, 580, 780, 700, 520, 480, 840, 680, 280, 480, 620, 440, 900, 740, 840, 560, 840, 580, 520, 420, 640, 700, 900, 680, 620, 500, 320, 640, 320, 600, 500, 280, 660, 660, 640, 660, 640, 280, 660, 600, 240, 260, 580, 240, 940, 600, 640, 660, 660, 320, 440, 300, 600, 560, 800, 560, 580, 460, 340, 600, 340, 600, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 280, 560, 560, 160, 560, 560, 560, 560, 220, 480, 460, 240, 240, 520, 520, 500, 500, 560, 560, 280, 500, 600, 600, 280, 480, 480, 460, 1000, 1280, 500, 560, 500, 420, 420, 540, 480, 420, 480, 280, 500, 500, 360, 340, 500, 700, 340, 540, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 900, 500, 360, 500, 500, 500, 500, 480, 840, 1060, 360, 500, 500, 500, 500, 500, 1080, 500, 500, 500, 240, 500, 500, 320, 660, 1080, 600, ) PyChart-1.39/pychart/afm/__init__.py0000644000175000017500000000153310354321374021006 0ustar santiagosantiago00000000000000__all__ = ["Courier_Oblique", "AvantGarde_BookOblique", "Times_Italic", "Helvetica_Bold", "NewCenturySchlbk_Roman", "Helvetica", "Helvetica_Narrow", "AvantGarde_Demi", "Times_BoldItalic", "Helvetica_Narrow_Bold", "Helvetica_Light", "Bookman_DemiItalic", "Utopia_Regular", "Times_Roman", "Palatino_Italic", "Courier_Bold", "ZapfChancery_MediumItalic", "NewCenturySchlbk_Italic", "NewCenturySchlbk_BoldItalic", "Helvetica_Narrow_BoldOblique", "Courier", "AvantGarde_DemiOblique", "Courier_BoldOblique", "Bookman_LightItalic", "Symbol", "Utopia_Bold", "Times_Bold", "Helvetica_BoldOblique", "Utopia_BoldItalic", "AvantGarde_Book", "Bookman_Demi", "Palatino_Roman", "Bookman_Light", "Utopia_Italic", "NewCenturySchlbk_Bold", "Helvetica_LightOblique", "ZapfDingbats", "Helvetica_Narrow_Oblique", "Helvetica_Oblique", "Palatino_BoldItalic", "Palatino_Bold", "dir"] PyChart-1.39/pychart/afm/Symbol.py0000644000175000017500000000271410354321374020516 0ustar santiagosantiago00000000000000# AFM font Symbol (path: /usr/share/fonts/afms/adobe/psyr.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Symbol"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 713, 500, 549, 833, 778, 439, 333, 333, 500, 549, 250, 549, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 278, 278, 549, 549, 549, 444, 549, 722, 667, 722, 612, 611, 763, 603, 722, 333, 631, 722, 686, 889, 722, 722, 768, 741, 556, 592, 611, 690, 439, 768, 645, 795, 611, 333, 863, 333, 658, 500, 500, 631, 549, 549, 494, 439, 521, 411, 603, 329, 603, 549, 549, 576, 521, 549, 549, 521, 549, 603, 439, 576, 713, 686, 493, 686, 494, 480, 200, 480, 549, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 620, 247, 549, 167, 713, 500, 753, 753, 753, 753, 1042, 987, 603, 987, 603, 400, 549, 411, 549, 549, 713, 494, 460, 549, 549, 549, 549, 1000, 603, 1000, 658, 823, 686, 795, 987, 768, 768, 823, 768, 768, 713, 713, 713, 713, 713, 713, 713, 768, 713, 790, 790, 890, 823, 549, 250, 713, 603, 603, 1042, 987, 603, 987, 603, 494, 329, 790, 790, 786, 713, 384, 384, 384, 384, 384, 384, 494, 494, 494, 494, 500, 329, 274, 686, 686, 686, 384, 384, 384, 384, 384, 384, 494, 494, 494, ) PyChart-1.39/pychart/afm/Times_Italic.py0000644000175000017500000000271110354321374021614 0ustar santiagosantiago00000000000000# AFM font Times-Italic (path: /usr/share/fonts/afms/adobe/ptmri8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Times-Italic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 333, 420, 500, 500, 833, 778, 333, 333, 333, 500, 675, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 675, 675, 675, 500, 920, 611, 611, 667, 722, 611, 611, 722, 722, 333, 444, 667, 556, 833, 667, 722, 611, 722, 611, 500, 556, 722, 611, 833, 611, 556, 556, 389, 278, 389, 422, 500, 333, 500, 500, 444, 500, 444, 278, 500, 500, 278, 278, 444, 278, 722, 500, 500, 500, 500, 389, 389, 278, 500, 444, 667, 444, 444, 389, 400, 275, 400, 541, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 389, 500, 500, 167, 500, 500, 500, 500, 214, 556, 500, 333, 333, 500, 500, 500, 500, 500, 500, 250, 500, 523, 350, 333, 556, 556, 500, 889, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 889, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 889, 500, 276, 500, 500, 500, 500, 556, 722, 944, 310, 500, 500, 500, 500, 500, 667, 500, 500, 500, 278, 500, 500, 278, 500, 667, 500, ) PyChart-1.39/pychart/afm/Helvetica_Narrow_Bold.py0000644000175000017500000000273210354321374023445 0ustar santiagosantiago00000000000000# AFM font Helvetica-Narrow-Bold (path: /usr/share/fonts/afms/adobe/phvb8an.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Helvetica-Narrow-Bold"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 228, 273, 389, 456, 456, 729, 592, 228, 273, 273, 319, 479, 228, 273, 228, 228, 456, 456, 456, 456, 456, 456, 456, 456, 456, 456, 273, 273, 479, 479, 479, 501, 800, 592, 592, 592, 592, 547, 501, 638, 592, 228, 456, 592, 501, 683, 592, 638, 547, 638, 592, 547, 501, 592, 547, 774, 547, 547, 501, 273, 228, 273, 479, 456, 228, 456, 501, 456, 501, 456, 273, 501, 501, 228, 228, 456, 228, 729, 501, 501, 501, 501, 319, 456, 273, 501, 456, 638, 456, 456, 410, 319, 230, 319, 479, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 273, 456, 456, 137, 456, 456, 456, 456, 195, 410, 456, 273, 273, 501, 501, 500, 456, 456, 456, 228, 500, 456, 287, 228, 410, 410, 456, 820, 820, 500, 501, 500, 273, 273, 273, 273, 273, 273, 273, 273, 500, 273, 273, 500, 273, 273, 273, 820, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 820, 500, 303, 500, 500, 500, 500, 501, 638, 820, 299, 500, 500, 500, 500, 500, 729, 500, 500, 500, 228, 500, 500, 228, 501, 774, 501, ) PyChart-1.39/pychart/afm/Times_BoldItalic.py0000644000175000017500000000272310354321374022420 0ustar santiagosantiago00000000000000# AFM font Times-BoldItalic (path: /usr/share/fonts/afms/adobe/ptmbi8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Times-BoldItalic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 250, 389, 555, 500, 500, 833, 778, 333, 333, 333, 500, 570, 250, 333, 250, 278, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 333, 333, 570, 570, 570, 500, 832, 667, 667, 667, 722, 667, 667, 722, 778, 389, 500, 667, 611, 889, 722, 722, 611, 722, 667, 556, 611, 722, 667, 889, 667, 611, 611, 333, 278, 333, 570, 500, 333, 500, 500, 444, 500, 444, 333, 500, 556, 278, 278, 500, 278, 778, 556, 500, 500, 500, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 389, 500, 500, 167, 500, 500, 500, 500, 278, 500, 500, 333, 333, 556, 556, 500, 500, 500, 500, 250, 500, 500, 350, 333, 500, 500, 500, 1000, 1000, 500, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 500, 333, 333, 500, 333, 333, 333, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 944, 500, 266, 500, 500, 500, 500, 611, 722, 944, 300, 500, 500, 500, 500, 500, 722, 500, 500, 500, 278, 500, 500, 278, 500, 722, 500, ) PyChart-1.39/pychart/afm/Utopia_Italic.py0000644000175000017500000000271610354321374022001 0ustar santiagosantiago00000000000000# AFM font Utopia-Italic (path: /usr/share/fonts/afms/adobe/putri8a.afm). # Derived from Ghostscript distribution. # Go to www.cs.wisc.edu/~ghost to get the Ghostcript source code. import dir dir.afm["Utopia-Italic"] = (500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 225, 240, 402, 530, 530, 826, 725, 216, 350, 350, 412, 570, 265, 392, 265, 270, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 265, 265, 570, 570, 570, 425, 794, 624, 632, 661, 763, 596, 571, 709, 775, 345, 352, 650, 565, 920, 763, 753, 614, 753, 640, 533, 606, 794, 637, 946, 632, 591, 622, 330, 390, 330, 570, 500, 216, 561, 559, 441, 587, 453, 315, 499, 607, 317, 309, 545, 306, 912, 618, 537, 590, 559, 402, 389, 341, 618, 510, 785, 516, 468, 468, 340, 270, 340, 570, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 240, 530, 530, 100, 530, 530, 530, 530, 216, 402, 462, 277, 277, 607, 603, 500, 500, 500, 490, 265, 500, 560, 500, 216, 402, 402, 462, 1000, 1200, 500, 425, 500, 400, 400, 400, 400, 400, 400, 402, 400, 500, 400, 400, 500, 400, 350, 400, 1000, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500, 880, 500, 425, 500, 500, 500, 500, 571, 753, 1020, 389, 500, 500, 500, 500, 500, 779, 500, 500, 500, 317, 500, 500, 318, 537, 806, 577, ) PyChart-1.39/pychart/color_doc.py0000644000175000017500000000006710354321374020450 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/log_coord.py0000644000175000017500000000275510354321345020460 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import coord import math class T(coord.T): def get_canvas_pos(self, size, val, min, max): if val <= 0: return 0 xminl = math.log(min) xmaxl = math.log(max) vl = math.log(val) return size * (vl-xminl) / float(xmaxl-xminl) def get_tics(self, min, max, interval): "Generate the list of places for drawing tick marks." v = [] if min <= 0: raise Exception, "Min value (%s) < 0 in a log coordinate." % min x = min while x <= max: v.append(x) x = x * interval return v def get_min_max(self, dmin, dmax, interval): interval = interval or 10 dmin = max(0, dmin) # we can't have a negative value with a log scale. v = 1.0 while v > dmin: v = v / interval dmin = v v = 1.0 while v < dmax: v = v * interval dmax = v return dmin, dmax, interval PyChart-1.39/pychart/axis_doc.py0000644000175000017500000000010310354321374020265 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc_x=" " doc_y=" " PyChart-1.39/pychart/object_set.py0000644000175000017500000000243110354321345020621 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # class T(object): def __init__(self, *objs): self.__objs = list(objs) def add(self, *objs): self.__objs.extend(objs) def add_objects(self, objs): self.__objs.extend(objs) def iterate(self): return Iterator(self) def list(self): return self.__objs def __getitem__(self, idx): return self.__objs[idx] def nth(self, idx): return self.__objs[idx] class Iterator(object): def __init__(self, set_): self.__set = set_ self.__idx = 0 def reset(self): self.__idx = 0 def next(self): val = self.__set.nth(self.__idx) self.__idx += 1 if self.__idx >= len(self.__set.list()): self.__idx = 0 return val PyChart-1.39/pychart/canvas.py0000644000175000017500000000765110352115032017754 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import basecanvas import pscanvas import pdfcanvas import svgcanvas import pngcanvas import x11canvas import theme import re invalid_coord = -999999 _oldexitfunc = None T = basecanvas.T def init(fname = None, format = None): """This is a "factory" procedure that creates a new canvas.T object. Both parameters, and , are optional. Parameter specifies either the output file name or a file object. Parameter , if specified, defines the file's format. Its value must be one of "ps", "pdf", "svg", "x11", or "png". When is omitted or is None, the output is sent to standard output. When is omitted, it is guessed from the 's suffix; failing that, "ps" is selected.""" fname = fname or theme.output_file format = format or theme.output_format if format == None: if not isinstance(fname, str): format = "ps" elif re.search("pdf$", fname): format = "pdf" elif re.search("png$", fname): format = "png" elif re.search("svg$", fname): format = "svg" else: format = "ps" if format == "ps": can = pscanvas.T(fname) elif format == "png": can = pngcanvas.T(fname) elif format == "x11": can = x11canvas.T(fname) elif format == "svg": can = svgcanvas.T(fname) elif format == "pdf-uncompressed": can = pdfcanvas.T(fname, False) else: can = pdfcanvas.T(fname, theme.compress_output) return can def default_canvas(): if len(basecanvas.active_canvases) > 0: return basecanvas.active_canvases[0] else: return init(None) def _exit(): global _oldexitfunc, _active_canvases for can in basecanvas.active_canvases[:]: can.close() if _oldexitfunc: foo = _oldexitfunc _oldexitfunc = None foo() # # The following procedures are there just for backward compatibility. # def line(style, x1, y1, x2, y2): default_canvas().line(style, x1, y1, x2, y2) def curve(style, points): default_canvas().curve(style, points) def clip(x1, y1, x2, y2): default_canvas().clip(x1, y1, x2, y2) def endclip(): default_canvas().endclip() def clip_polygon(points): default_canvas().clip_polygon(points) def clip_ellipsis(x, y, radius, ratio = 1.0): default_canvas().clip_ellipsis(x, y, radius, ratio) def ellipsis(line_style, pattern, x, y, radius, ratio = 1.0, start_angle=0, end_angle=360, shadow=None): default_canvas().ellipsis(line_style, pattern, x, y, radius, ratio, start_angle, end_angle, shadow) def rectangle(edge_style, pat, x1, y1, x2, y2, shadow = None): default_canvas().rectangle(edge_style, pat, x1, y1, x2, y2, shadow) def polygon(edge_style, pat, points, shadow = None): default_canvas().polygon(edge_style, pat, points, shadow = None) def close(): default_canvas().close() def round_rectangle(style, fill, x1, y1, x2, y2, radius, shadow=None): default_canvas().round_rectangle(style, fill, x1, y1, x2, y2, radius, shadow) def show(x, y, str): default_canvas().show(x, y, str) if not vars(sys).has_key("exitfunc"): sys.exitfunc = _exit elif sys.exitfunc != _exit: _oldexitfunc = sys.exitfunc sys.exitfunc = _exit #theme.add_reinitialization_hook(lambda: init(None)) PyChart-1.39/pychart/generate_docs.py0000644000175000017500000000713410354321416021306 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import doc_support import sys import re import os import area import arrow import axis import bar_plot import line_plot import pie_plot import color import error_bar import fill_style import font import text_box import line_style import legend import range_plot import tick_mark indent = 4 max_line_len = 64 def format_paragraph(fp, str): line_len = indent fp.write(" " * indent) for word in str.split(): if line_len >= max_line_len: fp.write("\n") fp.write(" " * indent) line_len = indent fp.write(word + " ") line_len += len(word) + 1 def format_string(fp, str): str = re.sub("<<([^>]+)>>", "See also pychart.\\1", str) str2 = "" in_example = 0 for l in str.split("\n"): if re.match("@example", l): in_example = 1 if re.match("@end example", l): in_example = 0 if in_example: str2 += l else: l = re.sub("^[ \t]*", "", l) str2 += l str2 += "\n" fname = os.tempnam() out_fp = open(fname, "w") out_fp.write(str2) out_fp.close() in_fp = os.popen("makeinfo --fill-column=64 --no-headers " + fname, "r") for l in in_fp.readlines(): fp.write(" " * indent) fp.write(l) in_fp.close() os.remove(fname) def generate_doc(c, name, suffix="", append = 0): if append: fp = open(name + "_doc.py", "a+") else: fp = open(name + "_doc.py", "w") fp.write("# automatically generated by generate_docs.py.\n") fp.write("doc" + suffix + "=\"\"\"Attributes supported by this class are:\n") for key in c.keys.keys(): val=c.keys[key] desc = "" defaultValDesc = None if len(val) > 3: desc = val[3] if len(val) > 4: defaultValDesc = val[4] fp.write(key + "(type:" + doc_support.stringify_type(val[0])) if defaultValDesc: fp.write(") default:" + defaultValDesc) else: fp.write(") default=" + str(doc_support.stringify_value(val[2])) + ".\n") format_string(fp, desc) fp.write("\"\"\"\n\n") fp.close() generate_doc(arrow.T, "arrow") generate_doc(area.T, "area") generate_doc(axis.X, "axis", "_x") generate_doc(axis.Y, "axis", "_y", 1) generate_doc(bar_plot.T, "bar_plot") generate_doc(line_plot.T, "line_plot") generate_doc(pie_plot.T, "pie_plot") generate_doc(color.T, "color") generate_doc(error_bar.error_bar1, "error_bar","_1") generate_doc(error_bar.error_bar2, "error_bar", "_2", 1) generate_doc(error_bar.error_bar3, "error_bar", "_3", 1) generate_doc(error_bar.error_bar4, "error_bar", "_4", 1) generate_doc(error_bar.error_bar5, "error_bar", "_5", 1) generate_doc(error_bar.error_bar6, "error_bar", "_6", 1) generate_doc(fill_style.T, "fill_style") generate_doc(text_box.T, "text_box") generate_doc(range_plot.T, "range_plot") generate_doc(legend.T, "legend") generate_doc(legend.Entry, "legend", "_entry", 1) generate_doc(line_style.T, "line_style") generate_doc(tick_mark.T, "tick_mark") PyChart-1.39/pychart/doc_support.py0000644000175000017500000000634310354321374021051 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import re import os.path from pychart import * from types import * from pychart.pychart_types import * oldstdout = sys.stdout if os.path.exists("/dev/null"): sys.stdout = open("/dev/null", "w") modules = {} values = [] sys.stdout = oldstdout g = globals() for mod in g.keys(): val = g[mod] if type(val) == ModuleType: dic = {} for name in val.__dict__.keys(): v = val.__dict__[name] if name[0] != '_': values.append((v, mod + "." + name)) if type(v) == type and issubclass(v, chart_object.T): dic[name] = v modules[mod] = dic def stringify_type(t): s = str(t) if t == AnyType: return "any" if t == ShadowType: return "(xoff,yoff,fill)" elif re.search("NumberType", s): return "number" elif re.search("UnitType", s): return 'length in points (\\xref{unit})' elif re.search("CoordType", s): return "(x,y) or None" elif re.search("CoordSystemType", s): return "['linear'|'log'|'category']" elif re.search("TextAlignType", s): return "['R'|'L'|'C'|None]" elif re.search("FormatType", s): return "printf format string" elif re.search("IntervalType", s): return "number or function" mo = re.match("", s) if mo: return mo.group(1) mo = re.match("", s) if mo: return mo.group(1) mo = re.match("", s) if mo: return mo.group(1) mo = re.match("pychart\\.(.*)", s) if mo: return mo.group(1) return s def stringify_value(val): t = type(val) if t == StringType: return '"' + val + '"' if t == bool: if val: return "True" else: return "False" if t in (IntType, LongType, FloatType): return str(val) if val == None: return "None" if type(val) == ListType: return map(stringify_value, val) for pair in values: if pair[0] == val: return pair[1] return str(val) def break_string(name): max_len = 10 if len(name) < max_len: return name name = re.sub("(\\d\\d)([^\\d])", "\\1-\n\\2", name) name = re.sub("black(.)", "black-\n\\1", name) elems = name.split("\n") while 1: broken = 0 for i in range(len(elems)): elem = elems[i] if len(elem) < max_len: continue broken = 1 elem1 = elem[0:len(elem)/2] elem2 = elem[len(elem)/2:] elems[i:i+1] = [elem1, elem2] break if not broken: break name = "\n".join(elems) return name PyChart-1.39/pychart/pychart_types.py0000644000175000017500000000337010354321374021403 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import pychart_util import types AnyType = 9998 def IntervalType(val): if type(val) in (types.IntType, types.LongType, types.FloatType, types.FunctionType): return None return "Expecting a number or a function" def CoordType(val): if type(val) not in (types.TupleType, types.ListType): return "Expecting a tuple or a list" if len(val) != 2: return "Coordinate must be a pair of numbers" for v in val: if v != None and NumberType(v): return "Expecting a pair of numbers (got %s)" % str(v) return None def NumberType(val): if type(val) in (types.IntType, types.LongType, types.FloatType): return None else: return "Expecting a number" def UnitType(val): if type(val) in (types.IntType, types.LongType, types.FloatType): return else: return "Expecting a unit" def ShadowType(val): if type(val) not in (types.TupleType, types.ListType): return "Expecting tuple or list." if len(val) != 3: return "Expecting (xoff, yoff, fill)." return None def FormatType(val): if type(val) in (types.StringType, types.FunctionType): return None return "Format must be a string or a function" PyChart-1.39/pychart/tick_mark_doc.py0000644000175000017500000000006710354321374021276 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/range_plot_doc.py0000644000175000017500000000006710354321374021464 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/chart_object.py0000644000175000017500000000616310352121432021126 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import pychart_types import types def set_defaults(cls, **dict): validAttrs = getattr(cls, "keys") for attr, val in dict.items(): if not validAttrs.has_key(attr): raise Exception, "%s: unknown attribute %s." % (cls, attr) tuple = list(validAttrs[attr]) # 0 : type # 1: defaultValue # 2: document # 3: defaultValue document (optional) tuple[1] = val validAttrs[attr] = tuple class T(object): def init(self, args): keys = self.keys for attr, tuple in keys.items(): defaultVal = tuple[1] if isinstance(defaultVal, types.FunctionType): # if the value is procedure, use the result of the proc call # as the default value defaultVal = apply(defaultVal, ()) setattr(self, attr, defaultVal) for key, val in args.items(): self.__setattr__(key, val) def __check_type(self, item, value): if item.startswith("_"): return if not self.keys.has_key(item): raise Exception, "%s: unknown attribute '%s'" % (self, item) typeval, default_value, docstring = self.keys[item][0:3] if value == None or typeval == pychart_types.AnyType: pass elif typeval == bool: # In 2.3, bool is a full-fledged type, whereas # in 2.2, it's just a function that returns an integer. # To mask this difference, we handle the bool type specially. if value not in (True, False): raise TypeError, "%s: Expecting bool, but got %s" % (self, value) elif typeval == str: if not isinstance(value, str) and not isinstance(value, unicode): raise TypeError, "%s: Expecting a string, but got %s" % (self, value) elif isinstance(typeval, types.FunctionType): # user-defined check procedure error = apply(typeval, (value,)) if error != None: raise TypeError, "%s: %s for attribute '%s', but got '%s'" % (self, error, item, value) elif isinstance(value, typeval): pass else: raise TypeError, "%s: Expecting type %s, but got %s (attr=%s, %s)" % (self, typeval, value, item, self.keys[item]) def __init__(self, **args): self.init(args) def __setattr__(self, item, value): self.__check_type(item, value) self.__dict__[item] = value def check_integrity(self): for attr, value in self.__dict__.items(): self.__check_type(attr, value) return True PyChart-1.39/pychart/axis_x_doc.py0000644000175000017500000000524010354321345020621 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # doc="""Attributes supported by this class are: tic_label_offset(type:(x,y)): The location where the tick labels is drawn. Relative to the tip of the tick mark. default value=(0, 0). format(type:printf format string): The format string for tick labels. It can be a `printf' style format string, or a single-parameter function that returns a string. See also font. default value=%s. minor_tic_len(type:number): The length of minor tick marks. default value=3. label_offset(type:(x,y) or None): The location where the axis label is drawn. Relative to the left-bottom corner of the axis. default value=(None, None). grid_interval(type:Number or function): When the value is a number, it specifies the interval with which grid lines are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where grid lines are drawn. default value=None. label(type:str): The description of the axis. See also font. default value=axis label. grid_style(type:line_style.T): The style of grid lines. default value=None. tic_interval(type:Number or function): When the value is a number, it specifies the interval with which tick marks are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where tick marks are drawn. default value=None. line_style(type:line_style.T): The style of tick lines. default value=default. tic_len(type:number): The length of tick lines default value=6. minor_tic_interval(type:Number or function): When the value is a number, it specifies the interval with which minor tick marks are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where minor tick marks are drawn. default value=None. first_tic_value(type:number): The location of the first tick mark. Defaults to the x_range[0] (or y_range[0]) of the area. default value=None. """PyChart-1.39/pychart/typechecker.py0000644000175000017500000000175610354321345021017 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import types class IntervalTypeClass: def typeCheck(self, val): if type(val) in (types.IntType, types.LongType, types.FloatType, types.FunctionType): return None return "Expecting a number or a function, but received '%s'", val def typeDescription(self): return "A number or function" def varDescription(self, name): return "A number or function" IntervalType = IntervalTypeClass() PyChart-1.39/pychart/line_style_doc.py0000644000175000017500000000006710354321374021501 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/error_bar_doc.py0000644000175000017500000000015310354321374021303 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc_1=" " doc_2=" " doc_3=" " doc_4=" " doc_5=" " doc_6=" " PyChart-1.39/pychart/pychart_util.py0000644000175000017500000001045710354321345021216 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import math import types import traceback from types import * def inch_to_point(inch): return inch * 72.0 def point_to_inch(pt): return float(pt) / 72.0 def rotate(x, y, degree): """Rotate a coordinate around point (0,0). - x and y specify the coordinate. - degree is a number from 0 to 360. Returns a new coordinate. """ radian = float(degree) * 2 * math.pi / 360.0 newx = math.cos(radian) * x - math.sin(radian) * y newy = math.sin(radian) * x + math.cos(radian) * y return (newx, newy) debug_level = 1 def warn(*strs): for s in strs: sys.stderr.write(str(s)) sys.stderr.write(" ") sys.stderr.write("\n") def info(*strs): if debug_level < 100: return for s in strs: sys.stderr.write(str(s)) sys.stderr.write("\n") def get_sample_val(l, col): if len(l) <= col: return None return l[col] def get_data_list(data, col): # data = [ elem[col] for elem in data if elem[col] != None ] r = [] for item in data: val = get_sample_val(item, col) if val != None: r.append(val) return r def get_data_range(data, col): data = get_data_list(data, col) for item in data: if type(item) not in (types.IntType, types.LongType, types.FloatType): raise TypeError, "Non-number passed to data: %s" % (data) return (min(data), max(data)) def round_down(val, bound): return int(val/float(bound)) * bound def round_up(val, bound): return (int((val-1)/float(bound))+1) * bound # # Attribute type checking stuff # def new_list(): return [] def union_dict(dict1, dict2): dict = dict1.copy() dict.update(dict2) return dict def TextVAlignType(val): if val in ('T', 'B', 'M', None): return None return "Text vertical alignment must be one of T(op), B(ottom), or M(iddle).\n" def TextAlignType(val): if val in ('C', 'R', 'L', None): return None return "Text horizontal alignment must be one of C(enter), R(ight), or L(eft)." def apply_format(format, val, defaultidx): if format == None: return None elif type(format) == StringType: return format % val[defaultidx] else: return apply(format, val) data_desc = "Specifies the data points. <>" label_desc = "The label to be displayed in the legend. <>, <>" xcol_desc = """The column, within attribute "data", from which the X values of sample points are extracted. <>""" ycol_desc = """The column, within attribute "data", from which the Y values of sample points are extracted. <>""" tick_mark_desc = "Tick marks to be displayed at each sample point. <>" line_desc="The style of the line. " def interval_desc(w): return "When the value is a number, it specifies the interval at which %s are drawn. Otherwise, the value must be a function that takes two arguments, min and max X (or Y) values. It must return a list of numbers that specify the X or Y points at which %s are drawn." % (w,w) shadow_desc = """The value is either None or a tuple. When non-None, a drop-shadow is drawn beneath the object. X-off, and y-off specifies the offset of the shadow relative to the object, and fill specifies the style of the shadow (@pxref{module-fill-style}).""" string_desc = """The appearance of the string produced here can be controlled using escape sequences. <>""" # # class symbol_lookup_table: def __init__(self, dict, objs): self.names = {} for name, val in dict.items(): for obj in objs.list(): if val == obj: self.names[val] = name break def lookup(self, obj): if self.names.has_key(obj): return self.names[obj] return None PyChart-1.39/pychart/fill_style_doc.py0000644000175000017500000000006710354321374021500 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/line_style.py0000644000175000017500000001320210354321345020645 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import color import pychart_util import chart_object import object_set import theme import line_style_doc from pychart_types import * from types import * _keys = { "width" : (UnitType, theme.default_line_width, "Width of the line, in points."), "color": (color.T, color.default, "The color of the line."), "dash" : (TupleType, None, """The value of None will draw a solid line. Otherwise, this attribute specifies the style of dashed lines. The 2N'th value specifies the length of the line (in points), and 2N+1'th value specifies the length of the blank. For example, the dash style of (3,2,4,1) draws a dashed line that looks like @samp{---__----_---__----_...}. """), "cap_style": (IntType, 0, """Defines the style of the tip of the line segment. 0: butt cap (square cutoff, with no projection beyond), 1: round cap (arc), 2: projecting square cap (square cutoff, but the line extends half the line width). See also Postscript/PDF reference manual."""), "join_style": (IntType, 0, """Join style. 0: Miter join (sharp, pointed corners), 1: round join (rounded corners), 2: bevel join (flattened corners). See also Postscript/PDF reference manual.""") } class T(chart_object.T): __doc__ = line_style_doc.doc keys = _keys ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def __str__(self): s = name_table().lookup(self) if s: return s return "" \ % (self.width, self.color, self.dash, self.cap_style, self.join_style) default = T(color=color.default) dash1 = 1.5,1.5 # - - - - dash2 = 5,2,5,2 # -- -- -- -- dash3 = 1,1 black = T(color=color.black) black_dash1 = T(color=color.black, dash=dash1) black_dash2 = T(color=color.black, dash=dash2) black_dash3 = T(color=color.black, dash=dash3) gray70 = T(color=color.gray70) gray70_dash1 = T(color=color.gray70, dash=dash1) gray70_dash2 = T(color=color.gray70, dash=dash2) gray70_dash3 = T(color=color.gray70, dash=dash3) gray10 = T(color=color.gray10) gray10_dash1 = T(color=color.gray10, dash=dash1) gray10_dash2 = T(color=color.gray10, dash=dash2) gray10_dash3 = T(color=color.gray10, dash=dash3) gray50 = T(color=color.gray50) gray50_dash1 = T(color=color.gray50, dash=dash1) gray50_dash2 = T(color=color.gray50, dash=dash2) gray50_dash3 = T(color=color.gray50, dash=dash3) gray60 = T(color=color.gray60) gray60_dash1 = T(color=color.gray60, dash=dash1) gray60_dash2 = T(color=color.gray60, dash=dash2) gray60_dash3 = T(color=color.gray60, dash=dash3) gray90 = T(color=color.gray90) gray90_dash1 = T(color=color.gray90, dash=dash1) gray90_dash2 = T(color=color.gray90, dash=dash2) gray90_dash3 = T(color=color.gray90, dash=dash3) gray30 = T(color=color.gray30) gray30_dash1 = T(color=color.gray30, dash=dash1) gray30_dash2 = T(color=color.gray30, dash=dash2) gray30_dash3 = T(color=color.gray30, dash=dash3) white = T(color=color.white) default = black red = T(color=color.red) darkblue = T(color=color.darkblue) darkseagreen = T(color=color.darkseagreen) darkkhaki = T(color = color.darkkhaki) blue = T(color=color.blue) green = T(color=color.green) red_dash1 = T(color=color.red, dash=dash1) darkblue_dash1 = T(color=color.darkblue, dash=dash1) darkseagreen_dash1 = T(color=color.darkseagreen, dash=dash1) darkkhaki_dash1 = T(color=color.darkkhaki, dash=dash1) red_dash2 = T(color=color.red, dash=dash2) darkblue_dash2 = T(color=color.darkblue, dash=dash2) darkseagreen_dash2 = T(color=color.darkseagreen, dash=dash2) darkkhaki_dash2 = T(color=color.darkkhaki, dash=dash2) standards = None _name_table = None def init(): global standards, _name_table standards = object_set.T() if theme.use_color: standards.add(black, red, darkblue, gray70, darkseagreen, darkkhaki, gray30, black_dash1, red_dash1, darkblue_dash1, gray70_dash1, darkseagreen_dash1, darkkhaki_dash1, gray30_dash1, black_dash2, red_dash2, darkblue_dash2, gray70_dash2, darkseagreen_dash2, darkkhaki_dash2, gray30_dash2) else: standards.add(black, black_dash1, black_dash2, gray70, gray70_dash1, gray70_dash2, gray10, gray10_dash1, gray10_dash2, gray50, gray50_dash1, gray50_dash2, gray90, gray90_dash1, gray90_dash2, gray30, gray30_dash1, gray30_dash2, black_dash3, gray70_dash3, gray10_dash3, gray50_dash3, gray90_dash3) for style in standards.list(): style.width = theme.default_line_width _name_table = None def name_table(): global _name_table if not _name_table: _name_table = pychart_util.symbol_lookup_table(globals(), standards) return _name_table init() theme.add_reinitialization_hook(init) PyChart-1.39/pychart/pie_plot_doc.py0000644000175000017500000000006710354321374021145 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/text_box.py0000644000175000017500000001412010354321345020332 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import canvas import line_style import pychart_util import fill_style import font import chart_object import color import arrow import text_box_doc from pychart_types import * from types import * class T(chart_object.T): __doc__ = text_box_doc.doc keys = {"text": (StringType, "???", "Text body. <>"), "loc": (TupleType, (0,0), "The location of the text box."), "line_style": (line_style.T, line_style.default, """The line style of the surrounding frame."""), "fill_style": (fill_style.T, fill_style.white, "Specifies the fill style of the text box."), "top_fudge": (UnitType, 0, "The amount of space (in points) above the first line"), "bottom_fudge": (UnitType, 5, "The amount of space below the last line"), "left_fudge": (UnitType, 5, "The amount of space left of the box"), "right_fudge": (UnitType, 5, "The amount of space right of the box"), "_arrows": (ListType, pychart_util.new_list, "The list of arrows. Not to be touched by the user directly"), "radius": (UnitType, 0, """Radius of the four corners of the rectangle. If the value is zero, a sharp-cornered rectangle is drawn."""), "shadow": (ShadowType, None, pychart_util.shadow_desc) } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def get_dimension(self): x = self.loc[0] - self.left_fudge y = self.loc[1] - self.bottom_fudge width = font.text_width(self.text) + self.right_fudge + self.left_fudge height = (font.text_height(self.text))[0] + self.top_fudge + self.bottom_fudge return (x, y, width, height) def choose_end_point(self, tipx, tipy): (x, y, width, height) = self.get_dimension() minDist = -1 minPoint = None vertices = [(x, y), (x+width, y), (x+width, y+height), (x, y+height)] if tipx >= x and tipx < x+width: vertices.append((tipx, y)) vertices.append((tipx, y+height)) if tipy >= y and tipy < y+height: vertices.append((x, tipy)) vertices.append((x+width, tipy)) for startPoint in vertices: dist = ((startPoint[0] - tipx) **2 + (startPoint[1] - tipy) **2) if not minPoint or dist < minDist: minPoint = startPoint minDist = dist return minPoint def add_arrow(self, tipLoc, tail=None, arrow = arrow.default): """This method adds a straight arrow that points to @var{TIPLOC}, which is a tuple of integers. @var{TAIL} specifies the starting point of the arrow. It is either None or a string consisting of the following letters: 'l', 'c', 'r', 't', 'm,', and 'b'. Letters 'l', 'c', or 'r' means to start the arrow from the left, center, or right of the text box, respectively. Letters 't', 'm', or 'b' means to start the arrow from the top, middle or bottom of the text box. For example, when @samp{tail = 'tc'} then arrow is drawn from top-center point of the text box. ARROW specifies the style of the arrow. <>. """ self._arrows.append((tipLoc, tail, arrow)) def draw(self, can = None): if can == None: can = canvas.default_canvas() x = self.loc[0] y = self.loc[1] text_width = font.text_width(self.text) text_height = font.text_height(self.text)[0] (halign, valign, angle) = font.get_align(self.text) if self.line_style or self.fill_style: width = text_width+self.left_fudge+self.right_fudge height = text_height+self.bottom_fudge+self.top_fudge can.round_rectangle(self.line_style, self.fill_style, x-self.left_fudge, y-self.bottom_fudge, x-self.left_fudge+width, y-self.bottom_fudge+height, self.radius, self.shadow) if halign == 'L': can.show(x, y, self.text) elif halign == 'C': can.show(x+text_width/2.0, y, self.text) elif halign == 'R': can.show(x+text_width, y, self.text) else: raise Exception, "Unsupported alignment (" + halign + ")" # draw arrows for t in self._arrows: (tipLoc, tail, arrow) = t if tail: (x, y, width, height) = self.get_dimension() origin = [x, y] for ch in tail: if ch == 'l': origin[0] = x elif ch == 'c': origin[0] = x+width/2.0 elif ch == 'r': origin[0] = x+width elif ch == 'b': origin[1] = y elif ch == 'm': origin[1] = y+height/2.0 elif ch == 't': origin[1] = y+height else: raise ValueError, tail + ": unknown tail location spec." else: origin = self.choose_end_point(tipLoc[0], tipLoc[1]) arrow.draw((origin, tipLoc), can) PyChart-1.39/pychart/pngcanvas.py0000644000175000017500000000344210354321345020463 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import os import gs_frontend import theme class T(gs_frontend.T): def close(self): gs_frontend.T.close(self) if self.__output_lines == []: return if theme.use_color: gs_args = "-sDEVICE=png256 -dTextAlphaBits=4 -q -dNOPAUSE" #PDS else: gs_args = "-sDEVICE=pnggray -dTextAlphaBits=4 -q -dNOPAUSE" #PDS temp_fname = None # the temporary file desc. out_fd = None # the final destination. if self.__out_fname and isinstance(self.__out_fname, str): gs_args += " -sOutputFile=%s" % self.__out_fname else: if not self.__out_fname: out_fd = sys.stdout else: if not hasattr(self.__out_fname, "write"): raise Exception, "Expecting either a filename or a file-like object, but got %s" % self.__out_fname out_fd = self.__out_fname import tempfile temp_fname = tempfile.mktemp() gs_args += " -sOutputFile=%s" % temp_fname self.start_gs(gs_args) self.close_gs() if temp_fname: temp_fd = file(temp_fname, 'rb') out_fd.write(temp_fd.read()) temp_fd.close() PyChart-1.39/pychart/pie_plot.py0000644000175000017500000001402510354321374020317 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import text_box import fill_style import line_style import pychart_util import chart_object import arrow import legend import font import pie_plot_doc import theme from pychart_types import * from types import * class T(chart_object.T): __doc__ = pie_plot_doc.doc keys = { "start_angle" : (NumberType, 90, """The angle at which the first item is drawn."""), "center" : (CoordType, None, "The location of the center of the pie."), "radius" : (UnitType, None, "The radius of the pie."), "line_style" : (line_style.T, line_style.default, "The style of the outer edge of each pie slice."), "fill_styles" : (ListType, fill_style.standards.list(), """The fill style of each item. The length of the list should be equal to the length of the data. """), "arc_offsets" : (ListType, None, """You can draw each pie "slice" shifted off-center. This attribute, if non-None, must be a number sequence whose length is equal to the number of pie slices. The Nth value in arc_offsets specify the amount of offset (from the center of the circle) for the Nth slice. The value of None will draw all the slices anchored at the center. """ ), "data" : (AnyType, None, pychart_util.data_desc), "label_format" : (FormatType, "%s", "Format string of the label"), "label_col" : (IntType, 0, """The column, within "data", from which the labels of items are retrieved."""), "data_col": (IntType, 1, """ The column, within "data", from which the data values are retrieved."""), "label_offset": (UnitType, None, "The distance from the center of each label."), "arrow_style": (arrow.T, None, """The style of arrow that connects a label to the corresponding "pie"."""), "label_line_style": (line_style.T, None, "The style of the frame surrounding each label."), "label_fill_style": (fill_style.T, fill_style.default, "The fill style of the frame surrounding each label."), "shadow": (ShadowType, None, pychart_util.shadow_desc) } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def _total(self): v = 0 for val in self.data: v += val[self.data_col] return v def check_integrity(self): chart_object.T.check_integrity(self) def get_data_range(self, which): return (0, 1) def get_legend_entry(self): legends = [] i = 0 for val in self.data: fill = self.fill_styles[i] i = (i + 1) % len(self.fill_styles) legends.append(legend.Entry(line_style=self.line_style, fill_style=fill, label=val[self.label_col])) return legends def draw(self, ar, can): center = self.center if not center: center = (ar.loc[0] + ar.size[0]/2.0, ar.loc[1] + ar.size[1]/2.0) radius = self.radius if not radius: radius = min(ar.size[0]/2.0, ar.size[1]/2.0) * 0.5 label_offset = radius + (self.label_offset or radius * 0.1) total = self._total() i = 0 cur_angle = self.start_angle for val in self.data: fill = self.fill_styles[i] degree = 360 * float(val[self.data_col]) / float(total) off = (0, 0) if len(self.arc_offsets) > i: off = pychart_util.rotate(self.arc_offsets[i], 0, cur_angle - degree/2.0) x_center = center[0]+ off[0] y_center = center[1]+ off[1] can.ellipsis(self.line_style, fill, x_center, y_center, radius, 1, cur_angle - degree, cur_angle, self.shadow) label = pychart_util.apply_format(self.label_format, val, self.label_col) if label != None: (x_label, y_label) = pychart_util.rotate(label_offset, 0, cur_angle - degree/2.0) (x_arrowtip, y_arrowtip) = pychart_util.rotate(radius, 0, cur_angle - degree/2.0) # Labels on left side of pie need # their text to avoid obscuring the pie if x_label < 0: x_label = x_label - font.text_width(label) t = text_box.T(loc = (x_label + x_center, y_label + y_center), text = label, line_style = self.label_line_style, fill_style = self.label_fill_style) if self.arrow_style: t.add_arrow((x_arrowtip + x_center, y_arrowtip + y_center), None, self.arrow_style) t.draw(can) cur_angle = (cur_angle - degree) % 360 i = (i + 1) % len(self.fill_styles) def init(): old_val = T.keys["fill_styles"] T.keys["fill_styles"] = (old_val[0], fill_style.standards.list(), old_val[2]) theme.add_reinitialization_hook(init) PyChart-1.39/pychart/legend.py0000644000175000017500000001523210354321345017741 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import tick_mark import font import line_style import color import fill_style import chart_object import pychart_util import types import legend_doc import theme from pychart_types import * from types import * class Entry(chart_object.T): keys = {"line_len" : (UnitType, None, "Length of the sample line for line plots. If omitted, it is set to be theme.default_font_size"), "rect_size" : (UnitType, None, "Size of the sample 'blob' for bar range charts. If omitted, it is set to be 70% of theme.default_size"), "tick_mark": (tick_mark.T, None, ""), "line_style": (line_style.T, None, ""), "fill_style": (fill_style.T, None, ""), "label": (StringType, "???", ""), } __doc__ = legend_doc.doc_entry ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def label_width(self): return font.text_width(" " + self.label) def get_line_len(self): return self.line_len or theme.default_font_size def get_rect_size(self): return self.rect_size or theme.default_font_size * 7 / 10.0 def sample_width(self): w = 0 if self.fill_style != None: w += self.get_line_len() elif self.line_style != None: w += self.get_line_len() elif self.tick_mark != None: w += self.tick_mark.size return w def height(self): h = font.text_height(self.label)[0] return h def draw(self, ar, can, x_tick, x_label, y): """Draw a legend entry. X_TICK and X_LABEL are the X location \ (in points) of where the sample and label are drawn.""" rect_size = self.get_rect_size() line_len = self.get_line_len() nr_lines = len(self.label.split("\n")) text_height = font.text_height(self.label)[0] line_height = text_height / float(nr_lines) y_center = y + text_height - line_height/1.5 if self.fill_style != None: can.rectangle(self.line_style, self.fill_style, x_tick, y_center - rect_size/2.0, x_tick + rect_size, y_center + rect_size/2.0) elif self.line_style != None: can.line(self.line_style, x_tick, y_center, x_tick + line_len, y_center) if self.tick_mark != None: self.tick_mark.draw(can, x_tick + line_len/2.0, y_center) elif self.tick_mark != None: self.tick_mark.draw(can, x_tick, y_center) can.show(x_label, y, self.label) __doc__ = """Legend is a rectangular box drawn in a chart to describe the meanings of plots. The contents of a legend box is extracted from plots' "label", "line-style", and "tick-mark" attributes. This module exports a single class, legend.T. Legend.T is a part of an area.T object, and is drawn automatically when area.draw() method is called. """ class T(chart_object.T): __doc__ = legend_doc.doc keys = { "inter_row_sep": (UnitType, 0, "Space between each row in the legend."), "inter_col_sep": (UnitType, 0, "Space between each column in the legend."), "frame_line_style": (line_style.T, line_style.default, ""), "frame_fill_style": (fill_style.T, fill_style.white, ""), "top_fudge": (UnitType, 0, "Amount of space above the first line."), "bottom_fudge": (UnitType, 3, "Amount of space below the last line."), "left_fudge": (UnitType, 5, "Amount of space left of the legend."), "right_fudge": (UnitType, 5, "Amount of space right of the legend."), "loc": (CoordType, None, """Bottom-left corner of the legend. The default location of a legend is the bottom-right end of the chart."""), "shadow": (ShadowType, None, pychart_util.shadow_desc), "nr_rows": (IntType, 9999, "Number of rows in the legend. If the number of plots in a chart is larger than nr_rows, multiple columns are created in the legend."), } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, ar, entries, can): if not self.loc: x = ar.loc[0] + ar.size[0] * 1.1 y = ar.loc[1] else: x = self.loc[0] y = self.loc[1] nr_rows = min(self.nr_rows, len(entries)) nr_cols = (len(entries)-1) / nr_rows + 1 ymin = y max_label_width = [0] * nr_cols max_sample_width = [0] * nr_cols heights = [0] * nr_rows for i in range(len(entries)): l = entries[i] (col, row) = divmod(i, nr_rows) max_label_width[col] = max(l.label_width(), max_label_width[col]) max_sample_width[col] = max(l.sample_width(), max_sample_width[col]) heights[row] = max(l.height(), heights[row]) for h in heights: y += h y += self.inter_row_sep * (nr_rows - 1) ymax = y tot_width = self.inter_col_sep * (nr_cols -1) for w in max_label_width: tot_width += w for w in max_sample_width: tot_width += w can.rectangle(self.frame_line_style, self.frame_fill_style, x - self.left_fudge, ymin - self.bottom_fudge, x + tot_width + self.right_fudge, ymax + self.top_fudge, self.shadow) for col in range(nr_cols): this_y = y this_x = x for row in range(nr_rows): idx = col * nr_rows + row if idx >= len(entries): continue this_y -= heights[row] l = entries[idx] if row != 0: this_y -= self.inter_row_sep l.draw(ar, can, this_x, this_x + max_sample_width[col], this_y) x += max_label_width[col] + max_sample_width[col] + self.inter_col_sep PyChart-1.39/pychart/rose_plot.py0000644000175000017500000001526710354321374020523 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import canvas import fill_style import line_style import pychart_util import chart_object import legend import font import color from pychart_types import * class T(chart_object.T): """Plots sector diagram which can be superimposed on one another. Sector diagrams are also known as wind roses""" keys = { "start_angle" : (NumberType, 90, ""), # top of chart (north) "center" : (CoordType, None, ""), "base_radius" : (NumberType, None, ""), "line_style" : (line_style.T, line_style.T(color=color.black, width=0.3), ""), "fill_styles" : (list, fill_style.standards.list()[:], """The fill style of each item. The length of the list should be equal to the length of the data. """), "sector_centred":(int, 1, """Bool indicating whether the sectors should be centred on each sector_width(e.g. on 0)"""), "dir_offset": (UnitType, None, """The distance between the directions and the outermost circle. Defaults fine for most cases"""), "data" : (AnyType, None, pychart_util.data_desc), "label_col" : (int, 0, """The column, within "data", from which the labels of items are retrieved."""), "data_col": (int, 1, """ The column, within "data", from which the data values are retrieved."""), "dir_line_style": (line_style.T, None, ""), "dir_fill_style": (fill_style.T, fill_style.default, ""), "shadow": (ShadowType, None, pychart_util.shadow_desc), "sector_width": (int, None, ""), # automatically generated } def __init__(self, colour=True, **args): chart_object.T.init(self, args) if colour: # the theme.color flag does not seem to affect the fill_style.standards, #besides, I want the first two colors to resemble those of gnuplot's postscript terminal self.fill_styles = [fill_style.Plain(bgcolor=color.red), fill_style.Plain(bgcolor=color.green), fill_style.Plain(bgcolor=color.blue), fill_style.Plain(bgcolor=color.magenta)] def check_integrity(self): nSectors = len(self.data[0][self.data_col]) if (360%nSectors != 0): raise Exception('Length of dataset ' + str(nSectors) + ' not a divisor of 360 degrees!') for dataset in self.data: length = len(dataset[self.data_col]) if length != nSectors: raise Exception('Lengths of datasets given is different!') for val in dataset[self.data_col]: if (val < 0) | (val > 1): raise Exception('Data value ' + str(val) + ' not between 0 and 1!') self.sector_width = 360/nSectors chart_object.T.check_integrity(self) def get_data_range(self, which): return (0, 1) def get_legend_entry(self): legends = [] i = 0 for dataset in self.data: fill = self.fill_styles[i] i = (i + 1) % len(self.fill_styles) legends.append(legend.Entry(line_style=self.line_style, fill_style=fill, label=dataset[self.label_col])) return legends def draw(self, ar, can): center = self.center if not center: center = (ar.loc[0] + ar.size[0]/2.0, ar.loc[1] + ar.size[1]/2.0) base_radius = self.base_radius # the maximum radius of a wedge if not base_radius: base_radius = min(ar.size[0]/2.0, ar.size[1]/2.0) #* 0.8 sector_decrement = 1./(len(self.data)*2) * self.sector_width # each following sector diagram will have its sector width decremented by half this amount (in degrees) i = 0 for dataset in self.data: cur_angle = self.start_angle if self.sector_centred: cur_angle -= self.sector_width/2. fill = self.fill_styles[i] x_center = center[0] y_center = center[1] if not i: # draw directions around sector diagram once off dir_offset = base_radius + (self.dir_offset or base_radius * 0.04) directions = ['N', 'E', 'S', 'W'] angle = self.start_angle can.ellipsis(line_style.T(color=color.black, width=0.3, dash=line_style.dash1), None, x_center, y_center, base_radius, 1, 0, 360) # for d in directions: x_label, y_label = pychart_util.rotate(dir_offset, 0, angle) # coords for bottom left corner of box tw = font.text_width(d) half = 1/3. # normal arithmetic does not seem to apply to these text_box objects... if (angle == 0): # east y_label -= font.text_height(d)[0]*half # move down half elif (angle == -180): # west y_label -= font.text_height(d)[0]*half # move down half x_label -= font.text_width(d) # move left full elif (angle == 90): # north x_label -= font.text_height(d)[0]*half # move left half elif (angle == -90): # south y_label -= font.text_height(d)[0]*.8 # move down (couldn't figure out how to set this dynamically so I fudged...) x_label -= font.text_height(d)[0]*half # move left half canvas.show(x_label + x_center, y_label + y_center, d) angle -= 360/len(directions) for val in dataset[self.data_col]: # now draw the sectors radius = base_radius*val # scale the radius start = cur_angle-self.sector_width+i*sector_decrement stop = cur_angle-i*sector_decrement # these may seem confusing, but remember that we need to go counterclockwise can.ellipsis(self.line_style, fill, x_center, y_center, radius, 1, start, stop, self.shadow) cur_angle = (cur_angle - self.sector_width) % 360 # we want to go in anticlockwise direction (North, West, South, etc. as in meteorology) i = (i + 1) % len(self.fill_styles) PyChart-1.39/pychart/category_coord.py0000644000175000017500000000325410354321345021507 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import coord import canvas class T(coord.T): def __init__(self, data, col): """This attribute is meaningful only when x_coord_system == 'category'. This attribute selects the column of 'x_category_data' from which X values are computed. Meaningful only when x_coord_system == 'category'. This attribute specifies the data-set from which the X values are extracted. See also x_category_col.""" self.data = data self.col = col def get_canvas_pos(self, size, val, min, max): i = 0.5 for v in self.data: if v[self.col] == val: return size * i / float(len(self.data)) i += 1 # the drawing area is clipped. So negative offset will make this plot # invisible. return canvas.invalid_coord; def get_tics(self, min, max, interval): tics = [] if interval == None: interval = 1 for i in range(0, len(self.data), interval): tics.append(self.data[i][self.col]) return tics #return map(lambda pair, self = self: pair[self.col], self.data) PyChart-1.39/pychart/svgcanvas.py0000644000175000017500000004741510352124162020502 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys,string,re,math from xml.dom.minidom import Document,Comment import theme import basecanvas import version from scaling import * # Note we flip all y-coords and negate all angles because SVG's coord # system is inverted wrt postscript/PDF - note it's not enough to # scale(1,-1) since that turns text into mirror writing with wrong origin _comment_p = 0 # whether comment() writes output def _svgcolor(color): """ Convert a PyChart color object to an SVG rgb() value. See color.py. """ return 'rgb(%d,%d,%d)' % tuple(map(lambda x:int(255*x), [color.r,color.g,color.b])) def _parse_style_str(s): """ Take an SVG 'style' attribute string like 'stroke:none;fill:black' and parse it into a dictionary like {'stroke' : 'none', 'fill' : 'black'}. """ styledict = {} if s : # parses L -> R so later keys overwrite earlier ones for keyval in s.split(';'): l = keyval.strip().split(':') if l and len(l) == 2: styledict[l[0].strip()] = l[1].strip() return styledict def _make_style_str(styledict): """ Make an SVG style string from the dictionary. See also _parse_style_str also. """ s = '' for key in styledict.keys(): s += "%s:%s;"%(key, styledict[key]) return s def _protect_current_children(elt): # If elt is a group, check to see whether there are any non-comment # children, and if so, create a new group to hold attributes # to avoid affecting previous children. Return either the current # elt or the newly generated group. if (elt.nodeName == 'g') : for kid in elt.childNodes : if kid.nodeType != Comment.nodeType: g = elt.ownerDocument.createElement('g') g.setAttribute('auto','') if _comment_p: g.appendChild(g.ownerDocument.createComment ('auto-generated group')) elt.appendChild(g) elt = g break return elt class T(basecanvas.T): def __init__(self, fname): basecanvas.T.__init__(self) self.__out_fname = fname self.__xmin, self.__xmax, self.__ymin, self.__ymax = 0,0,0,0 self.__doc = Document() self.__doc.appendChild(self.__doc.createComment ('Created by PyChart ' + version.version + ' ' + version.copyright)) self.__svg = self.__doc.createElement('svg') # the svg doc self.__doc.appendChild(self.__svg) self.__defs = self.__doc.createElement('defs') # for clip paths self.__svg.appendChild(self.__defs) self.__cur_element = self.__svg self.gsave() # create top-level group for dflt styles self.__update_style(font_family = theme.default_font_family, font_size = theme.default_font_size, font_style = 'normal', font_weight = 'normal', font_stretch = 'normal', fill = 'none', stroke = 'rgb(0,0,0)', #SVG dflt none, PS dflt blk stroke_width = theme.default_line_width, stroke_linejoin = 'miter', stroke_linecap = 'butt', stroke_dasharray = 'none') def __update_style(self, **addstyledict): elt = _protect_current_children(self.__cur_element) # fetch the current styles for this node my_style_dict = _parse_style_str(elt.getAttribute('style')) # concat all ancestor style strings to get default styles for this node parent, s = elt.parentNode, '' while parent.nodeType != Document.nodeType : # prepend parent str so later keys will override earlier ones s = parent.getAttribute('style') + s parent = parent.parentNode default_style_dict = _parse_style_str(s) # Do some pre-processing on the caller-supplied add'l styles # Convert '_' to '-' so caller can specify style tags as python # variable names, eg. stroke_width => stroke-width. # Also convert all RHS values to strs for key in addstyledict.keys(): k = re.sub('_','-',key) addstyledict[k] = str(addstyledict[key]) # all vals => strs if (k != key) : del addstyledict[key] for k in addstyledict.keys() : if (my_style_dict.has_key(k) or # need to overwrite it (not default_style_dict.has_key(k)) or # need to set it default_style_dict[k] != addstyledict[k]) : # need to override it my_style_dict[k] = addstyledict[k] s = _make_style_str(my_style_dict) if s : elt.setAttribute('style',s) self.__cur_element = elt #################################################################### # methods below define the pychart backend device API # First are a set of methods to start, construct and finalize a path def newpath(self): # Start a new path if (self.__cur_element.nodeName != 'g') : raise OverflowError, "No containing group for newpath" # Just insert a new 'path' element into the document p = self.__doc.createElement('path') self.__cur_element.appendChild(p) self.__cur_element = p # This set of methods add data to an existing path element, # simply add to the 'd' (data) attribute of the path elt def moveto(self, x, y): # if (self.__cur_element.nodeName != 'path') : raise OverflowError, "No path for moveto" d = ' '.join([self.__cur_element.getAttribute('d'),'M',`x`,`-y`]).strip() self.__cur_element.setAttribute('d', d) def lineto(self, x, y): if (self.__cur_element.nodeName != 'path') : raise OverflowError, "No path for lineto" d = ' '.join([self.__cur_element.getAttribute('d'),'L',`x`,`-y`]).strip() self.__cur_element.setAttribute('d', d) def path_arc(self, x, y, radius, ratio, start_angle, end_angle): # mimic PS 'arc' given radius, yr/xr (=eccentricity), start and # end angles. PS arc draws from CP (if exists) to arc start, # then draws arc in counterclockwise dir from start to end # SVG provides an arc command that draws a segment of an # ellipse (but not a full circle) given these args: # A xr yr rotate majorArcFlag counterclockwiseFlag xe ye # We don't use rotate(=0) and flipped axes => all arcs are clockwise if (self.__cur_element.nodeName != 'path') : raise OverflowError, "No path for path_arc" self.comment('x=%g, y=%g, r=%g, :=%g, %g-%g' % (x,y,radius,ratio,start_angle,end_angle)) xs = x+radius*math.cos(2*math.pi/360.*start_angle) ys = y+ratio*radius*math.sin(2*math.pi/360.*start_angle) xe = x+radius*math.cos(2*math.pi/360.*end_angle) ye = y+ratio*radius*math.sin(2*math.pi/360.*end_angle) if (end_angle < start_angle) : # make end bigger than start while end_angle <= start_angle: # '<=' so 360->0 becomes 360->720 end_angle += 360 full_circ = (end_angle - start_angle >= 360) # draw a full circle? d = self.__cur_element.getAttribute('d') d += ' %s %g %g' % (d and 'L' or 'M',xs,-ys) # draw from CP, if exists if (radius > 0) : # skip, eg. 0-radius 'rounded' corners which blowup if (full_circ) : # If we're drawing a full circle, move to the end coord # and draw half a circle to the reflected xe,ye d += ' M %g %g A %g %g 0 1 0 %g %g'%(xe,-ye, radius,radius*ratio, 2*x-xe,-(2*y-ye)) # Draw arc from the CP (either reflected xe,ye for full circle else # xs,ys) to the end coord - note with full_circ the # 'bigArcFlag' value is moot, with exactly 180deg left to draw d += ' A %g %g 0 %d 0 %g %g' % (radius,radius*ratio, end_angle-start_angle>180, xe,-ye) self.__cur_element.setAttribute('d',d.strip()) def curveto(self, x1,y1,x2,y2,x3,y3): # Equivalent of PostScript's x1 y1 x2 y2 x3 y3 curveto which # draws a cubic bezier curve from curr pt to x3,y3 with ctrl points # x1,y1, and x2,y2 # In SVG this is just d='[M x0 y0] C x1 y1 x2 y2 x3 y3' #! I can't find an example of this being used to test it if (self.__cur_element.nodeNode != 'path') : raise OverflowError, "No path for curveto" d = ' '.join([self.__cur_element.getAttribute('d'),'C', `x1`,`-y1`,`x2`,`-y2`,`x3`,`-y3`,]).strip() self.__cur_element.setAttribute('d', d) def closepath(self): # close back to start of path if (self.__cur_element.nodeName != 'path') : raise OverflowError, "No path for closepath" d = ' '.join([self.__cur_element.getAttribute('d'),'Z']).strip() self.__cur_element.setAttribute('d', d) # Next we have three methods for finalizing a path element, # either fill it, clip to it, or draw it (stroke) # canvas.polygon() can generate fill/clip cmds with # no corresponding path so just ignore them def stroke(self): if (self.__cur_element.nodeName != 'path') : self.comment('No path - ignoring stroke') return self.__update_style(fill='none') self.__cur_element = self.__cur_element.parentNode def fill(self): if (self.__cur_element.nodeName != 'path') : self.comment('No path - ignoring fill') return self.__update_style(stroke='none') self.__cur_element = self.__cur_element.parentNode def clip_sub(self): if (self.__cur_element.nodeName != 'path') : self.comment('No path - ignoring clip') return # remove the current path from the tree ... p = self.__cur_element self.__cur_element=p.parentNode self.__cur_element.removeChild(p) # ... add it to a clipPath elt in the defs section clip = self.__doc.createElement('clipPath') clipid = 'clip'+`len(self.__defs.childNodes)` clip.setAttribute('id',clipid) clip.appendChild(p) self.__defs.appendChild(clip) # ... update the local style to point to it self.__update_style(clip_path = 'url(#%s)'%clipid) # The text_xxx routines specify the start/end and contents of text def text_begin(self): if (self.__cur_element.nodeName != 'g') : raise ValueError, "No group for text block" t = self.__doc.createElement('text') self.__cur_element.appendChild(t) self.__cur_element = t def text_moveto(self, x, y, angle): if (self.__cur_element.nodeName != 'text') : raise ValueError, "No text for moveto" self.__cur_element.setAttribute('x',`x`) self.__cur_element.setAttribute('y',`-y`) if (angle) : self.__cur_element.setAttribute('transform', 'rotate(%g,%g,%g)' % (-angle,x,-y)) def text_show(self, font_name, size, color, string): if (self.__cur_element.nodeName != 'text') : raise ValueError, "No text for show" # PyChart constructs a postscript font name, for example: # # Helvetica Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique # Helvetica-Narrow Times-Roman Times-Italic # Symbol Palatino-Roman Bookman-Demi Courier AvantGarde-Book # # We need to deconstruct this to get the font-family (the # piece before the '-'), and other characteristics. # Note that 'Courier' seems to correspond to SVGs 'CourierNew' # and that the SVG Symbol font is Unicode where the ascii text # 'Symbol' doesn't create greek characters like 'Sigma ...' - # should really pass a unicode string, or provide translation # # SVG defines: # font-style = normal (aka roman) | italic | oblique # font-weight = normal | bold (aka demi?) # font-stretch = normal | wider | narrower | ultra-condensed | # extra-condensed | condensed | semi-condensed | # semi-expanded | expanded | extra-expanded | ultra-expanded # ('narrow' seems to correspond to 'condensed') font_name, modifiers = re.match(r'([^-]*)(-.*)?', font_name).groups() if font_name == 'Courier' : font_name = 'CourierNew' font_style = font_weight = font_stretch = 'normal' if modifiers : if re.search('Italic',modifiers) : font_style = 'italic' elif re.search('Oblique',modifiers) : font_style = 'oblique' if re.search('Bold|Demi',modifiers) : font_weight = 'bold' if re.search('Narrow',modifiers) : font_stretch = 'condensed' #! translate ascii symbol font chars -> unicode (see www.unicode.org) #! http://www.unicode.org/Public/MAPPINGS/VENDORS/ADOBE/symbol.txt #! but xml Text element writes unicode chars as '?' to XML file... string = re.sub(r'\\([()])',r'\1',string) # unescape brackets self.__update_style(fill=_svgcolor(color), stroke='none', font_family=font_name, font_size=size, font_style=font_style, font_weight=font_weight, font_stretch=font_stretch) self.__cur_element.appendChild(self.__doc.createTextNode(string.encode('utf-8'))) def text_end(self): if (self.__cur_element.nodeName != 'text') : raise ValueError, "No text for close" self.__cur_element = self.__cur_element.parentNode # Three methods that change the local style of elements # If applied to a group, they persist until the next grestore, # If applied within a path element, they only affect that path - # although this may not in general correspond to (say) PostScript # behavior, it appears to correspond to reflect mode of use of this API def set_fill_color(self, color): self.__update_style(fill=_svgcolor(color)) def set_stroke_color(self, color): self.__update_style(stroke=_svgcolor(color)) def set_line_style(self, style): # see line_style.py linecap = {0:'butt', 1:'round', 2:'square'} linejoin = {0:'miter', 1:'round', 2:'bevel'} if style.dash: dash = ','.join(map(str,style.dash)) else : dash = 'none' self.__update_style(stroke_width = style.width, stroke = _svgcolor(style.color), stroke_linecap = linecap[style.cap_style], stroke_linejoin = linejoin[style.join_style], stroke_dasharray = dash) # gsave & grestore respectively push & pop a new context to hold # new style and transform parameters. push/pop transformation are # similar but explicitly specify a coordinate transform at the # same time def gsave(self): if (self.__cur_element.nodeName not in ['g','svg']) : raise ValueError, "No group for gsave" g = self.__doc.createElement('g') self.__cur_element.appendChild(g) self.__cur_element = g def grestore(self): if (self.__cur_element.nodeName != 'g'): raise ValueError, "No group for grestore" # first pop off any auto-generated groups (see protectCurrentChildren) while (self.__cur_element.hasAttribute('auto')) : self.__cur_element.removeAttribute('auto') self.__cur_element = self.__cur_element.parentNode # then pop off the original caller-generated group self.__cur_element = self.__cur_element.parentNode def push_transformation(self, baseloc, scale, angle, in_text=0): #? in_text arg appears to always be ignored # In some cases this gets called after newpath, with # corresonding pop_transformation called after the path is # finalized so we check specifically for that, and generate # an enclosing group to hold the incomplete path element # We could add the transform directly to the path element # (like we do with line-style etc) but that makes it harder # to handle the closing 'pop' and might lead to inconsitency # with PostScript if the closing pop doesn't come right after # the path element elt = self.__cur_element if elt.nodeName == 'g': elt = None elif (elt.nodeName == 'path' and not elt.hasAttribute('d')) : g = elt.parentNode g.removeChild(elt) self.__cur_element = g else: raise ValueError, "Illegal placement of push_transformation" t = '' if baseloc : t += 'translate(%g,%g) '%(baseloc[0],-baseloc[1]) if angle : t += 'rotate(%g) '%-angle if scale : t += 'scale(%g,%g) '%tuple(scale) self.gsave() self.__cur_element.setAttribute('transform',t.strip()) if elt: # elt has incomplete 'path' or None self.__cur_element.appendChild(elt) self.__cur_element = elt def pop_transformation(self, in_text=0): #? in_text unused? self.grestore() # If verbose, add comments to the output stream (helps debugging) def comment(self, string): if _comment_p : self.__cur_element.appendChild(self.__doc.createComment(string)) # The verbatim method is currently not supported - presumably with # the SVG backend the user would require access to the DOM since # we're not directly outputting plain text here def verbatim(self, string): self.__cur_element.appendChild(self.__doc.createComment('verbatim not implemented: ' + string)) # The close() method finalizes the SVG document and flattens the # DOM document to XML text to the specified file (or stdout) def close(self): basecanvas.T.close(self) self.grestore() # matching the gsave in __init__ if (self.__cur_element.nodeName != 'svg') : raise ValueError, "Incomplete document at close!" # Don't bother to output an empty document - this can happen # when we get close()d immediately by theme reinit if (len(self.__svg.childNodes[-1].childNodes) == 0) : return fp, need_close = self.open_output(self.__out_fname) bbox = theme.adjust_bounding_box([self.__xmin, self.__ymin, self.__xmax, self.__ymax]) self.__svg.setAttribute('viewBox','%g %g %g %g' % (xscale(bbox[0]), -yscale(bbox[3]), xscale(bbox[2])-xscale(bbox[0]), yscale(bbox[3])-yscale(bbox[1]))) self.__svg.setAttribute('xmlns','http://www.w3.org/2000/svg') self.__svg.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink') self.__doc.writexml(fp,'',' ','\n') if need_close: fp.close() PyChart-1.39/pychart/arrow_doc.py0000644000175000017500000000006710354321374020464 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/area_doc.py0000644000175000017500000000006710354321374020242 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/empty_docs.py0000644000175000017500000000263410354321345020653 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # def generate_doc(name, suffix="", append = 0): if append: fp = open(name + "_doc.py", "a+") else: fp = open(name + "_doc.py", "w") fp.write("# automatically generated by generate_docs.py.\n") fp.write("doc" + suffix + "=\" \"\n") fp.close() generate_doc( "area") generate_doc( "arrow") generate_doc( "axis", "_x") generate_doc( "axis", "_y", 1) generate_doc( "bar_plot") generate_doc( "color") generate_doc( "error_bar","_1") generate_doc( "error_bar", "_2", 1) generate_doc( "error_bar", "_3", 1) generate_doc( "error_bar", "_4", 1) generate_doc( "error_bar", "_5", 1) generate_doc( "error_bar", "_6", 1) generate_doc( "fill_style") generate_doc("line_plot") generate_doc("pie_plot") generate_doc("text_box") generate_doc("range_plot") generate_doc("legend") generate_doc("legend", "_entry", 1) generate_doc("line_style") generate_doc("tick_mark") PyChart-1.39/pychart/color.py0000644000175000017500000007522710354321374017635 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import chart_object import object_set import types import theme import pychart_util import color_doc from pychart_types import * blackify_colors = 1 class T(chart_object.T): __doc__ = color_doc.doc keys={ "r" : (NumberType, 0.0, "The intensity of red. The value is between 0 and 1."), "g" : (NumberType, 0.0, "The intensity of green. The value is between 0 and 1."), "b" : (NumberType, 0.0, "The intensity of blue. The value is between 0 and 1.") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def __str__(self): s = name_table().lookup(self) if s: return s if self.r == self.g and self.r == self.b: return "" % self.r else: return "" % (self.r, self.g, self.b) standards = object_set.T() def _intern(r,g,b): c = T(r = r, g = g, b = b) standards.add(c) return c def gray_scale(g): """Generate a grayscale color.T object. G=0 produces white, G=1.0 produces black.""" return T(r=g,g=g,b=g) # generated automatically from rgb.txt snow = _intern(r=1.000000,g=0.980392,b=0.980392) ghostwhite = _intern(r=0.972549,g=0.972549,b=1.000000) whitesmoke = _intern(r=0.960784,g=0.960784,b=0.960784) gainsboro = _intern(r=0.862745,g=0.862745,b=0.862745) floralwhite = _intern(r=1.000000,g=0.980392,b=0.941176) oldlace = _intern(r=0.992157,g=0.960784,b=0.901961) linen = _intern(r=0.980392,g=0.941176,b=0.901961) antiquewhite = _intern(r=0.980392,g=0.921569,b=0.843137) papayawhip = _intern(r=1.000000,g=0.937255,b=0.835294) blanchedalmond = _intern(r=1.000000,g=0.921569,b=0.803922) bisque = _intern(r=1.000000,g=0.894118,b=0.768627) peachpuff = _intern(r=1.000000,g=0.854902,b=0.725490) navajowhite = _intern(r=1.000000,g=0.870588,b=0.678431) moccasin = _intern(r=1.000000,g=0.894118,b=0.709804) cornsilk = _intern(r=1.000000,g=0.972549,b=0.862745) ivory = _intern(r=1.000000,g=1.000000,b=0.941176) lemonchiffon = _intern(r=1.000000,g=0.980392,b=0.803922) seashell = _intern(r=1.000000,g=0.960784,b=0.933333) honeydew = _intern(r=0.941176,g=1.000000,b=0.941176) mintcream = _intern(r=0.960784,g=1.000000,b=0.980392) azure = _intern(r=0.941176,g=1.000000,b=1.000000) aliceblue = _intern(r=0.941176,g=0.972549,b=1.000000) lavender = _intern(r=0.901961,g=0.901961,b=0.980392) lavenderblush = _intern(r=1.000000,g=0.941176,b=0.960784) mistyrose = _intern(r=1.000000,g=0.894118,b=0.882353) white = _intern(r=1.000000,g=1.000000,b=1.000000) black = _intern(r=0.000000,g=0.000000,b=0.000000) darkslategray = _intern(r=0.184314,g=0.309804,b=0.309804) dimgray = _intern(r=0.411765,g=0.411765,b=0.411765) slategray = _intern(r=0.439216,g=0.501961,b=0.564706) lightslategray = _intern(r=0.466667,g=0.533333,b=0.600000) gray = _intern(r=0.745098,g=0.745098,b=0.745098) lightgray = _intern(r=0.827451,g=0.827451,b=0.827451) midnightblue = _intern(r=0.098039,g=0.098039,b=0.439216) navy = _intern(r=0.000000,g=0.000000,b=0.501961) navyblue = _intern(r=0.000000,g=0.000000,b=0.501961) cornflowerblue = _intern(r=0.392157,g=0.584314,b=0.929412) darkslateblue = _intern(r=0.282353,g=0.239216,b=0.545098) slateblue = _intern(r=0.415686,g=0.352941,b=0.803922) mediumslateblue = _intern(r=0.482353,g=0.407843,b=0.933333) lightslateblue = _intern(r=0.517647,g=0.439216,b=1.000000) mediumblue = _intern(r=0.000000,g=0.000000,b=0.803922) royalblue = _intern(r=0.254902,g=0.411765,b=0.882353) blue = _intern(r=0.000000,g=0.000000,b=1.000000) dodgerblue = _intern(r=0.117647,g=0.564706,b=1.000000) deepskyblue = _intern(r=0.000000,g=0.749020,b=1.000000) skyblue = _intern(r=0.529412,g=0.807843,b=0.921569) lightskyblue = _intern(r=0.529412,g=0.807843,b=0.980392) steelblue = _intern(r=0.274510,g=0.509804,b=0.705882) lightsteelblue = _intern(r=0.690196,g=0.768627,b=0.870588) lightblue = _intern(r=0.678431,g=0.847059,b=0.901961) powderblue = _intern(r=0.690196,g=0.878431,b=0.901961) paleturquoise = _intern(r=0.686275,g=0.933333,b=0.933333) darkturquoise = _intern(r=0.000000,g=0.807843,b=0.819608) mediumturquoise = _intern(r=0.282353,g=0.819608,b=0.800000) turquoise = _intern(r=0.250980,g=0.878431,b=0.815686) cyan = _intern(r=0.000000,g=1.000000,b=1.000000) lightcyan = _intern(r=0.878431,g=1.000000,b=1.000000) cadetblue = _intern(r=0.372549,g=0.619608,b=0.627451) mediumaquamarine = _intern(r=0.400000,g=0.803922,b=0.666667) aquamarine = _intern(r=0.498039,g=1.000000,b=0.831373) darkgreen = _intern(r=0.000000,g=0.392157,b=0.000000) darkolivegreen = _intern(r=0.333333,g=0.419608,b=0.184314) darkseagreen = _intern(r=0.560784,g=0.737255,b=0.560784) seagreen = _intern(r=0.180392,g=0.545098,b=0.341176) mediumseagreen = _intern(r=0.235294,g=0.701961,b=0.443137) lightseagreen = _intern(r=0.125490,g=0.698039,b=0.666667) palegreen = _intern(r=0.596078,g=0.984314,b=0.596078) springgreen = _intern(r=0.000000,g=1.000000,b=0.498039) lawngreen = _intern(r=0.486275,g=0.988235,b=0.000000) green = _intern(r=0.000000,g=1.000000,b=0.000000) chartreuse = _intern(r=0.498039,g=1.000000,b=0.000000) mediumspringgreen = _intern(r=0.000000,g=0.980392,b=0.603922) greenyellow = _intern(r=0.678431,g=1.000000,b=0.184314) limegreen = _intern(r=0.196078,g=0.803922,b=0.196078) yellowgreen = _intern(r=0.603922,g=0.803922,b=0.196078) forestgreen = _intern(r=0.133333,g=0.545098,b=0.133333) olivedrab = _intern(r=0.419608,g=0.556863,b=0.137255) darkkhaki = _intern(r=0.741176,g=0.717647,b=0.419608) khaki = _intern(r=0.941176,g=0.901961,b=0.549020) palegoldenrod = _intern(r=0.933333,g=0.909804,b=0.666667) lightgoldenrodyellow = _intern(r=0.980392,g=0.980392,b=0.823529) lightyellow = _intern(r=1.000000,g=1.000000,b=0.878431) yellow = _intern(r=1.000000,g=1.000000,b=0.000000) gold = _intern(r=1.000000,g=0.843137,b=0.000000) lightgoldenrod = _intern(r=0.933333,g=0.866667,b=0.509804) goldenrod = _intern(r=0.854902,g=0.647059,b=0.125490) darkgoldenrod = _intern(r=0.721569,g=0.525490,b=0.043137) rosybrown = _intern(r=0.737255,g=0.560784,b=0.560784) indianred = _intern(r=0.803922,g=0.360784,b=0.360784) saddlebrown = _intern(r=0.545098,g=0.270588,b=0.074510) sienna = _intern(r=0.627451,g=0.321569,b=0.176471) peru = _intern(r=0.803922,g=0.521569,b=0.247059) burlywood = _intern(r=0.870588,g=0.721569,b=0.529412) beige = _intern(r=0.960784,g=0.960784,b=0.862745) wheat = _intern(r=0.960784,g=0.870588,b=0.701961) sandybrown = _intern(r=0.956863,g=0.643137,b=0.376471) tan = _intern(r=0.823529,g=0.705882,b=0.549020) chocolate = _intern(r=0.823529,g=0.411765,b=0.117647) firebrick = _intern(r=0.698039,g=0.133333,b=0.133333) brown = _intern(r=0.647059,g=0.164706,b=0.164706) darksalmon = _intern(r=0.913725,g=0.588235,b=0.478431) salmon = _intern(r=0.980392,g=0.501961,b=0.447059) lightsalmon = _intern(r=1.000000,g=0.627451,b=0.478431) orange = _intern(r=1.000000,g=0.647059,b=0.000000) darkorange = _intern(r=1.000000,g=0.549020,b=0.000000) coral = _intern(r=1.000000,g=0.498039,b=0.313725) lightcoral = _intern(r=0.941176,g=0.501961,b=0.501961) tomato = _intern(r=1.000000,g=0.388235,b=0.278431) orangered = _intern(r=1.000000,g=0.270588,b=0.000000) red = _intern(r=1.000000,g=0.000000,b=0.000000) hotpink = _intern(r=1.000000,g=0.411765,b=0.705882) deeppink = _intern(r=1.000000,g=0.078431,b=0.576471) pink = _intern(r=1.000000,g=0.752941,b=0.796078) lightpink = _intern(r=1.000000,g=0.713725,b=0.756863) palevioletred = _intern(r=0.858824,g=0.439216,b=0.576471) maroon = _intern(r=0.690196,g=0.188235,b=0.376471) mediumvioletred = _intern(r=0.780392,g=0.082353,b=0.521569) violetred = _intern(r=0.815686,g=0.125490,b=0.564706) magenta = _intern(r=1.000000,g=0.000000,b=1.000000) violet = _intern(r=0.933333,g=0.509804,b=0.933333) plum = _intern(r=0.866667,g=0.627451,b=0.866667) orchid = _intern(r=0.854902,g=0.439216,b=0.839216) mediumorchid = _intern(r=0.729412,g=0.333333,b=0.827451) darkorchid = _intern(r=0.600000,g=0.196078,b=0.800000) darkviolet = _intern(r=0.580392,g=0.000000,b=0.827451) blueviolet = _intern(r=0.541176,g=0.168627,b=0.886275) purple = _intern(r=0.627451,g=0.125490,b=0.941176) mediumpurple = _intern(r=0.576471,g=0.439216,b=0.858824) thistle = _intern(r=0.847059,g=0.749020,b=0.847059) snow1 = _intern(r=1.000000,g=0.980392,b=0.980392) snow2 = _intern(r=0.933333,g=0.913725,b=0.913725) snow3 = _intern(r=0.803922,g=0.788235,b=0.788235) snow4 = _intern(r=0.545098,g=0.537255,b=0.537255) seashell1 = _intern(r=1.000000,g=0.960784,b=0.933333) seashell2 = _intern(r=0.933333,g=0.898039,b=0.870588) seashell3 = _intern(r=0.803922,g=0.772549,b=0.749020) seashell4 = _intern(r=0.545098,g=0.525490,b=0.509804) antiquewhite1 = _intern(r=1.000000,g=0.937255,b=0.858824) antiquewhite2 = _intern(r=0.933333,g=0.874510,b=0.800000) antiquewhite3 = _intern(r=0.803922,g=0.752941,b=0.690196) antiquewhite4 = _intern(r=0.545098,g=0.513725,b=0.470588) bisque1 = _intern(r=1.000000,g=0.894118,b=0.768627) bisque2 = _intern(r=0.933333,g=0.835294,b=0.717647) bisque3 = _intern(r=0.803922,g=0.717647,b=0.619608) bisque4 = _intern(r=0.545098,g=0.490196,b=0.419608) peachpuff1 = _intern(r=1.000000,g=0.854902,b=0.725490) peachpuff2 = _intern(r=0.933333,g=0.796078,b=0.678431) peachpuff3 = _intern(r=0.803922,g=0.686275,b=0.584314) peachpuff4 = _intern(r=0.545098,g=0.466667,b=0.396078) navajowhite1 = _intern(r=1.000000,g=0.870588,b=0.678431) navajowhite2 = _intern(r=0.933333,g=0.811765,b=0.631373) navajowhite3 = _intern(r=0.803922,g=0.701961,b=0.545098) navajowhite4 = _intern(r=0.545098,g=0.474510,b=0.368627) lemonchiffon1 = _intern(r=1.000000,g=0.980392,b=0.803922) lemonchiffon2 = _intern(r=0.933333,g=0.913725,b=0.749020) lemonchiffon3 = _intern(r=0.803922,g=0.788235,b=0.647059) lemonchiffon4 = _intern(r=0.545098,g=0.537255,b=0.439216) cornsilk1 = _intern(r=1.000000,g=0.972549,b=0.862745) cornsilk2 = _intern(r=0.933333,g=0.909804,b=0.803922) cornsilk3 = _intern(r=0.803922,g=0.784314,b=0.694118) cornsilk4 = _intern(r=0.545098,g=0.533333,b=0.470588) ivory1 = _intern(r=1.000000,g=1.000000,b=0.941176) ivory2 = _intern(r=0.933333,g=0.933333,b=0.878431) ivory3 = _intern(r=0.803922,g=0.803922,b=0.756863) ivory4 = _intern(r=0.545098,g=0.545098,b=0.513725) honeydew1 = _intern(r=0.941176,g=1.000000,b=0.941176) honeydew2 = _intern(r=0.878431,g=0.933333,b=0.878431) honeydew3 = _intern(r=0.756863,g=0.803922,b=0.756863) honeydew4 = _intern(r=0.513725,g=0.545098,b=0.513725) lavenderblush1 = _intern(r=1.000000,g=0.941176,b=0.960784) lavenderblush2 = _intern(r=0.933333,g=0.878431,b=0.898039) lavenderblush3 = _intern(r=0.803922,g=0.756863,b=0.772549) lavenderblush4 = _intern(r=0.545098,g=0.513725,b=0.525490) mistyrose1 = _intern(r=1.000000,g=0.894118,b=0.882353) mistyrose2 = _intern(r=0.933333,g=0.835294,b=0.823529) mistyrose3 = _intern(r=0.803922,g=0.717647,b=0.709804) mistyrose4 = _intern(r=0.545098,g=0.490196,b=0.482353) azure1 = _intern(r=0.941176,g=1.000000,b=1.000000) azure2 = _intern(r=0.878431,g=0.933333,b=0.933333) azure3 = _intern(r=0.756863,g=0.803922,b=0.803922) azure4 = _intern(r=0.513725,g=0.545098,b=0.545098) slateblue1 = _intern(r=0.513725,g=0.435294,b=1.000000) slateblue2 = _intern(r=0.478431,g=0.403922,b=0.933333) slateblue3 = _intern(r=0.411765,g=0.349020,b=0.803922) slateblue4 = _intern(r=0.278431,g=0.235294,b=0.545098) royalblue1 = _intern(r=0.282353,g=0.462745,b=1.000000) royalblue2 = _intern(r=0.262745,g=0.431373,b=0.933333) royalblue3 = _intern(r=0.227451,g=0.372549,b=0.803922) royalblue4 = _intern(r=0.152941,g=0.250980,b=0.545098) blue1 = _intern(r=0.000000,g=0.000000,b=1.000000) blue2 = _intern(r=0.000000,g=0.000000,b=0.933333) blue3 = _intern(r=0.000000,g=0.000000,b=0.803922) blue4 = _intern(r=0.000000,g=0.000000,b=0.545098) dodgerblue1 = _intern(r=0.117647,g=0.564706,b=1.000000) dodgerblue2 = _intern(r=0.109804,g=0.525490,b=0.933333) dodgerblue3 = _intern(r=0.094118,g=0.454902,b=0.803922) dodgerblue4 = _intern(r=0.062745,g=0.305882,b=0.545098) steelblue1 = _intern(r=0.388235,g=0.721569,b=1.000000) steelblue2 = _intern(r=0.360784,g=0.674510,b=0.933333) steelblue3 = _intern(r=0.309804,g=0.580392,b=0.803922) steelblue4 = _intern(r=0.211765,g=0.392157,b=0.545098) deepskyblue1 = _intern(r=0.000000,g=0.749020,b=1.000000) deepskyblue2 = _intern(r=0.000000,g=0.698039,b=0.933333) deepskyblue3 = _intern(r=0.000000,g=0.603922,b=0.803922) deepskyblue4 = _intern(r=0.000000,g=0.407843,b=0.545098) skyblue1 = _intern(r=0.529412,g=0.807843,b=1.000000) skyblue2 = _intern(r=0.494118,g=0.752941,b=0.933333) skyblue3 = _intern(r=0.423529,g=0.650980,b=0.803922) skyblue4 = _intern(r=0.290196,g=0.439216,b=0.545098) lightskyblue1 = _intern(r=0.690196,g=0.886275,b=1.000000) lightskyblue2 = _intern(r=0.643137,g=0.827451,b=0.933333) lightskyblue3 = _intern(r=0.552941,g=0.713725,b=0.803922) lightskyblue4 = _intern(r=0.376471,g=0.482353,b=0.545098) slategray1 = _intern(r=0.776471,g=0.886275,b=1.000000) slategray2 = _intern(r=0.725490,g=0.827451,b=0.933333) slategray3 = _intern(r=0.623529,g=0.713725,b=0.803922) slategray4 = _intern(r=0.423529,g=0.482353,b=0.545098) lightsteelblue1 = _intern(r=0.792157,g=0.882353,b=1.000000) lightsteelblue2 = _intern(r=0.737255,g=0.823529,b=0.933333) lightsteelblue3 = _intern(r=0.635294,g=0.709804,b=0.803922) lightsteelblue4 = _intern(r=0.431373,g=0.482353,b=0.545098) lightblue1 = _intern(r=0.749020,g=0.937255,b=1.000000) lightblue2 = _intern(r=0.698039,g=0.874510,b=0.933333) lightblue3 = _intern(r=0.603922,g=0.752941,b=0.803922) lightblue4 = _intern(r=0.407843,g=0.513725,b=0.545098) lightcyan1 = _intern(r=0.878431,g=1.000000,b=1.000000) lightcyan2 = _intern(r=0.819608,g=0.933333,b=0.933333) lightcyan3 = _intern(r=0.705882,g=0.803922,b=0.803922) lightcyan4 = _intern(r=0.478431,g=0.545098,b=0.545098) paleturquoise1 = _intern(r=0.733333,g=1.000000,b=1.000000) paleturquoise2 = _intern(r=0.682353,g=0.933333,b=0.933333) paleturquoise3 = _intern(r=0.588235,g=0.803922,b=0.803922) paleturquoise4 = _intern(r=0.400000,g=0.545098,b=0.545098) cadetblue1 = _intern(r=0.596078,g=0.960784,b=1.000000) cadetblue2 = _intern(r=0.556863,g=0.898039,b=0.933333) cadetblue3 = _intern(r=0.478431,g=0.772549,b=0.803922) cadetblue4 = _intern(r=0.325490,g=0.525490,b=0.545098) turquoise1 = _intern(r=0.000000,g=0.960784,b=1.000000) turquoise2 = _intern(r=0.000000,g=0.898039,b=0.933333) turquoise3 = _intern(r=0.000000,g=0.772549,b=0.803922) turquoise4 = _intern(r=0.000000,g=0.525490,b=0.545098) cyan1 = _intern(r=0.000000,g=1.000000,b=1.000000) cyan2 = _intern(r=0.000000,g=0.933333,b=0.933333) cyan3 = _intern(r=0.000000,g=0.803922,b=0.803922) cyan4 = _intern(r=0.000000,g=0.545098,b=0.545098) darkslategray1 = _intern(r=0.592157,g=1.000000,b=1.000000) darkslategray2 = _intern(r=0.552941,g=0.933333,b=0.933333) darkslategray3 = _intern(r=0.474510,g=0.803922,b=0.803922) darkslategray4 = _intern(r=0.321569,g=0.545098,b=0.545098) aquamarine1 = _intern(r=0.498039,g=1.000000,b=0.831373) aquamarine2 = _intern(r=0.462745,g=0.933333,b=0.776471) aquamarine3 = _intern(r=0.400000,g=0.803922,b=0.666667) aquamarine4 = _intern(r=0.270588,g=0.545098,b=0.454902) darkseagreen1 = _intern(r=0.756863,g=1.000000,b=0.756863) darkseagreen2 = _intern(r=0.705882,g=0.933333,b=0.705882) darkseagreen3 = _intern(r=0.607843,g=0.803922,b=0.607843) darkseagreen4 = _intern(r=0.411765,g=0.545098,b=0.411765) seagreen1 = _intern(r=0.329412,g=1.000000,b=0.623529) seagreen2 = _intern(r=0.305882,g=0.933333,b=0.580392) seagreen3 = _intern(r=0.262745,g=0.803922,b=0.501961) seagreen4 = _intern(r=0.180392,g=0.545098,b=0.341176) palegreen1 = _intern(r=0.603922,g=1.000000,b=0.603922) palegreen2 = _intern(r=0.564706,g=0.933333,b=0.564706) palegreen3 = _intern(r=0.486275,g=0.803922,b=0.486275) palegreen4 = _intern(r=0.329412,g=0.545098,b=0.329412) springgreen1 = _intern(r=0.000000,g=1.000000,b=0.498039) springgreen2 = _intern(r=0.000000,g=0.933333,b=0.462745) springgreen3 = _intern(r=0.000000,g=0.803922,b=0.400000) springgreen4 = _intern(r=0.000000,g=0.545098,b=0.270588) green1 = _intern(r=0.000000,g=1.000000,b=0.000000) green2 = _intern(r=0.000000,g=0.933333,b=0.000000) green3 = _intern(r=0.000000,g=0.803922,b=0.000000) green4 = _intern(r=0.000000,g=0.545098,b=0.000000) chartreuse1 = _intern(r=0.498039,g=1.000000,b=0.000000) chartreuse2 = _intern(r=0.462745,g=0.933333,b=0.000000) chartreuse3 = _intern(r=0.400000,g=0.803922,b=0.000000) chartreuse4 = _intern(r=0.270588,g=0.545098,b=0.000000) olivedrab1 = _intern(r=0.752941,g=1.000000,b=0.243137) olivedrab2 = _intern(r=0.701961,g=0.933333,b=0.227451) olivedrab3 = _intern(r=0.603922,g=0.803922,b=0.196078) olivedrab4 = _intern(r=0.411765,g=0.545098,b=0.133333) darkolivegreen1 = _intern(r=0.792157,g=1.000000,b=0.439216) darkolivegreen2 = _intern(r=0.737255,g=0.933333,b=0.407843) darkolivegreen3 = _intern(r=0.635294,g=0.803922,b=0.352941) darkolivegreen4 = _intern(r=0.431373,g=0.545098,b=0.239216) khaki1 = _intern(r=1.000000,g=0.964706,b=0.560784) khaki2 = _intern(r=0.933333,g=0.901961,b=0.521569) khaki3 = _intern(r=0.803922,g=0.776471,b=0.450980) khaki4 = _intern(r=0.545098,g=0.525490,b=0.305882) lightgoldenrod1 = _intern(r=1.000000,g=0.925490,b=0.545098) lightgoldenrod2 = _intern(r=0.933333,g=0.862745,b=0.509804) lightgoldenrod3 = _intern(r=0.803922,g=0.745098,b=0.439216) lightgoldenrod4 = _intern(r=0.545098,g=0.505882,b=0.298039) lightyellow1 = _intern(r=1.000000,g=1.000000,b=0.878431) lightyellow2 = _intern(r=0.933333,g=0.933333,b=0.819608) lightyellow3 = _intern(r=0.803922,g=0.803922,b=0.705882) lightyellow4 = _intern(r=0.545098,g=0.545098,b=0.478431) yellow1 = _intern(r=1.000000,g=1.000000,b=0.000000) yellow2 = _intern(r=0.933333,g=0.933333,b=0.000000) yellow3 = _intern(r=0.803922,g=0.803922,b=0.000000) yellow4 = _intern(r=0.545098,g=0.545098,b=0.000000) gold1 = _intern(r=1.000000,g=0.843137,b=0.000000) gold2 = _intern(r=0.933333,g=0.788235,b=0.000000) gold3 = _intern(r=0.803922,g=0.678431,b=0.000000) gold4 = _intern(r=0.545098,g=0.458824,b=0.000000) goldenrod1 = _intern(r=1.000000,g=0.756863,b=0.145098) goldenrod2 = _intern(r=0.933333,g=0.705882,b=0.133333) goldenrod3 = _intern(r=0.803922,g=0.607843,b=0.113725) goldenrod4 = _intern(r=0.545098,g=0.411765,b=0.078431) darkgoldenrod1 = _intern(r=1.000000,g=0.725490,b=0.058824) darkgoldenrod2 = _intern(r=0.933333,g=0.678431,b=0.054902) darkgoldenrod3 = _intern(r=0.803922,g=0.584314,b=0.047059) darkgoldenrod4 = _intern(r=0.545098,g=0.396078,b=0.031373) rosybrown1 = _intern(r=1.000000,g=0.756863,b=0.756863) rosybrown2 = _intern(r=0.933333,g=0.705882,b=0.705882) rosybrown3 = _intern(r=0.803922,g=0.607843,b=0.607843) rosybrown4 = _intern(r=0.545098,g=0.411765,b=0.411765) indianred1 = _intern(r=1.000000,g=0.415686,b=0.415686) indianred2 = _intern(r=0.933333,g=0.388235,b=0.388235) indianred3 = _intern(r=0.803922,g=0.333333,b=0.333333) indianred4 = _intern(r=0.545098,g=0.227451,b=0.227451) sienna1 = _intern(r=1.000000,g=0.509804,b=0.278431) sienna2 = _intern(r=0.933333,g=0.474510,b=0.258824) sienna3 = _intern(r=0.803922,g=0.407843,b=0.223529) sienna4 = _intern(r=0.545098,g=0.278431,b=0.149020) burlywood1 = _intern(r=1.000000,g=0.827451,b=0.607843) burlywood2 = _intern(r=0.933333,g=0.772549,b=0.568627) burlywood3 = _intern(r=0.803922,g=0.666667,b=0.490196) burlywood4 = _intern(r=0.545098,g=0.450980,b=0.333333) wheat1 = _intern(r=1.000000,g=0.905882,b=0.729412) wheat2 = _intern(r=0.933333,g=0.847059,b=0.682353) wheat3 = _intern(r=0.803922,g=0.729412,b=0.588235) wheat4 = _intern(r=0.545098,g=0.494118,b=0.400000) tan1 = _intern(r=1.000000,g=0.647059,b=0.309804) tan2 = _intern(r=0.933333,g=0.603922,b=0.286275) tan3 = _intern(r=0.803922,g=0.521569,b=0.247059) tan4 = _intern(r=0.545098,g=0.352941,b=0.168627) chocolate1 = _intern(r=1.000000,g=0.498039,b=0.141176) chocolate2 = _intern(r=0.933333,g=0.462745,b=0.129412) chocolate3 = _intern(r=0.803922,g=0.400000,b=0.113725) chocolate4 = _intern(r=0.545098,g=0.270588,b=0.074510) firebrick1 = _intern(r=1.000000,g=0.188235,b=0.188235) firebrick2 = _intern(r=0.933333,g=0.172549,b=0.172549) firebrick3 = _intern(r=0.803922,g=0.149020,b=0.149020) firebrick4 = _intern(r=0.545098,g=0.101961,b=0.101961) brown1 = _intern(r=1.000000,g=0.250980,b=0.250980) brown2 = _intern(r=0.933333,g=0.231373,b=0.231373) brown3 = _intern(r=0.803922,g=0.200000,b=0.200000) brown4 = _intern(r=0.545098,g=0.137255,b=0.137255) salmon1 = _intern(r=1.000000,g=0.549020,b=0.411765) salmon2 = _intern(r=0.933333,g=0.509804,b=0.384314) salmon3 = _intern(r=0.803922,g=0.439216,b=0.329412) salmon4 = _intern(r=0.545098,g=0.298039,b=0.223529) lightsalmon1 = _intern(r=1.000000,g=0.627451,b=0.478431) lightsalmon2 = _intern(r=0.933333,g=0.584314,b=0.447059) lightsalmon3 = _intern(r=0.803922,g=0.505882,b=0.384314) lightsalmon4 = _intern(r=0.545098,g=0.341176,b=0.258824) orange1 = _intern(r=1.000000,g=0.647059,b=0.000000) orange2 = _intern(r=0.933333,g=0.603922,b=0.000000) orange3 = _intern(r=0.803922,g=0.521569,b=0.000000) orange4 = _intern(r=0.545098,g=0.352941,b=0.000000) darkorange1 = _intern(r=1.000000,g=0.498039,b=0.000000) darkorange2 = _intern(r=0.933333,g=0.462745,b=0.000000) darkorange3 = _intern(r=0.803922,g=0.400000,b=0.000000) darkorange4 = _intern(r=0.545098,g=0.270588,b=0.000000) coral1 = _intern(r=1.000000,g=0.447059,b=0.337255) coral2 = _intern(r=0.933333,g=0.415686,b=0.313725) coral3 = _intern(r=0.803922,g=0.356863,b=0.270588) coral4 = _intern(r=0.545098,g=0.243137,b=0.184314) tomato1 = _intern(r=1.000000,g=0.388235,b=0.278431) tomato2 = _intern(r=0.933333,g=0.360784,b=0.258824) tomato3 = _intern(r=0.803922,g=0.309804,b=0.223529) tomato4 = _intern(r=0.545098,g=0.211765,b=0.149020) orangered1 = _intern(r=1.000000,g=0.270588,b=0.000000) orangered2 = _intern(r=0.933333,g=0.250980,b=0.000000) orangered3 = _intern(r=0.803922,g=0.215686,b=0.000000) orangered4 = _intern(r=0.545098,g=0.145098,b=0.000000) red1 = _intern(r=1.000000,g=0.000000,b=0.000000) red2 = _intern(r=0.933333,g=0.000000,b=0.000000) red3 = _intern(r=0.803922,g=0.000000,b=0.000000) red4 = _intern(r=0.545098,g=0.000000,b=0.000000) deeppink1 = _intern(r=1.000000,g=0.078431,b=0.576471) deeppink2 = _intern(r=0.933333,g=0.070588,b=0.537255) deeppink3 = _intern(r=0.803922,g=0.062745,b=0.462745) deeppink4 = _intern(r=0.545098,g=0.039216,b=0.313725) hotpink1 = _intern(r=1.000000,g=0.431373,b=0.705882) hotpink2 = _intern(r=0.933333,g=0.415686,b=0.654902) hotpink3 = _intern(r=0.803922,g=0.376471,b=0.564706) hotpink4 = _intern(r=0.545098,g=0.227451,b=0.384314) pink1 = _intern(r=1.000000,g=0.709804,b=0.772549) pink2 = _intern(r=0.933333,g=0.662745,b=0.721569) pink3 = _intern(r=0.803922,g=0.568627,b=0.619608) pink4 = _intern(r=0.545098,g=0.388235,b=0.423529) lightpink1 = _intern(r=1.000000,g=0.682353,b=0.725490) lightpink2 = _intern(r=0.933333,g=0.635294,b=0.678431) lightpink3 = _intern(r=0.803922,g=0.549020,b=0.584314) lightpink4 = _intern(r=0.545098,g=0.372549,b=0.396078) palevioletred1 = _intern(r=1.000000,g=0.509804,b=0.670588) palevioletred2 = _intern(r=0.933333,g=0.474510,b=0.623529) palevioletred3 = _intern(r=0.803922,g=0.407843,b=0.537255) palevioletred4 = _intern(r=0.545098,g=0.278431,b=0.364706) maroon1 = _intern(r=1.000000,g=0.203922,b=0.701961) maroon2 = _intern(r=0.933333,g=0.188235,b=0.654902) maroon3 = _intern(r=0.803922,g=0.160784,b=0.564706) maroon4 = _intern(r=0.545098,g=0.109804,b=0.384314) violetred1 = _intern(r=1.000000,g=0.243137,b=0.588235) violetred2 = _intern(r=0.933333,g=0.227451,b=0.549020) violetred3 = _intern(r=0.803922,g=0.196078,b=0.470588) violetred4 = _intern(r=0.545098,g=0.133333,b=0.321569) magenta1 = _intern(r=1.000000,g=0.000000,b=1.000000) magenta2 = _intern(r=0.933333,g=0.000000,b=0.933333) magenta3 = _intern(r=0.803922,g=0.000000,b=0.803922) magenta4 = _intern(r=0.545098,g=0.000000,b=0.545098) orchid1 = _intern(r=1.000000,g=0.513725,b=0.980392) orchid2 = _intern(r=0.933333,g=0.478431,b=0.913725) orchid3 = _intern(r=0.803922,g=0.411765,b=0.788235) orchid4 = _intern(r=0.545098,g=0.278431,b=0.537255) plum1 = _intern(r=1.000000,g=0.733333,b=1.000000) plum2 = _intern(r=0.933333,g=0.682353,b=0.933333) plum3 = _intern(r=0.803922,g=0.588235,b=0.803922) plum4 = _intern(r=0.545098,g=0.400000,b=0.545098) mediumorchid1 = _intern(r=0.878431,g=0.400000,b=1.000000) mediumorchid2 = _intern(r=0.819608,g=0.372549,b=0.933333) mediumorchid3 = _intern(r=0.705882,g=0.321569,b=0.803922) mediumorchid4 = _intern(r=0.478431,g=0.215686,b=0.545098) darkorchid1 = _intern(r=0.749020,g=0.243137,b=1.000000) darkorchid2 = _intern(r=0.698039,g=0.227451,b=0.933333) darkorchid3 = _intern(r=0.603922,g=0.196078,b=0.803922) darkorchid4 = _intern(r=0.407843,g=0.133333,b=0.545098) purple1 = _intern(r=0.607843,g=0.188235,b=1.000000) purple2 = _intern(r=0.568627,g=0.172549,b=0.933333) purple3 = _intern(r=0.490196,g=0.149020,b=0.803922) purple4 = _intern(r=0.333333,g=0.101961,b=0.545098) mediumpurple1 = _intern(r=0.670588,g=0.509804,b=1.000000) mediumpurple2 = _intern(r=0.623529,g=0.474510,b=0.933333) mediumpurple3 = _intern(r=0.537255,g=0.407843,b=0.803922) mediumpurple4 = _intern(r=0.364706,g=0.278431,b=0.545098) thistle1 = _intern(r=1.000000,g=0.882353,b=1.000000) thistle2 = _intern(r=0.933333,g=0.823529,b=0.933333) thistle3 = _intern(r=0.803922,g=0.709804,b=0.803922) thistle4 = _intern(r=0.545098,g=0.482353,b=0.545098) gray00 = _intern(r=0.000000,g=0.000000,b=0.000000) gray01 = _intern(r=0.011765,g=0.011765,b=0.011765) gray02 = _intern(r=0.019608,g=0.019608,b=0.019608) gray03 = _intern(r=0.031373,g=0.031373,b=0.031373) gray04 = _intern(r=0.039216,g=0.039216,b=0.039216) gray05 = _intern(r=0.050980,g=0.050980,b=0.050980) gray06 = _intern(r=0.058824,g=0.058824,b=0.058824) gray07 = _intern(r=0.070588,g=0.070588,b=0.070588) gray08 = _intern(r=0.078431,g=0.078431,b=0.078431) gray09 = _intern(r=0.090196,g=0.090196,b=0.090196) gray10 = _intern(r=0.101961,g=0.101961,b=0.101961) gray11 = _intern(r=0.109804,g=0.109804,b=0.109804) gray12 = _intern(r=0.121569,g=0.121569,b=0.121569) gray13 = _intern(r=0.129412,g=0.129412,b=0.129412) gray14 = _intern(r=0.141176,g=0.141176,b=0.141176) gray15 = _intern(r=0.149020,g=0.149020,b=0.149020) gray16 = _intern(r=0.160784,g=0.160784,b=0.160784) gray17 = _intern(r=0.168627,g=0.168627,b=0.168627) gray18 = _intern(r=0.180392,g=0.180392,b=0.180392) gray19 = _intern(r=0.188235,g=0.188235,b=0.188235) gray20 = _intern(r=0.200000,g=0.200000,b=0.200000) gray21 = _intern(r=0.211765,g=0.211765,b=0.211765) gray22 = _intern(r=0.219608,g=0.219608,b=0.219608) gray23 = _intern(r=0.231373,g=0.231373,b=0.231373) gray24 = _intern(r=0.239216,g=0.239216,b=0.239216) gray25 = _intern(r=0.250980,g=0.250980,b=0.250980) gray26 = _intern(r=0.258824,g=0.258824,b=0.258824) gray27 = _intern(r=0.270588,g=0.270588,b=0.270588) gray28 = _intern(r=0.278431,g=0.278431,b=0.278431) gray29 = _intern(r=0.290196,g=0.290196,b=0.290196) gray30 = _intern(r=0.301961,g=0.301961,b=0.301961) gray31 = _intern(r=0.309804,g=0.309804,b=0.309804) gray32 = _intern(r=0.321569,g=0.321569,b=0.321569) gray33 = _intern(r=0.329412,g=0.329412,b=0.329412) gray34 = _intern(r=0.341176,g=0.341176,b=0.341176) gray35 = _intern(r=0.349020,g=0.349020,b=0.349020) gray36 = _intern(r=0.360784,g=0.360784,b=0.360784) gray37 = _intern(r=0.368627,g=0.368627,b=0.368627) gray38 = _intern(r=0.380392,g=0.380392,b=0.380392) gray39 = _intern(r=0.388235,g=0.388235,b=0.388235) gray40 = _intern(r=0.400000,g=0.400000,b=0.400000) gray41 = _intern(r=0.411765,g=0.411765,b=0.411765) gray42 = _intern(r=0.419608,g=0.419608,b=0.419608) gray43 = _intern(r=0.431373,g=0.431373,b=0.431373) gray44 = _intern(r=0.439216,g=0.439216,b=0.439216) gray45 = _intern(r=0.450980,g=0.450980,b=0.450980) gray46 = _intern(r=0.458824,g=0.458824,b=0.458824) gray47 = _intern(r=0.470588,g=0.470588,b=0.470588) gray48 = _intern(r=0.478431,g=0.478431,b=0.478431) gray49 = _intern(r=0.490196,g=0.490196,b=0.490196) gray50 = _intern(r=0.498039,g=0.498039,b=0.498039) gray51 = _intern(r=0.509804,g=0.509804,b=0.509804) gray52 = _intern(r=0.521569,g=0.521569,b=0.521569) gray53 = _intern(r=0.529412,g=0.529412,b=0.529412) gray54 = _intern(r=0.541176,g=0.541176,b=0.541176) gray55 = _intern(r=0.549020,g=0.549020,b=0.549020) gray56 = _intern(r=0.560784,g=0.560784,b=0.560784) gray57 = _intern(r=0.568627,g=0.568627,b=0.568627) gray58 = _intern(r=0.580392,g=0.580392,b=0.580392) gray59 = _intern(r=0.588235,g=0.588235,b=0.588235) gray60 = _intern(r=0.600000,g=0.600000,b=0.600000) gray61 = _intern(r=0.611765,g=0.611765,b=0.611765) gray62 = _intern(r=0.619608,g=0.619608,b=0.619608) gray63 = _intern(r=0.631373,g=0.631373,b=0.631373) gray64 = _intern(r=0.639216,g=0.639216,b=0.639216) gray65 = _intern(r=0.650980,g=0.650980,b=0.650980) gray66 = _intern(r=0.658824,g=0.658824,b=0.658824) gray67 = _intern(r=0.670588,g=0.670588,b=0.670588) gray68 = _intern(r=0.678431,g=0.678431,b=0.678431) gray69 = _intern(r=0.690196,g=0.690196,b=0.690196) gray70 = _intern(r=0.701961,g=0.701961,b=0.701961) gray71 = _intern(r=0.709804,g=0.709804,b=0.709804) gray72 = _intern(r=0.721569,g=0.721569,b=0.721569) gray73 = _intern(r=0.729412,g=0.729412,b=0.729412) gray74 = _intern(r=0.741176,g=0.741176,b=0.741176) gray75 = _intern(r=0.749020,g=0.749020,b=0.749020) gray76 = _intern(r=0.760784,g=0.760784,b=0.760784) gray77 = _intern(r=0.768627,g=0.768627,b=0.768627) gray78 = _intern(r=0.780392,g=0.780392,b=0.780392) gray79 = _intern(r=0.788235,g=0.788235,b=0.788235) gray80 = _intern(r=0.800000,g=0.800000,b=0.800000) gray81 = _intern(r=0.811765,g=0.811765,b=0.811765) gray82 = _intern(r=0.819608,g=0.819608,b=0.819608) gray83 = _intern(r=0.831373,g=0.831373,b=0.831373) gray84 = _intern(r=0.839216,g=0.839216,b=0.839216) gray85 = _intern(r=0.850980,g=0.850980,b=0.850980) gray86 = _intern(r=0.858824,g=0.858824,b=0.858824) gray87 = _intern(r=0.870588,g=0.870588,b=0.870588) gray88 = _intern(r=0.878431,g=0.878431,b=0.878431) gray89 = _intern(r=0.890196,g=0.890196,b=0.890196) gray90 = _intern(r=0.898039,g=0.898039,b=0.898039) gray91 = _intern(r=0.909804,g=0.909804,b=0.909804) gray92 = _intern(r=0.921569,g=0.921569,b=0.921569) gray93 = _intern(r=0.929412,g=0.929412,b=0.929412) gray94 = _intern(r=0.941176,g=0.941176,b=0.941176) gray95 = _intern(r=0.949020,g=0.949020,b=0.949020) gray96 = _intern(r=0.960784,g=0.960784,b=0.960784) gray97 = _intern(r=0.968627,g=0.968627,b=0.968627) gray98 = _intern(r=0.980392,g=0.980392,b=0.980392) gray99 = _intern(r=0.988235,g=0.988235,b=0.988235) gray100 = _intern(r=1.000000,g=1.000000,b=1.000000) darkgray = _intern(r=0.662745,g=0.662745,b=0.662745) darkblue = _intern(r=0.000000,g=0.000000,b=0.545098) darkcyan = _intern(r=0.000000,g=0.545098,b=0.545098) darkmagenta = _intern(r=0.545098,g=0.000000,b=0.545098) darkred = _intern(r=0.545098,g=0.000000,b=0.000000) lightgreen = _intern(r=0.564706,g=0.933333,b=0.564706) default = black _name_table = None def name_table(): global _name_table if not _name_table: _name_table = pychart_util.symbol_lookup_table(globals(), standards) return _name_table PyChart-1.39/pychart/line_plot.py0000644000175000017500000001503410354321374020472 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import tick_mark import line_style import pychart_util import error_bar import chart_object import legend import object_set import line_plot_doc import theme from pychart_types import * from types import * default_width = 1.2 line_style_itr = None _keys = { 'data' : (AnyType, None, pychart_util.data_desc), 'label': (StringType, '???', pychart_util.label_desc), 'data_label_offset': (CoordType, (0, 5), """The location of data labels relative to the sample point. Meaningful only when data_label_format != None."""), 'data_label_format': (FormatType, None, """The format string for the label printed beside a sample point. It can be a `printf' style format string, or a two-parameter function that takes the (x, y) values and returns a string. """ + pychart_util.string_desc), 'xcol' : (IntType, 0, pychart_util.xcol_desc), 'ycol': (IntType, 1, pychart_util.ycol_desc), 'y_error_minus_col': (IntType, 2, """The column (within "data") from which the depth of the errorbar is extracted. Meaningful only when error_bar != None. <>"""), 'y_error_plus_col': (IntType, -1, """The column (within "data") from which the height of the errorbar is extracted. Meaningful only when error_bar != None. <>"""), 'y_qerror_minus_col': (IntType, -1, '<>'), 'y_qerror_plus_col': (IntType, -1, '<>'), 'line_style': (line_style.T, lambda: line_style_itr.next(), pychart_util.line_desc, "By default, a style is picked from standard styles round-robin. <>"), 'tick_mark': (tick_mark.T, None, pychart_util.tick_mark_desc), 'error_bar': (error_bar.T, None, 'The style of the error bar. <>'), } class T(chart_object.T): __doc__ = line_plot_doc.doc keys = _keys def check_integrity(self): assert chart_object.T.check_integrity(self) ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def get_data_range(self, which): if which == 'X': return pychart_util.get_data_range(self.data, self.xcol) else: return pychart_util.get_data_range(self.data, self.ycol) def get_legend_entry(self): if self.label: line_style = self.line_style if not line_style and self.error_bar: line_style = getattr(self.error_bar, 'line_style', None) or \ getattr(self.error_bar, 'hline_style', None) or \ getattr(self.error_bar, 'vline_style', None) if not line_style: raise Exception, 'Line plot has label, but an empty line style and error bar.' return legend.Entry(line_style=line_style, tick_mark=self.tick_mark, fill_style=None, label=self.label) return None def draw(self, ar, can): # Draw the line clipbox = theme.adjust_bounding_box([ar.loc[0], ar.loc[1], ar.loc[0] + ar.size[0], ar.loc[1] + ar.size[1]]); can.clip(clipbox[0],clipbox[1],clipbox[2],clipbox[3]) if self.line_style: points = [] for pair in self.data: yval = pychart_util.get_sample_val(pair, self.ycol) xval = pair[self.xcol] if None not in (xval, yval): points.append((ar.x_pos(xval), ar.y_pos(yval))) can.lines(self.line_style, points) can.endclip() # Draw tick marks and error bars can.clip(ar.loc[0] - 10, ar.loc[1] - 10, ar.loc[0] + ar.size[0] + 10, ar.loc[1] + ar.size[1] + 10) for pair in self.data: x = pair[self.xcol] y = pychart_util.get_sample_val(pair, self.ycol) if None in (x, y): continue x_pos = ar.x_pos(x) y_pos = ar.y_pos(y) if self.error_bar: plus = pair[self.y_error_plus_col or self.y_error_minus_col] minus = pair[self.y_error_minus_col or self.y_error_plus_col] if self.y_qerror_minus_col or self.y_qerror_plus_col: q_plus = pair[self.y_qerror_plus_col or self.y_qerror_minus_col] q_minus = pair[self.y_qerror_minus_col or self.y_qerror_plus_col] if None not in (minus,plus,q_minus,q_plus): self.error_bar.draw(can, (x_pos, y_pos), ar.y_pos(y - minus), ar.y_pos(y + plus), ar.y_pos(y - q_minus), ar.y_pos(y + q_plus)) else: if None not in (minus,plus): #PDS self.error_bar.draw(can, (x_pos, y_pos), ar.y_pos(y - minus), ar.y_pos(y + plus)) if self.tick_mark: self.tick_mark.draw(can, x_pos, y_pos) if self.data_label_format: can.show(x_pos + self.data_label_offset[0], y_pos + self.data_label_offset[1], '/hC' + pychart_util.apply_format(self.data_label_format, (x, y), 1)) can.endclip() def init(): global line_style_itr line_styles = object_set.T() for org_style in line_style.standards.list(): style = line_style.T(width = default_width, color = org_style.color, dash = org_style.dash) line_styles.add(style) line_style_itr = line_styles.iterate() theme.add_reinitialization_hook(init) PyChart-1.39/pychart/bar_plot_doc.py0000644000175000017500000000006710354321374021134 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/font.py0000644000175000017500000003775210352115326017462 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import color import string import pychart_util import re import theme import afm.dir __doc__ = """The module for manipulating texts and their attributes. Pychart supports extensive sets of attributes in texts. All attributes are specified via "escape sequences", starting from letter "/". For example, the below examples draws string "Hello" using a 12-point font at 60-degree angle: /12/a60{}Hello List of attributes: /hA Specifies horizontal alignment of the text. A is one of L (left alignment), R (right alignment), or C (center alignment). /vA Specifies vertical alignment of the text. A is one of "B" (bottom), "T" (top), " M" (middle). /F{FONT} Switch to FONT font family. /T Shorthand of /F{Times-Roman}. /H Shorthand of /F{Helvetica}. /C Shorthand of /F{Courier}. /B Shorthand of /F{Bookman-Demi}. /A Shorthand of /F{AvantGarde-Book}. /P Shorthand of /F{Palatino}. /S Shorthand of /F{Symbol}. /b Switch to bold typeface. /i Switch to italic typeface. /o Switch to oblique typeface. /DD Set font size to DD points. /20{}2001 space odyssey! /cDD Set gray-scale to 0.DD. Gray-scale of 00 means black, 99 means white. //, /{, /} Display `/', `{', or `}'. { ... } Limit the effect of escape sequences. For example, the below example draws "Foo" at 12pt, "Bar" at 8pt, and "Baz" at 12pt. /12Foo{/8Bar}Baz \n Break the line. """ # List of fonts for which their absence have been already warned. _undefined_font_warned = {} class FontException(Exception): def __init__(self, msg, str): self.__msg = msg self.__str = str def __str__(self): return """%s (got "%s"). Write "//". "/{", "/}" to display "/", "{", "}", respectively.""" % \ (self.__msg, self.__str) def _intern_afm(font, text): global _undefined_font_warned r = afm.dir.afm.get(font, None) if r: return r font2 = _font_aliases.get(font, None) if font2: r = afm.dir.afm.get(font2, None) if r: return r try: exec("import pychart.afm.%s" % re.sub("-", "_", font)) return afm.dir.afm[font] except: if not font2 and not _undefined_font_warned.has_key(font): pychart_util.warn('Warning: unknown font "%s" while parsing "%s"' % (font, text)) _undefined_font_warned[font] = 1 if font2: try: exec('import pychart.afm.%s' % re.sub('-', '_', font2)) return afm.dir.afm[font2] except: if not _undefined_font_warned.has_key(font): pychart_util.warn('Warning: unknown font "%s" while parsing "%s"' % (font, text)) _undefined_font_warned[font] = 1 return None def line_width(font, size, text): table = _intern_afm(font, text) if not table: return 0 width = 0 for ch in text: code = ord(ch) if code < len(table): width += table[code] else: # Invalid char. Make up a number. width += table[0] width = float(width) * size / 1000.0 return width _font_family_map = {'T': 'Times', 'H': 'Helvetica', 'C': 'Courier', 'N': 'Helvetica-Narrow', 'B': 'Bookman-Demi', 'A': 'AvantGarde-Book', 'P': 'Palatino', 'S': 'Symbol'} # Aliases for ghostscript font names. _font_aliases = { 'Bookman-Demi': 'URWBookmanL-DemiBold%I', 'Bookman-DemiItalic': 'URWBookmanL-DemiBoldItal', 'Bookman-Demi-Italic': 'URWBookmanL-DemiBoldItal', 'Bookman-Light': 'URWBookmanL-Ligh', 'Bookman-LightItalic': 'URWBookmanL-LighItal', 'Bookman-Light-Italic': 'URWBookmanL-LighItal', 'Courier': 'NimbusMonL-Regu', 'Courier-Oblique': 'NimbusMonL-ReguObli', 'Courier-Bold': 'NimbusMonL-Bold', 'Courier-BoldOblique': 'NimbusMonL-BoldObli', 'AvantGarde-Book': 'URWGothicL-Book', 'AvantGarde-BookOblique': 'URWGothicL-BookObli', 'AvantGarde-Book-Oblique': 'URWGothicL-BookObli', 'AvantGarde-Demi': 'URWGothicL-Demi', 'AvantGarde-DemiOblique': 'URWGothicL-DemiObli', 'AvantGarde-Demi-Oblique': 'URWGothicL-DemiObli', 'Helvetica': 'NimbusSanL-Regu', 'Helvetica-Oblique': 'NimbusSanL-ReguItal', 'Helvetica-Bold': 'NimbusSanL-Bold', 'Helvetica-BoldOblique': 'NimbusSanL-BoldItal', 'Helvetica-Narrow': 'NimbusSanL-ReguCond', 'Helvetica-Narrow-Oblique': 'NimbusSanL-ReguCondItal', 'Helvetica-Narrow-Bold': 'NimbusSanL-BoldCond', 'Helvetica-Narrow-BoldOblique': 'NimbusSanL-BoldCondItal', 'Palatino-Roman': 'URWPalladioL-Roma', 'Palatino': 'URWPalladioL-Roma', 'Palatino-Italic': 'URWPalladioL-Ital', 'Palatino-Bold': 'URWPalladioL-Bold', 'Palatino-BoldItalic': 'URWPalladioL-BoldItal', 'NewCenturySchlbk-Roman': 'CenturySchL-Roma', 'NewCenturySchlbk': 'CenturySchL-Roma', 'NewCenturySchlbk-Italic': 'CenturySchL-Ital', 'NewCenturySchlbk-Bold': 'CenturySchL-Bold', 'NewCenturySchlbk-BoldItalic': 'CenturySchL-BoldItal', 'Times-Roman': 'NimbusRomNo9L-Regu', 'Times': 'NimbusRomNo9L-Regu', 'Times-Italic': 'NimbusRomNo9L-ReguItal', 'Times-Bold': 'NimbusRomNo9L-Medi', 'Times-BoldItalic': 'NimbusRomNo9L-MediItal', 'Symbol': 'StandardSymL', 'ZapfChancery-MediumItalic': 'URWChanceryL-MediItal', 'ZapfChancery-Medium-Italic': 'URWChanceryL-MediItal', 'ZapfDingbats': 'Dingbats' } class text_state: def copy(self): ts = text_state() ts.family = self.family ts.modifiers = list(self.modifiers) ts.size = self.size ts.line_height = self.line_height ts.color = self.color ts.halign = self.halign ts.valign = self.valign ts.angle = self.angle return ts def __init__(self): self.family = theme.default_font_family self.modifiers = [] # 'b' for bold, 'i' for italic, 'o' for oblique. self.size = theme.default_font_size self.line_height = theme.default_line_height or theme.default_font_size self.color = color.default self.halign = theme.default_font_halign self.valign = theme.default_font_valign self.angle = theme.default_font_angle class text_iterator: def __init__(self, s): self.str = unicode(s) self.i = 0 self.ts = text_state() self.stack = [] def reset(self, s): self.str = unicode(s) self.i = 0 def __return_state(self, ts, str): font_name = ts.family if ts.modifiers != []: is_bold = 0 if 'b' in ts.modifiers: is_bold = 1 font_name += '-Bold' if 'o' in ts.modifiers: if not is_bold: font_name += '-' font_name += 'Oblique' elif 'i' in ts.modifiers: if not is_bold: font_name += '-' font_name += 'Italic' elif font_name in ('Palatino', 'Times', 'NewCenturySchlbk'): font_name += '-Roman' return (font_name, ts.size, ts.line_height, ts.color, ts.halign, ts.valign, ts.angle, str) def __parse_float(self): istart = self.i while self.i < len(self.str) and self.str[self.i] in string.digits or self.str[self.i] == '.': self.i += 1 return float(self.str[istart:self.i]) def __parse_int(self): istart = self.i while self.i < len(self.str) and \ (self.str[self.i] in string.digits or self.str[self.i] == '-'): self.i += 1 return int(self.str[istart:self.i]) def next(self): "Get the next text segment. Return an 8-element array: (FONTNAME, SIZE, LINEHEIGHT, COLOR, H_ALIGN, V_ALIGN, ANGLE, STR." l = [] changed = 0 self.old_state = self.ts.copy() while self.i < len(self.str): if self.str[self.i] == '/': self.i = self.i+1 ch = self.str[self.i] self.i = self.i+1 self.old_state = self.ts.copy() if ch == '/' or ch == '{' or ch == '}': l.append(ch) elif _font_family_map.has_key(ch): self.ts.family = _font_family_map[ch] changed = 1 elif ch == 'F': # /F{font-family} if self.str[self.i] != '{': raise FontException('"{" must follow /F', self.str) self.i += 1 istart = self.i while self.str[self.i] != '}': self.i += 1 if self.i >= len(self.str): raise FontException('Expecting "/F{...}"', self.str) self.ts.family = self.str[istart:self.i] self.i += 1 changed = 1 elif ch in string.digits: self.i -= 1 self.ts.size = self.__parse_int() self.ts.line_height = self.ts.size changed = 1 elif ch == 'l': self.ts.line_height = self.__parse_int() changed = 1 elif ch == 'b': self.ts.modifiers.append('b') changed = 1 elif ch == 'i': self.ts.modifiers.append('i') changed = 1 elif ch == 'o': self.ts.modifiers.append('q') changed = 1 elif ch == 'c': self.ts.color = color.gray_scale(self.__parse_float()) elif ch == 'v': if self.str[self.i] not in 'BTM': raise FontException('Undefined escape sequence "/v%c"' % self.str[self.i], self.str) self.ts.valign = self.str[self.i] self.i += 1 changed = 1 elif ch == 'h': if self.str[self.i] not in 'LRC': raise FontException('Undefined escape sequence "/h%c"' % self.str[self.i], self.str) self.ts.halign = self.str[self.i] self.i += 1 changed = 1 elif ch == 'a': self.ts.angle = self.__parse_int() changed = 1 else: raise FontException('Undefined escape sequence: "/%c"' % ch, self.str) elif self.str[self.i] == '{': self.stack.append(self.ts.copy()) self.i += 1 elif self.str[self.i] == '}': if len(self.stack) == 0: raise FontError('Unmatched "}"', self.str) self.ts = self.stack[-1] del self.stack[-1] self.i += 1 changed = 1 else: l.append(self.str[self.i]) self.i += 1 if changed and len(l) > 0: return self.__return_state(self.old_state, ''.join(l)) else: # font change in the beginning of the sequence doesn't count. self.old_state = self.ts.copy() changed = 0 if len(l) > 0: return self.__return_state(self.old_state, ''.join(l)) else: return None # # def unaligned_get_dimension(text): """Return the bounding box of the text, assuming that the left-bottom corner of the first letter of the text is at (0, 0). This procedure ignores /h, /v, and /a directives when calculating the BB; it just returns the alignment specifiers as a part of the return value. The return value is a tuple (width, height, halign, valign, angle).""" xmax = 0 ymax = 0 ymax = 0 angle = None halign = None valign = None itr = text_iterator(None) for line in unicode(text).split('\n'): cur_height = 0 cur_width = 0 itr.reset(line) while 1: elem = itr.next() if not elem: break (font, size, line_height, color, new_h, new_v, new_a, chunk) = elem if halign != None and new_h != halign: raise FontException('Only one "/h" can appear in a string.', unicode(text)) if valign != None and new_v != valign: raise FontException('Only one "/v" can appear in a string.', unicode(text)) if angle != None and new_a != angle: raise FontException('Only one "/a" can appear in a string.', unicode(text)) halign = new_h valign = new_v angle = new_a cur_width += line_width(font, size, chunk) cur_height = max(cur_height, line_height) xmax = max(cur_width, xmax) ymax += cur_height return (xmax, ymax, halign or theme.default_font_halign, valign or theme.default_font_valign, angle or theme.default_font_angle) def get_dimension(text): """Return the bounding box of the , assuming that the left-bottom corner of the first letter of the text is at (0, 0). This procedure ignores /h, /v, and /a directives when calculating the boundingbox; it just returns the alignment specifiers as a part of the return value. The return value is a tuple (width, height, halign, valign, angle).""" (xmax, ymax, halign, valign, angle) = unaligned_get_dimension(text) xmin = ymin = 0 if halign == 'C': xmin = -xmax / 2.0 xmax = xmax / 2.0 elif halign == 'R': xmin = -xmax xmax = 0 if valign == 'M': ymin = -ymax / 2.0 ymax = ymax / 2.0 elif valign == 'T': ymin = -ymax ymax = 0 if angle != 0: (x0, y0) = pychart_util.rotate(xmin, ymin, angle) (x1, y1) = pychart_util.rotate(xmax, ymin, angle) (x2, y2) = pychart_util.rotate(xmin, ymax, angle) (x3, y3) = pychart_util.rotate(xmax, ymax, angle) xmax = max(x0, x1, x2, x3) xmin = min(x0, x1, x2, x3) ymax = max(y0, y1, y2, y3) ymin = min(y0, y1, y2, y3) return (xmin, xmax, ymin, ymax) return (xmin, xmax, ymin, ymax) def unaligned_text_width(text): x = unaligned_get_dimension(text) return x[0] def text_width(text): """Return the width of the in points.""" (xmin, xmax, d1, d2) = get_dimension(text) return xmax-xmin def unaligned_text_height(text): x = unaligned_get_dimension(text) return x[1] def text_height(text): """Return the total height of the and the length from the base point to the top of the text box.""" (d1, d2, ymin, ymax) = get_dimension(text) return (ymax-ymin, ymax) def get_align(text): "Return (halign, valign, angle) of the ." (x1, x2, h, v, a) = unaligned_get_dimension(text) return (h, v, a) def quotemeta(text): """Quote letters with special meanings in pychart so that will display as-is when passed to canvas.show(). >>> font.quotemeta("foo/bar") "foo//bar" """ text = re.sub(r'/', '//', text) text = re.sub(r'\\{', '/{', text) text = re.sub(r'\\}', '/}', text) return text PyChart-1.39/pychart/text_box_doc.py0000644000175000017500000000006710354321374021166 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/coord.py0000644000175000017500000000423210354321345017607 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # class T(object): def get_canvas_pos(self, size, val, min, max): """ Compute the screen location at which a sample value would be drawn. ``size`` is the width or height of the chart, in points. ``val`` is the sample value. ``min`` and ``max`` are the minimum and maximum sample values that are to be displayed over the length of ``size``. For example, suppose the width of a chart is 200 points and the minimum and maximum X values in the sample data are 100 and 150 respectively. When Pychart wants to draw a sample point at the X value of 120, it will call area.T.x_coord.get_canvas_pos(size = 200, val = 120, min = 100, max = 150). """ raise Exception def get_tics(self, min, max, interval): """Generate the list of places for drawing tick marks.""" raise Exception def get_min_max(self, min, max, interval): """Compute the min/max values to be displayed in the chart. Parameters ``min`` and ``max`` are the minimum and maximum values of the sample data passed to the plots. Parameter ``interval`` is the value of attribute area.T.x_grid_interval (or y_grid_interval). It is None if these attributes are non-specified. This method must return tuple (dmin, dmax, dinterval). dmin should be ``min`` rounded down to some good number. dmax should be ``max`` rounded up to some good number. dinterval should be ``interval`` if it is non-None. Otherwise, the method must compute some good value. """ raise Exception PyChart-1.39/pychart/theme.py0000644000175000017500000001707310354321416017611 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import os import re import getopt import pychart_util __doc__ = """This module is defines variables for changing the looks of charts. All the variables can be changed either via environment variable PYCHART_OPTIONS or via the command-line options. The value of PYCHART_OPTIONS should be a sequence of var=val separated by space. Below is an example, which tells Pychart to write to file foo.pdf and use Times-Roman as the default font. PYCHART_OPTIONS="output=foo.pdf font-family=Times" The summary of attributes that can be set via PYCHART_OPTIONS follows: output=FILENAME (default: stdout) Set the output file name. format=[ps|pdf|pdf-uncompressed|png|x11|svg] (default: ps) Set the output file format. font-family=NAME (default: Helvetica) Set the default font to be used by texts. font-size=N (default: 9) Set the default font to be used by texts. line-width=X (default: 0.4) Set the default line width, in points. See also pychart.line_style. scale=X (default: 1.0) Set the scaling factor. The default is 1.0. color=[yes|no] (default: no) If yes, Pychart colorizes default object attributes. You can also set these variables by calling theme.get_options. """ use_color = 0 scale_factor = 1 output_format = None # "ps", "pdf", "png", "x11", or "svg" compress_output = 1 output_file = "" default_font_family = "Helvetica" default_font_size = 9 default_line_height = None default_font_halign = "L" default_font_valign = "B" default_font_angle = 0 default_line_width = 0.4 debug_level = 1 delta_bounding_box = [-3, -3, 3, 3] bounding_box = {} creator = None creation_date = None author = None title = None aux_comments = None def parse_yesno(str): if str in ("yes", "true", "1"): return 1 else: return 0 def parse_bounding_box(arg): global delta_bounding_box, bounding_box l = arg.split(",") if len(l) != 4: raise ValueError, "Need to specify margin=LEFT,BOTTOM,RIGHT,TOP" for i in range(0, 4): val = l[i].strip() if val[0] == '+': delta_bounding_box[i] = int(val[1:]) elif val[0] == '-': delta_bounding_box[i] = int(val[1:]) else: bounding_box[i] = int(val) def adjust_bounding_box(bbox): """Adjust the bounding box as specified by user. Returns the adjusted bounding box. - bbox: Bounding box computed from the canvas drawings. It must be a four-tuple of numbers. """ for i in range(0, 4): if bounding_box.has_key(i): bbox[i] = bounding_box[i] else: bbox[i] += delta_bounding_box[i] return bbox def parse_option(opt, arg): global use_color, scale_factor, margin global output_format, output_file, compress_output global default_font_family, default_font_size global default_line_height global default_line_width, debug_level global creator, creation_date, author, title, aux_comments if opt == "format": if arg in ("ps", "eps"): output_format = "ps" elif arg == "png": output_format = "png" elif arg == "svg": output_format = "svg" elif arg == "x11": output_format = "x11" elif arg == "pdf-uncompressed": output_format = "pdf" compress_output = 0 elif arg in ("pdf-compressed", "pdf"): output_format = "pdf" compress_output = 1 else: raise ValueError, "Unknown output option: " + str(arg) elif opt == "output": output_file = arg elif opt == "color": use_color = 1 elif opt == "scale": scale_factor = float(arg) elif opt == "bbox": parse_bounding_box(arg) elif opt == "font-family": default_font_family = arg elif opt == "font-size": default_font_size = float(arg) default_line_height = float(arg) elif opt == "line-width": default_line_width = float(arg) elif opt == "debug-level": debug_level = int(arg) elif opt == "author": author = arg elif opt == "creator": creator = arg elif opt == "creation_date": creation_date = arg elif opt == "title": title =arg elif opt == "aux_comments": aux_comments = arg else: raise getopt.GetoptError, "Unknown option: " + opt + " " + arg if os.environ.has_key("PYCHART_OPTIONS"): for opt in os.environ["PYCHART_OPTIONS"].split(): opt, arg = opt.split("=") parse_option(opt, arg) hooks = [] def add_reinitialization_hook(proc): global hooks hooks.append(proc) proc() def usage(): print "Usage: %s [options..]" % sys.argv[0] print """ --scale=X: Set the scaling factor to X (default: 1.0). --format=[ps|png|pdf|x11|svg]: Set the output format (default: ps). --font-family=NAME: Set the default font family (default: Helvetica). --font-size=NAME: Set the default font size (default: 9pts). --line-width=NAME: Set the default line width (default: 0.4). --debug-level=N: Set the messaging verbosity (default: 0). --bbox=LEFT,BOTTOM,RIGHT,TOP: Specifies the amount of space (in PS points) to be left in the edges of the picture (default: -1,-1,+1,+1). """ def reinitialize(): """This procedure must be called after setting variables in the |theme| module. This procedure propagates the new values of the theme variables to other modules that depend on their values.""" for proc in hooks: proc() def get_options(argv = None): """This procedure takes a list of command line arguments in and parses options. It returns the non-parsed portion of . Parameter can be omitted, in which case its value defaults to |sys.argv[1:]|. The options supported are: "|--format=[ps,png,pdf,x11,svg]|", "|--output=|", "|--color=[yes,no]|" "|--scale=|", "|--font-family=|", "|--font-size=|", "|--line-width=|", "|--debug-level=|", "|bbox=|". The below code shows an example. #!/usr/bin/python from pychart import * args = theme.get_options() ar = area.T(...) ... """ if argv == None: argv = sys.argv[1:] try: opts, args = getopt.getopt(argv, "d:co:f:", ["format=", "output=", "color=", "scale=", "font-family=", "font-size=", "line-width=", "debug-level=", "title=", "author=", "creation_date=", "creator=", "bbox="]) except getopt.GetoptError, arg: print arg usage() raise getopt.GetoptError for opt, arg in opts: if opt == "-d": parse_option("debug-level", arg) elif opt == "-c": parse_option("color", None) elif opt == "-o": parse_option("output", arg) elif opt == "-f": parse_option("format", arg) else: parse_option(opt[2:], arg) reinitialize() return args PyChart-1.39/pychart/bar_plot.py0000644000175000017500000002640710354321374020315 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import line_style import fill_style import pychart_util import chart_object import legend import error_bar import bar_plot_doc import theme from types import * from pychart_types import * fill_styles = None _keys = { "direction" : (StringType, "vertical", """The direction the growth of the bars. The value is either 'horizontal' or 'vertical'."""), "data" : (AnyType, None, pychart_util.data_desc), "data_label_offset": (CoordType, (0, 5), "The location of data labels relative to the sample point. See also attribute data_label_format."), "data_label_format": (FormatType, None, """The format string for the label displayed besides each bar. It can be a `printf' style format string, or a two-parameter function that takes (x,y) values and returns a string. """ + pychart_util.string_desc), "label": (StringType, "???", pychart_util.label_desc), "bcol" : (IntType, 0, """Specifies the column from which base values (i.e., X values when attribute "direction" is "vertical", Y values otherwise) are extracted. The combination of "data", "bcol", and "hcol" attributes defines the set of boxes drawn by this chart. See the below example: @example d = [[5,10], [7,22], [8,25]] p = bar_plot.T(data = d, bcol = 1, hcol = 2) @end example Here, three bars will be drawn. The X values of the bars will be 5, 7, and 8. The Y values of the bars will be 10, 22, and 25, respectively. (In practice, because the values of bcol and hcol defaults to 1 and 2, you can write the above example just as "p = bar_plot.T(data = d)". """), "hcol": (IntType, 1, """The column from which the height of each bar is extracted. See also the description of the 'bcol' attribute."""), "line_style": (line_style.T, line_style.default, "The style of the outer frame of each box."), "fill_style": (fill_style.T, lambda: fill_styles.next(), "Defines the fill style of each box.", "The style is picked from standard styles round-robin."), "legend_line_style": (line_style.T, None, """The line style used to draw a legend entry. Usually, the value is None, meaning that the value of "line_style" attribute is used."""), "legend_fill_style": (fill_style.T, None, """The fill style used to draw a legend entry. Usually, the value is None, meaning that the value of "fill_style" attribute is used."""), "cluster": (TupleType, (0, 1), """This attribute is used to cluster multiple bar plots side by side in a single chart. The value should be a tuple of two integers. The second value should be equal to the total number of bar plots in the chart. The first value should be the relative position of this chart; 0 places this chart the leftmost, and N-1 (where N is the 2nd value of this attribute) places this chart the rightmost. Consider the below example: @example a = area.T(...) p1 = bar_plot.T(data = [[1,20][2,30]], cluster=(0,2)) p2 = bar_plot.T(data = [[1,25],[2,10]], cluster=(1,2)) a.add_plot(p1, p2) a.draw() @end example In this example, one group of bars will be drawn side-by-side at position x=1, one with height 20, the other with height 25. The other two bars will be drawn side by side at position x=2, one with height 30 and the other with height 10. """), "width": (UnitType, 5, """Width of each box. @cindex width!- of bar plot @cindex size!- of bar plot """), "cluster_sep": (UnitType, 0, """The separation between clustered boxes."""), "stack_on": (AnyType, None, "The value must be either None or bar_plot.T. If not None, bars of this plot are stacked on top of another bar plot."), "error_minus_col": (IntType, -1, """Specifies the column from which the depth of the errorbar is extracted. This attribute is meaningful only when error_bar != None. """), "qerror_minus_col": (IntType, -1, """The depth of the "quartile" errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None. """), "error_plus_col": (IntType, -1, """The depth of the errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None."""), "qerror_plus_col": (IntType, -1, """The depth of the "quartile" errorbar is extracted from this column in data. This attribute is meaningful only when error_bar != None."""), "error_bar": (error_bar.T, None, "Specifies the style of the error bar. <>"), "_abs_data" : (ListType, None, "Used only internally."), } def find_bar_plot(ar, nth): "Find the NTH barplot of the cluster in area AR." for plot in ar.plots(): if isinstance(plot, T) and plot.cluster[0] == nth: return plot raise Exception, "The %dth bar plot in the cluster not found." % nth class T(chart_object.T): __doc__ = bar_plot_doc.doc keys = _keys def check_integrity(self): chart_object.T.check_integrity(self) self.compute_abs_data() return True def compute_abs_data(self): if self._abs_data != None: return if self.stack_on == None: self._abs_data = self.data else: n = [] for pair in self.data: self.stack_on.compute_abs_data() newpair = list(pair[:]) newpair[self.hcol] = self.stack_on.get_value(newpair[self.bcol]) + pair[self.hcol] n.append(newpair) self._abs_data = n ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def get_value(self, bval): for pair in self._abs_data: if pair[self.bcol] == bval: return pair[self.hcol] raise ValueError, str(bval) + ": can't find the xval" def get_data_range(self, which): if self.direction == 'vertical': if which == 'X': return pychart_util.get_data_range(self._abs_data, self.bcol) else: return pychart_util.get_data_range(self._abs_data, self.hcol) else: assert self.direction == 'horizontal' if which == 'Y': return pychart_util.get_data_range(self._abs_data, self.bcol) else: return pychart_util.get_data_range(self._abs_data, self.hcol) def get_bar_width(self, ar, nth): off = 0 for i in range(0, nth): plot = find_bar_plot(ar, i) off += plot.width + plot.cluster_sep return off def draw_vertical(self, ar, can): for pair in self.data: xval = pair[self.bcol] yval = pychart_util.get_sample_val(pair, self.hcol) if None in (xval, yval): continue ybot = 0 if self.stack_on: ybot = self.stack_on.get_value(xval) yval += ybot totalWidth = self.get_bar_width(ar, self.cluster[1]) firstX = ar.x_pos(xval) - totalWidth/2.0 thisX = firstX + self.get_bar_width(ar, self.cluster[0]) can.rectangle(self.line_style, self.fill_style, thisX, ar.y_pos(ybot), thisX+self.width, ar.y_pos(yval)) if self.error_bar: plus = pair[self.error_minus_col or self.error_plus_col] minus = pair[self.error_plus_col or self.error_minus_col] qplus = 0 qminus = 0 if self.qerror_minus_col or self.qerror_plus_col: qplus = pair[self.qerror_minus_col or self.qerror_plus_col] qminus = pair[self.qerror_plus_col or self.qerror_minus_col] if None not in (plus, minus, qplus, qminus): self.error_bar.draw(can, (thisX+self.width/2.0, ar.y_pos(yval)), ar.y_pos(yval - minus), ar.y_pos(yval + plus), ar.y_pos(yval - qminus), ar.y_pos(yval + qplus)) if self.data_label_format: can.show(thisX + self.width/2.0 + self.data_label_offset[0], ar.y_pos(yval) + self.data_label_offset[1], "/hC" + pychart_util.apply_format(self.data_label_format, (pair[self.bcol], pair[self.hcol]), 1)) def draw_horizontal(self, ar, can): for pair in self.data: yval = pair[self.bcol] xval = pychart_util.get_sample_val(pair, self.hcol) if None in (xval, yval): continue xbot = 0 if self.stack_on: xbot = self.stack_on.get_value(yval) xval += xbot totalWidth = self.get_bar_width(ar, self.cluster[1]) firstY = ar.y_pos(yval) - totalWidth/2.0 thisY = firstY + self.get_bar_width(ar, self.cluster[0]) can.rectangle(self.line_style, self.fill_style, ar.x_pos(xbot), thisY, ar.x_pos(xval), thisY+self.width) if self.data_label_format: can.show(ar.x_pos(xval) + self.data_label_offset[0], thisY + self.width/2.0 + self.data_label_offset[1], "/vM/hL" + pychart_util.apply_format(self.data_label_format, (pair[self.bcol], pair[self.hcol]), 1)) def get_legend_entry(self): if self.label: return legend.Entry(line_style=(self.legend_line_style or self.line_style), fill_style=(self.legend_fill_style or self.fill_style), label=self.label) return None def draw(self, ar, can): assert self.check_integrity() can.clip(ar.loc[0], ar.loc[1], ar.loc[0] + ar.size[0], ar.loc[1] + ar.size[1]) if self.direction == "vertical": self.draw_vertical(ar, can) else: self.draw_horizontal(ar, can) can.endclip() def init(): global fill_styles fill_styles = fill_style.standards.iterate() theme.add_reinitialization_hook(init) PyChart-1.39/pychart/pdfcanvas.py0000644000175000017500000002312710352115070020444 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import pychart_util import re import math import theme import os import basecanvas from scaling import * try: import zlib _zlib_available_p = 1 except: _zlib_available_p = 0 class pdf_stream(object): def __init__(self, fp): self.fp = fp self.off = 0 def write(self, str): self.fp.write(str) self.off += len(str) def tell(self): return self.off def to_radian(deg): return deg*2*math.pi / 360.0 class T(basecanvas.T): def __init__(self, fname, compress_p_): basecanvas.T.__init__(self) self.__out_fname = fname self.__reset_context() self.__next_obj_id = 1 self.__next_font_id = 1 self.__obj_offsets = {} # Maps font name -> integer font ID. self.__registered_fonts = {} self.__lines = [] self.__nr_gsave = 0 if compress_p_ and not _zlib_available_p: pychart_util.warn("Zlib not available. Compression request ignored.\n") compress_p_ = 0 self.__compress_p = compress_p_ def __register_font(self, name): "Assign an ID to the font NAME. Return its ID." if not self.__registered_fonts.has_key(name): self.__registered_fonts[name] = self.__next_font_id self.__next_font_id += 1 return self.__registered_fonts[name] def __define_obj(self, fp, str): obj_id = self.__next_obj_id self.__next_obj_id += 1 self.__obj_offsets[obj_id] = fp.tell() fp.write("%d 0 obj\n%s\nendobj\n" % (obj_id, str)) return obj_id def __define_stream_obj(self, fp, s): if self.__compress_p: p = zlib.compress(s) return self.__define_obj(fp, "<>\nstream\n%sendstream" % (len(p), p)) else: return self.__define_obj(fp, "<>\nstream\n%s\nendstream" % (len(s), s)) def __define_font_obj(self, fp, name, font_id): obj_id = self.__define_obj(fp, """<>""" % (font_id, name)) return obj_id def __reset_context(self): self.__font_name = None self.__font_size = -1 self.__line_style = None self.__fill_color = None self.__stroke_color = None self.__mtx_pushed = 0 def newpath(self): pass def set_fill_color(self, color): if self.__fill_color == color: return if color.r == color.g and color.r == color.b: self.__write("%f g\n" % (color.r)) self.__write("%f G\n" % (color.r)) else: self.__write("%f %f %f rg\n" % (color.r, color.g, color.b)) self.__write("%f %f %f RG\n" % (color.r, color.g, color.b)) self.__fill_color = color def set_stroke_color(self, color): self.set_fill_color(color) return def __arcsub(self, x, y, radius, start, theta): xcos = math.cos(to_radian(theta)) xsin = math.sin(to_radian(theta)) x0 = radius * xcos y0 = radius * xsin x1 = radius * (4-xcos)/3.0 y1 = radius * (1-xcos)*(xcos-3)/(3*xsin) xx0, xy0 = pychart_util.rotate(x0, y0, start+theta) xx1, xy1 = pychart_util.rotate(x1, -y1, start+theta) xx2, xy2 = pychart_util.rotate(x1, y1, start+theta) self.__write("%f %f %f %f %f %f c\n" % (x+xx1, y+xy1, x+xx2, y+xy2, x+xx0, y+xy0)) def path_arc(self, x, y, radius, ratio, start, end): self.comment("PATHARC %f %f %f %f %f %f\n" % (x, y, radius, ratio, start, end)) step = 10 if radius < 10: step = 20 if radius < 5: step = 30 if ratio != 1.0: self.push_transformation((x, y), (1, ratio), None) deg = start while deg < end: theta = min(step, end-deg) self.__arcsub(x, y, radius, deg, theta/2) deg += theta self.pop_transformation() else: deg = start while deg < end: theta = min(step, end-deg) self.__arcsub(x, y, radius, deg, theta/2) deg += theta self.comment("end PATHARC\n") def text_begin(self): self.__write("BT ") self.__font_name = None self.__font_size = None def text_end(self): self.__write("ET\n") def text_moveto(self, x, y, angle): if angle != None: xcos = math.cos(to_radian(angle)) xsin = math.sin(to_radian(angle)) self.__write("%f %f %f %f %f %f Tm " % (xcos, xsin, -xsin, xcos, x, y)) else: self.__write("1 0 0 1 %f %f Tm " % (x, y)) def text_show(self, font_name, font_size, color, str): if self.__font_name != font_name or self.__font_size != font_size: self.__write("/F%d %d Tf " % (self.__register_font(font_name), font_size)) self.__font_name = font_name self.__font_size = font_size self.set_fill_color(color) self.__write("(%s) Tj " % (str.encode('mac_roman'))) def push_transformation(self, baseloc, scale, angle, in_text = 0): if in_text: op = "Tm" else: op = "cm" self.gsave() if baseloc == None: baseloc = (0,0) if angle != None: radian = to_radian(angle) self.__write("%f %f %f %f %f %f %s\n" % (math.cos(radian), math.sin(radian), -math.sin(radian), math.cos(radian), baseloc[0], baseloc[1], op)) if scale != None: self.__write("%f 0 0 %f %f %f %s\n" % (scale[0], scale[1], baseloc[0], baseloc[1], op)) def pop_transformation(self, in_text = 0): if not in_text: self.grestore() def closepath(self): self.__write("h\n") def clip_sub(self): self.__write("W n\n") def fill(self): self.__write("f n\n") def gsave(self): self.__write("q\n") def grestore(self): self.__write("Q\n") self.__reset_context() def moveto(self, x, y): self.__write('%f %f m ' % (x, y)) def lineto(self, x, y): self.__write("%f %f l\n" % (x, y)) def stroke(self): self.__write("S\n") def set_line_style(self, style): if (self.__line_style == style): pass else: self.set_stroke_color(style.color) self.__write("%f w " % nscale(style.width)) if style.dash != None: self.__write("[%s] 0 d\n" % " ".join(map(str, nscale_seq(style.dash)))) else: self.__write("[] 0 d\n") self.__write("%d j %d J\n" % (style.cap_style, style.join_style)) self.__line_style = style def comment(self, str): if not self.__compress_p: self.__write("%%" + str + "\n") def verbatim(self, str): self.__write(str) def __write(self, str): self.__lines.append(str) def close(self): basecanvas.T.close(self) if self.__lines == []: return _fp, need_close = self.open_output(self.__out_fname) fp = pdf_stream(_fp) fp.write("%PDF-1.2\n") stream_obj_id = self.__define_stream_obj(fp, " ".join(self.__lines)) fontstr = "" for font_name, font_id in self.__registered_fonts.items(): obj_id = self.__define_font_obj(fp, font_name, font_id) fontstr += "/F%d %d 0 R " % (font_id, obj_id) pages_obj_id = self.__define_obj(fp, " <>" % (self.__next_obj_id + 1)) bbox = theme.adjust_bounding_box([xscale(self.__xmin), yscale(self.__ymin), xscale(self.__xmax), yscale(self.__ymax)]) page_obj_id = self.__define_obj(fp, """ <> >> >>""" % (pages_obj_id, stream_obj_id, bbox[0], bbox[1], bbox[2], bbox[3], fontstr)) info_str = "/Producer (%s)\n/CreationDate (%s)" % (self.creator, self.creation_date) if self.title: info_str += "\n/Title (%s)" % (self.title, ) if self.author: info_str += "\n/Author (%s)" % (self.author, ) info_obj_id = self.__define_obj(fp, """<<%s>>""" % info_str) catalog_obj_id = self.__define_obj(fp, """ <>""" % (pages_obj_id)) xref_offset = fp.tell() fp.write("xref\n0 %d\n" % (len(self.__obj_offsets)+1)) fp.write("0000000000 65535 f \n") id = 1 while id <= len(self.__obj_offsets): fp.write("%010d 00000 n \n" % (self.__obj_offsets[id])) id += 1 fp.write("trailer << /Size %d /Root %d 0 R /Info %d 0 R\n>>\n" % (len(self.__obj_offsets)+1, catalog_obj_id, info_obj_id)) fp.write("startxref\n%d\n%%%%EOF\n" % xref_offset) if need_close: _fp.close() PyChart-1.39/pychart/gs_frontend.py0000644000175000017500000000620010354321374021010 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import pychart_util import theme import sys import os import os.path import pscanvas import tempfile import basecanvas from scaling import * def _get_gs_path(): """Guess where the Ghostscript executable is and return its absolute path name.""" path = os.environ.get("PATH", os.defpath) for dir in path.split(os.pathsep): for name in ("gs", "gs.exe", "gswin32c.exe"): g = os.path.join(dir, name) if os.path.exists(g): return g raise Exception, "Ghostscript not found. path=%s" % str(path) class T(pscanvas.T): """This class is a special kind of canvas that runs ghostscript on the generated postscript contents. It is not used stand-alone, but as a component of PNG and X11 display functionality.""" def __write_contents(self, fp): fp.write(pscanvas.preamble_text) for name, id in self.__font_ids.items(): fp.write("/%s {/%s findfont SF} def\n" % (id, name)) fp.write("%d %d translate\n" % (-self.bbox[0], -self.bbox[1])) fp.writelines(self.__output_lines) fp.write("showpage end\n") fp.flush() def close(self): # Don't call pscanvas.T.close, as it creates a # ps file. basecanvas.T.close(self) def start_gs(self, arg): self.bbox = theme.adjust_bounding_box([xscale(self.__xmin), yscale(self.__ymin), xscale(self.__xmax), yscale(self.__ymax)]) gs_path = _get_gs_path() self.pipe_fp = None if self.__output_lines == []: return if sys.platform != "win32" and hasattr(os, "popen"): # UNIX-like systems cmdline = "\"%s\" -q %s -g%dx%d -q >/dev/null 2>&1" % \ (gs_path, arg, self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1]) self.pipe_fp = os.popen(cmdline, "w") self.__write_contents(self.pipe_fp) else: # XXX should use mktemp, but need to support python<=2.2 as well. fname = tempfile.mktemp("xxx") fp = open(fname, "wb") self.__write_contents(fp) fp.close() cmdline = "\"%s\" -q %s -g%dx%d -q <%s >NUL" % \ (gs_path, arg, self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1], fname) os.system(cmdline) os.unlink(fname) def close_gs(self): if self.pipe_fp: self.pipe_fp.close() self.pipe_fp = None PyChart-1.39/pychart/axis_y_doc.py0000644000175000017500000000521710354321345020626 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # doc="""Attributes supported by this class are: minor_tic_len(type:number): The length of minor tick marks. default value=3. tic_label_offset(type:(x,y)): The location where the tick labels is drawn. Relative to the tip of the tick mark. default value=(0, 0). format(type:printf format string): The format string for tick labels. It can be a `printf' style format string, or a single-parameter function that returns a string. See also font. default value=%s. label_offset(type:(x,y) or None): The location where the axis label is drawn. Relative to the left-bottom corner of the axis. default value=(None, None). grid_interval(type:Number or function): When the value is a number, it specifies the interval with which grid lines are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where grid lines are drawn. default value=None. tic_len(type:number): The length of tick lines default value=6. grid_style(type:line_style.T): default value=gray70dash3. tic_interval(type:Number or function): When the value is a number, it specifies the interval with which tick marks are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where tick marks are drawn. default value=None. line_style(type:line_style.T): The style of tick lines. default value=default. label(type:str): The description of the axis. See also font. default value=axis label. minor_tic_interval(type:Number or function): When the value is a number, it specifies the interval with which minor tick marks are drawn. Otherwise, the value must be a function. It must take no argument and return the list of numbers, which specifies the X or Y points where minor tick marks are drawn. default value=None. first_tic_value(type:number): The location of the first tick mark. Defaults to the x_range[0] (or y_range[0]) of the area. default value=None. """ PyChart-1.39/pychart/zap.py0000644000175000017500000000446410354321345017302 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import fill_style import line_style import copy def _draw_zap(can, p1, p2, style, pat): x = copy.deepcopy(p1) x.extend(p2) can.polygon(None, pat, x) can.lines(style, p1) can.lines(style, p2) def zap_horizontally(can, style, pat, x1, y1, x2, y2, xsize, ysize): """Draw a horizontal "zapping" symbol on the canvas that shows that a graph is ripped in the middle. Parameter specifies the style for the zig-zag lines. PAT specifies the pattern with which the area is filled. The symbol is drawn in the rectangle (, ) - (, ). Each "zigzag" has the width , height .""" assert isinstance(style, line_style.T) assert isinstance(pat, fill_style.T) points = [] points2 = [] x = x1 y = y1 while x < x2: points.append((x, y)) points2.append((x, y + (y2-y1))) x += xsize if y == y1: y += ysize else: y -= ysize points2.reverse() _draw_zap(can, points, points2, style, pat) def zap_vertically(can, style, pat, x1, y1, x2, y2, xsize, ysize): """Draw a vertical "zapping" symbol on the canvas that shows that a graph is ripped in the middle. Parameter specifies the style for the zig-zag lines. PAT specifies the pattern with which the area is filled. The symbol is drawn in the rectangle (, ) - (, ). Each "zigzag" has the width , height .""" points = [] points2 = [] x = x1 y = y1 while y < y2: points.append((x, y)) points2.append((x + (x2-x1), y)) y += ysize if x == x1: x += xsize else: x -= xsize points2.reverse() _draw_zap(can, points, points2, style, pat) PyChart-1.39/pychart/area.py0000644000175000017500000002346610354321374017425 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import coord import line_style import legend import axis import chart_object import fill_style import canvas import area_doc import linear_coord import category_coord import theme from pychart_types import * from types import * _dummy_legend = legend.T() def range_doc(t): u = t.upper() return """Specifies the range of %s values that are displayed in the chart. IF the value is None, both the values are computed automatically from the samples. Otherwise, the value must be a tuple of format (MIN, MAX). MIN and MAX must be either None or a number. If None, the value is computed automatically from the samples. For example, if %s_range = (None,5), then the minimum %s value is computed automatically, but the maximum %s value is fixed at 5.""" % (u, t, u, u) _keys = { "loc" : (CoordType, (0,0), """The location of the bottom-left corner of the chart. None means to use the default value. @cindex location (- of chart) """), "size" : (CoordType, (120,110), """The size of the chart-drawing area, excluding axis labels, legends, tick marks, etc. None means to use the default value. @cindex size!- of area """), "bg_style": (fill_style.T, None, "Background fill-pattern."), "border_line_style": (line_style.T, None, "Line style of the outer frame of the chart."), "x_coord": (coord.T, linear_coord.T(), """Set the X coordinate system.""", """A linear coordinate system."""), "y_coord": (coord.T, linear_coord.T(), "Set the Y coordinate system.", """A linear coordinate system."""), "x_range": (CoordType, None, range_doc("x")), "y_range": (CoordType, None, range_doc("y")), "x_axis": (axis.X, None, "The X axis. <>."), "x_axis2": (axis.X, None, """The second X axis. This axis should be non-None either when you want to display plots with two distinct domains or when you just want to display two axes at the top and bottom of the chart. <>"""), "y_axis": (axis.Y, None, "The Y axis. <>."), "y_axis2": (axis.Y, None, """The second Y axis. This axis should be non-None either when you want to display plots with two distinct ranges or when you just want to display two axes at the left and right of the chart. <>"""), "x_grid_style" : (line_style.T, None, """The style of horizontal grid lines. @cindex grid lines"""), "y_grid_style" : (line_style.T, line_style.gray70_dash3, "The style of vertical grid lines."), "x_grid_interval": (IntervalType, None, """The horizontal grid-line interval. A numeric value specifies the interval at which lines are drawn. If value is a function, it takes two arguments, (MIN, MAX), that tells the minimum and maximum values found in the sample data. The function should return a list of values at which lines are drawn."""), "y_grid_interval": (IntervalType, None, "The vertical grid-line interval. See also x_grid_interval"), "x_grid_over_plot": (bool, False, "If True, grid lines are drawn over plots. Otherwise, plots are drawn over grid lines."), "y_grid_over_plot": (IntType, False, "See x_grid_over_plot."), "legend": (legend.T, _dummy_legend, "The legend of the chart.", """a legend is by default displayed in the right-center of the chart. If you don't want to draw a legend, you should explicitly set None to this attribute."""), } class T(chart_object.T): keys = _keys __doc__ = area_doc.doc def __init__(self, **args): chart_object.T.init(self, args) self.__plots = [] ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def x_pos(self, xval): "Return the x position (on the canvas) corresponding to XVAL." off = self.x_coord.get_canvas_pos(self.size[0], xval, self.x_range[0], self.x_range[1]) return self.loc[0] + off def y_pos(self, yval): "Return the y position (on the canvas) corresponding to YVAL." off = self.y_coord.get_canvas_pos(self.size[1], yval, self.y_range[0], self.y_range[1]) return self.loc[1] + off def x_tic_points(self, interval): "Return the list of X values for which tick marks and grid lines are drawn." if type(interval) == FunctionType: return apply(interval, self.x_range) return self.x_coord.get_tics(self.x_range[0], self.x_range[1], interval) def y_tic_points(self, interval): "Return the list of Y values for which tick marks and grid lines are drawn." if type(interval) == FunctionType: return apply(interval, self.y_range) return self.y_coord.get_tics(self.y_range[0], self.y_range[1], interval) def __draw_x_grid_and_axis(self, can): if self.x_grid_style: for i in self.x_tic_points(self.x_grid_interval): x = self.x_pos(i) if x > self.loc[0]: can.line(self.x_grid_style, x, self.loc[1], x, self.loc[1]+self.size[1]) if self.x_axis: self.x_axis.draw(self, can) if self.x_axis2: self.x_axis2.draw(self, can) def __draw_y_grid_and_axis(self, can): if self.y_grid_style: for i in self.y_tic_points(self.y_grid_interval): y = self.y_pos(i) if y > self.loc[1]: can.line(self.y_grid_style, self.loc[0], y, self.loc[0]+self.size[0], y) if self.y_axis: self.y_axis.draw(self, can) if self.y_axis2: self.y_axis2.draw(self, can) def __get_data_range(self, r, which, coord, interval): if isinstance(coord, category_coord.T): # This info is unused for the category coord type. # So I just return a random value. return ((0,0), 1) r = r or (None, None) if len(self.__plots) == 0: raise ValueError, "No chart to draw, and no data range specified.\n"; dmin, dmax = 999999, -999999 for plot in self.__plots: this_min, this_max = plot.get_data_range(which) dmin = min(this_min, dmin) dmax = max(this_max, dmax) if interval and type(interval) == FunctionType: tics = apply(interval, (dmin, dmax)) dmin = tics[0] dmax = tics[len(tics)-1] else: dmin, dmax, interval = coord.get_min_max(dmin, dmax, interval) if r[0] != None: dmin = r[0] if r[1] != None: dmax = r[1] return ((dmin, dmax), interval) def draw(self, can = None): "Draw the charts." if can == None: can = canvas.default_canvas() assert self.check_integrity() for plot in self.__plots: plot.check_integrity() self.x_range, self.x_grid_interval = \ self.__get_data_range(self.x_range, 'X', self.x_coord, self.x_grid_interval) self.y_range, self.y_grid_interval = \ self.__get_data_range(self.y_range, 'Y', self.y_coord, self.y_grid_interval) can.rectangle(self.border_line_style, self.bg_style, self.loc[0], self.loc[1], self.loc[0] + self.size[0], self.loc[1] + self.size[1]) if not self.x_grid_over_plot: self.__draw_x_grid_and_axis(can) if not self.y_grid_over_plot: self.__draw_y_grid_and_axis(can) clipbox = theme.adjust_bounding_box([self.loc[0], self.loc[1], self.loc[0] + self.size[0], self.loc[1] + self.size[1]]) can.clip(clipbox[0], clipbox[1], clipbox[2], clipbox[3]) for plot in self.__plots: plot.draw(self, can) can.endclip() if self.x_grid_over_plot: self.__draw_x_grid_and_axis(can) if self.y_grid_over_plot: self.__draw_y_grid_and_axis(can) if self.legend == _dummy_legend: self.legend = legend.T() if self.legend: legends = [] for plot in self.__plots: entry = plot.get_legend_entry() if entry == None: pass elif type(entry) != ListType: legends.append(entry) else: for e in entry: legends.append(e) self.legend.draw(self, legends, can) def plots(self): return self.__plots def add_plot(self, *plots): "Add PLOTS... to the area." self.__plots.extend(plots) PyChart-1.39/pychart/scaling.py0000644000175000017500000000143210354321345020120 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import theme x_base = 300 y_base = 300 def xscale(x): return x * theme.scale_factor + x_base def yscale(y): return y * theme.scale_factor + y_base def nscale(x): return x * theme.scale_factor def nscale_seq(x): return map(nscale, x) PyChart-1.39/pychart/arrow.py0000644000175000017500000001524210354321374017640 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import line_style import color import chart_object import object_set import math import arrow_doc import canvas from pychart_types import * from types import * from scaling import * __doc__ = """ Arrow is an optional component of a chart that draws line segments with an arrowhead. To draw an arrow, one creates an arrow.T object, and calls its "draw" method usually after area.draw() is called (otherwise, area.draw() may overwrite the arrow). For example, the below code draws an arrow from (10,10) to (20,30). ar = area.T(...) a = arrow.T(head_style = 1) ar.draw() a.draw([(10,10), (20,30)]) """ def draw_arrowhead(can, tailx, taily, tipx, tipy, thickness, head_len, style): can.comment("ARROWHEAD tail=(%d,%d) tip=(%d,%d)\n" % (tailx, taily, tipx, tipy)) halfthickness = thickness/2.0 dx = tipx - tailx dy = tipy - taily arrow_len = math.sqrt(dx*dx + dy*dy) angle = math.atan2(dy, dx) * 360 / (2*math.pi) base = arrow_len - head_len can.push_transformation((tailx, taily), None, angle) can.newpath() if style == 0: can.moveto(base, - halfthickness) can.lineto(base, halfthickness) can.lineto(arrow_len, 0) can.closepath() elif style == 1: depth = head_len / 2.5 can.moveto(base - depth, -halfthickness) can.lineto(base, 0) can.lineto(base - depth, halfthickness) can.lineto(arrow_len, 0) can.closepath() elif style == 2: can.moveto(base + head_len/2.0, 0) can.path_arc(base + head_len / 2.0, 0, head_len / 2.0, 1.0, 0, 400) elif style == 3: can.moveto(base, 0) can.lineto(base + head_len/2.0, -halfthickness) can.lineto(arrow_len, 0) can.lineto(base + head_len/2.0, halfthickness) can.closepath() else: raise Exception, "Arrow style must be a number between 0 and 3." can.fill() can.pop_transformation() can.comment("end ARROWHEAD.\n") def draw_arrowbody(can, tailx, taily, tipx, tipy, head_len): dx = tipx - tailx dy = tipy - taily arrow_len = math.sqrt(dx*dx + dy*dy) angle = math.atan2(dy, dx) * 360 / (2*math.pi) base = arrow_len - head_len can.push_transformation((tailx, taily), None, angle) can.moveto(0, 0) can.lineto(base+head_len*0.1, 0) can.stroke() can.pop_transformation() class T(chart_object.T): __doc__ = arrow_doc.doc keys = { "thickness" : (UnitType, 4, "The width of the arrow head."), "head_len": (UnitType, 8, "The length of the arrow head."), "head_color": (color.T, color.default, "The color of the arrow head."), "line_style": (line_style.T, line_style.default, "Line style."), "head_style": (IntType, 1, "The value of 0 draws a triangular arrow head. The value of 1 draws a swallow-tail arrow head. The value of 2 draws a circular head. The value of 3 draws a diamond-shaped head.") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, points, can = None): """Parameter specifies the list of points the arrow traverses through. It should contain at least two points, i.e., the tail and tip. Parameter is an optional parameter that specifies the output. <> """ if can == None: can = canvas.default_canvas() assert self.check_integrity() xtip = points[-1][0] ytip = points[-1][1] xtail = points[-2][0] ytail = points[-2][1] can.newpath() can.set_line_style(self.line_style) if len(points) > 2: can.moveto(points[0][0], points[0][1]) for i in range(1, len(points)-1): can.lineto(points[i][0], points[i][1]) draw_arrowbody(can, xscale(xtail), yscale(ytail), yscale(xtip), yscale(ytip), nscale(self.head_len)) can.set_fill_color(self.head_color) draw_arrowhead(can, xscale(xtail), yscale(ytail), xscale(xtip), yscale(ytip), nscale(self.thickness), nscale(self.head_len), self.head_style) can.setbb(xtail, ytail) can.setbb(xtip, ytip) standards = object_set.T() def _intern(a): global standards standards.add(a) return a a0 = _intern(T(head_style=0)) a1 = _intern(T(head_style=1)) a2 = _intern(T(head_style=2)) a3 = _intern(T(head_style=3)) gray0 = _intern(T(head_style=0, head_color = color.gray50, line_style=line_style.T(color=color.gray50))) gray1 = _intern(T(head_style=1, head_color = color.gray50, line_style=line_style.T(color=color.gray50))) gray2 = _intern(T(head_style=2, head_color = color.gray50, line_style=line_style.T(color=color.gray50))) gray3 = _intern(T(head_style=3, head_color = color.gray50, line_style=line_style.T(color=color.gray50))) fat0 = _intern(T(head_style=0, head_len=12, thickness=10, line_style=line_style.T(width=2))) fat1 = _intern(T(head_style=1, head_len=12, thickness=10, line_style=line_style.T(width=2))) fat2 = _intern(T(head_style=2, head_len=12, thickness=10, line_style=line_style.T(width=2))) fat3 = _intern(T(head_style=3, head_len=12, thickness=10, line_style=line_style.T(width=2))) fatgray0 = _intern(T(head_style=0, head_len=12, thickness=10, head_color = color.gray50, line_style=line_style.T(width=2, color=color.gray50))) fatgray1 = _intern(T(head_style=1, head_len=12, thickness=10, head_color = color.gray50, line_style=line_style.T(width=2, color=color.gray50))) fatgray2 = _intern(T(head_style=2, head_len=12, thickness=10, head_color = color.gray50, line_style=line_style.T(width=2, color=color.gray50))) fatgray3 = _intern(T(head_style=3, head_len=12, thickness=10, head_color = color.gray50, line_style=line_style.T(width=2, color=color.gray50))) default = a1 PyChart-1.39/pychart/range_plot.py0000644000175000017500000001137110354321374020637 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import line_style import pychart_util import chart_object import fill_style import legend import range_plot_doc from pychart_types import * from types import * from scaling import * class T(chart_object.T): __doc__ = range_plot_doc.doc keys = { "data" : (AnyType, None, pychart_util.data_desc), "label": (StringType, "???", pychart_util.label_desc), "xcol" : (IntType, 0, pychart_util.xcol_desc), "min_col": (IntType, 1, "The lower bound of the sweep is extracted from " + "this column of data."), "max_col": (IntType, 2, "The upper bound of the sweep is extracted from " + "this column of data."), "line_style": (line_style.T, line_style.default, "The style of the boundary line."), "fill_style": (fill_style.T, fill_style.default, ""), } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def check_integrity(self): chart_object.T.check_integrity(self) def get_data_range(self, which): if which == 'X': return pychart_util.get_data_range(self.data, self.xcol) else: ymax = (pychart_util.get_data_range(self.data, self.max_col))[1] ymin = (pychart_util.get_data_range(self.data, self.min_col))[0] return (ymin, ymax) def get_legend_entry(self): if self.label: return legend.Entry(line_style=self.line_style, fill_style=self.fill_style, label=self.label) return None def draw(self, ar, can): prevPair = None xmin=999999 xmax=-999999 ymin=999999 ymax=-999999 # Draw the boundary in a single stroke. can.gsave() can.newpath() for pair in self.data: x = pair[self.xcol] y = pychart_util.get_sample_val(pair, self.max_col) if y == None: continue xmin = min(xmin, ar.x_pos(x)) xmax = max(xmax, ar.x_pos(x)) ymin = min(ymin, ar.y_pos(y)) ymax = max(ymax, ar.y_pos(y)) if prevPair != None: can.lineto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) else: can.moveto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) prevPair = pair for i in range(len(self.data)-1, -1, -1): pair = self.data[i] x = pair[self.xcol] y = pychart_util.get_sample_val(pair, self.min_col) if None in (x, y): continue xmin = min(xmin, ar.x_pos(x)) xmax = max(xmax, ar.x_pos(x)) ymin = min(ymin, ar.y_pos(y)) ymax = max(ymax, ar.y_pos(y)) can.lineto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) can.closepath() # create a clip region, and fill it. can.clip_sub() can.fill_with_pattern(self.fill_style, xmin, ymin, xmax, ymax) can.grestore() if self.line_style: # draw the boundary. prevPair = None can.newpath() can.set_line_style(self.line_style) for pair in self.data: x = pair[self.xcol] y = pychart_util.get_sample_val(pair, self.min_col) if None in (x, y): continue if prevPair != None: can.lineto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) else: can.moveto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) prevPair = pair can.stroke() prevPair = None can.newpath() can.set_line_style(self.line_style) for pair in self.data: x = pair[self.xcol] y = pychart_util.get_sample_val(pair, self.max_col) if y == None: continue if prevPair != None: can.lineto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) else: can.moveto(xscale(ar.x_pos(x)), yscale(ar.y_pos(y))) prevPair = pair can.stroke() PyChart-1.39/pychart/legend_doc.py0000644000175000017500000000010510354321374020561 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " doc_entry=" " PyChart-1.39/pychart/error_bar.py0000644000175000017500000001210010354321345020447 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import tick_mark import line_style import pychart_util import chart_object import fill_style import types import error_bar_doc import object_set from pychart_types import * __doc__ = """Pychart offers several styles of error bars. Some of them only displays the min/max confidence interval, while others can display quartiles in addition to min/max.""" class T(chart_object.T): keys = {} ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED pass # Two horizontal lines at min & max locations. class error_bar1(T): __doc__ = error_bar_doc.doc_1 keys = {"tic_len" : (UnitType, 10, "Length of the horizontal bars"), "line_style": (line_style.T, line_style.default, "") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin = None, qmax = None): x = loc[0] y = min can.line(self.line_style, x-self.tic_len/2.0, y, x+self.tic_len/2.0, y) y = max can.line(self.line_style, x-self.tic_len/2.0, y, x+self.tic_len/2.0, y) class error_bar2(T): __doc__ = error_bar_doc.doc_2 keys = {"tic_len" : (UnitType, 3, "The length of the horizontal bars"), "hline_style": (line_style.T, line_style.default, "The style of the horizontal bars."), "vline_style": (line_style.T, None, "The style of the vertical bar.") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin = None, qmax = None): vline_style = self.vline_style if not vline_style: vline_style = self.hline_style x = loc[0] y1 = min can.line(self.hline_style, x-self.tic_len/2.0, y1, x+self.tic_len/2.0, y1) y2 = max can.line(self.hline_style, x-self.tic_len/2.0, y2, x+self.tic_len/2.0, y2) can.line(vline_style, x, y1, x, y2) class error_bar3(T): # Tufte style __doc__ = "This style is endorsed by the Tufte's books. " \ + error_bar_doc.doc_3 keys = { "line_style": (line_style.T, line_style.default, "") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin, qmax): x = loc[0] can.line(self.line_style, x, min, x, qmin) can.line(self.line_style, x, qmax, x, max) class error_bar4(T): __doc__ = error_bar_doc.doc_4 keys = { "line_style": (line_style.T, line_style.default, ""), "fill_style": (fill_style.T, fill_style.gray70, ""), "box_width": (UnitType, 4, ""), "tic_len": (UnitType, 4, "") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin, qmax): x = loc[0] style = self.line_style y1 = min can.line(style, x-self.tic_len/2.0, y1, x+self.tic_len/2.0, y1) y2 = max can.line(style, x-self.tic_len/2.0, y2, x+self.tic_len/2.0, y2) can.line(style, x, y1, x, y2) can.rectangle(style, self.fill_style, x-self.box_width/2.0, qmin, x+self.box_width/2.0, qmax) # vertical line class error_bar5(T): __doc__ = error_bar_doc.doc_5 keys = { "line_style": (line_style.T, line_style.default, "") } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin = None, qmax = None): x = loc[0] y = loc[1] min = (min - y) *1 + y max = (max - y) *1+ y can.line(self.line_style, x, min, x, max) # a box class error_bar6(T): __doc__ = error_bar_doc.doc_6 keys = { "line_style": (line_style.T, line_style.default, ""), "fill_style": (fill_style.T, fill_style.gray70, ""), "center_line_style": (line_style.T, line_style.T(width=0.5), ""), "box_width": (UnitType, 4, ""), } ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw(self, can, loc, min, max, qmin = None, qmax = None): x = loc[0] y = loc[1] can.rectangle(self.line_style, self.fill_style, x - self.box_width / 2.0, min, x + self.box_width / 2.0, max) can.line(self.center_line_style, x - self.box_width/2.0, (min+max)/2.0, x + self.box_width/2.0, (min+max)/2.0) bar1 = error_bar1() bar2 = error_bar2() bar3 = error_bar3() bar4 = error_bar4() bar5 = error_bar5() bar6 = error_bar6() standards = object_set.T(bar1, bar2, bar3, bar4, bar5, bar6) PyChart-1.39/pychart/line_plot_doc.py0000644000175000017500000000006710354321374021317 0ustar santiagosantiago00000000000000# automatically generated by generate_docs.py. doc=" " PyChart-1.39/pychart/pscanvas.py0000644000175000017500000002603210352122023020307 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import re import theme import version import basecanvas from scaling import * comment_p = 0 # Converts BMP Unicode character to Postscript character name. In # theory, we should be able to just use ISOLatin1Encoding, but this # doesn't seem to work. _unicode_latin1_conversion_table = { 0x0027: 'quotesingle', 0x0060: 'grave', 0x00A0: 'space', 0x00A1: 'exclamdown', 0x00A2: 'cent', 0x00A3: 'sterling', 0x00A4: 'currency', 0x00A5: 'yen', 0x00A6: 'brokenbar', 0x00A7: 'section', 0x00A8: 'dieresis', 0x00A9: 'copyright', 0x00AA: 'ordfeminine', 0x00AB: 'guillemotleft', 0x00AC: 'logicalnot', 0x00AD: 'hyphen', 0x00AE: 'registered', 0x00AF: 'macron', 0x00B0: 'degree', 0x00B1: 'plusminus', 0x00B2: 'twosuperior', 0x00B3: 'threesuperior', 0x00B4: 'acute', 0x00B5: 'mu', 0x00B6: 'paragraph', 0x00B7: 'periodcentered', 0x00B8: 'cedilla', 0x00B9: 'onesuperior', 0x00BA: 'ordmasculine', 0x00BB: 'guillemotright', 0x00BC: 'onequarter', 0x00BD: 'onehalf', 0x00BE: 'threequarters', 0x00BF: 'questiondown', 0x00C0: 'Agrave', 0x00C1: 'Aacute', 0x00C2: 'Acircumflex', 0x00C3: 'Atilde', 0x00C4: 'Adieresis', 0x00C5: 'Aring', 0x00C6: 'AE', 0x00C7: 'Ccedilla', 0x00C8: 'Egrave', 0x00C9: 'Eacute', 0x00CA: 'Ecircumflex', 0x00CB: 'Edieresis', 0x00CC: 'Igrave', 0x00CD: 'Iacute', 0x00CE: 'Icircumflex', 0x00CF: 'Idieresis', 0x00D0: 'Eth', 0x00D1: 'Ntilde', 0x00D2: 'Ograve', 0x00D3: 'Oacute', 0x00D4: 'Ocircumflex', 0x00D5: 'Otilde', 0x00D6: 'Odieresis', 0x00D7: 'multiply', 0x00D8: 'Oslash', 0x00D9: 'Ugrave', 0x00DA: 'Uacute', 0x00DB: 'Ucircumflex', 0x00DC: 'Udieresis', 0x00DD: 'Yacute', 0x00DE: 'Thorn', 0x00DF: 'germandbls', 0x00E0: 'agrave', 0x00E1: 'aacute', 0x00E2: 'acircumflex', 0x00E3: 'atilde', 0x00E4: 'adieresis', 0x00E5: 'aring', 0x00E6: 'ae', 0x00E7: 'ccedilla', 0x00E8: 'egrave', 0x00E9: 'eacute', 0x00EA: 'ecircumflex', 0x00EB: 'edieresis', 0x00EC: 'igrave', 0x00ED: 'iacute', 0x00EE: 'icircumflex', 0x00EF: 'idieresis', 0x00F0: 'eth', 0x00F1: 'ntilde', 0x00F2: 'ograve', 0x00F3: 'oacute', 0x00F4: 'ocircumflex', 0x00F5: 'otilde', 0x00F6: 'odieresis', 0x00F7: 'divide', 0x00F8: 'oslash', 0x00F9: 'ugrave', 0x00FA: 'uacute', 0x00FB: 'ucircumflex', 0x00FC: 'udieresis', 0x00FD: 'yacute', 0x00FE: 'thorn', 0x00FF: 'ydieresis', } class T(basecanvas.T): def __init__(self, fname): basecanvas.T.__init__(self) self.__out_fname = fname self.__reset_context() self.__output_lines = [] self.__nr_gsave = 0 self.__font_ids = {} self.__nr_fonts = 0 def __reset_context(self): self.__font_name = None self.__font_size = -1 self.__line_style = None self.__color = None self.__mtx_pushed = 0 self.__txtmtx_pushed = 0 def __intern_font(self, name): if self.__font_ids.has_key(name): return self.__font_ids[name] id = "F%d" % self.__nr_fonts self.__nr_fonts += 1 self.__font_ids[name] = id return id def newpath(self): self.__write("N\n") def stroke(self): self.__write("ST\n") def closepath(self): self.__write("CP\n") def moveto(self, x, y): self.__write('%g %g M\n' % (x, y)) def set_fill_color(self, color): if self.__color == color: pass else: if color.r == color.g and color.r == color.b: self.__write("%g SG\n" % color.r) else: self.__write("%g %g %g SC\n" % (color.r, color.g, color.b)) self.__color = color def set_stroke_color(self, color): self.set_fill_color(color) def set_line_style(self, style): self.set_stroke_color(style.color) if (self.__line_style == style): pass else: self.__write("%g %d %d " % (nscale(style.width), style.cap_style, style.join_style)) if style.dash != None: self.__write("[%s] 0 SLD " % " ".join(map(str, nscale_seq(style.dash)))) else: self.__write("SL ") self.__line_style = style def gsave(self): self.__nr_gsave += 1 self.__write("GS\n") def grestore(self): self.__write("GR\n") self.__nr_gsave -= 1 self.__reset_context() def clip_sub(self): self.__write("clip\n") def path_arc(self, x, y, radius, ratio, start_angle, end_angle): self.push_transformation((x, y), (1, ratio), None) self.__write("0 0 %g %g %g arc\n" % (radius, start_angle, end_angle)) self.pop_transformation() def curveto(self, a,b,c,d,e,f): self.__write("%g %g %g %g %g %g curveto\n" % (a,b,c,d,e,f)) def push_transformation(self, baseloc, scale, angle, in_text=0): self.__mtx_pushed += 1 self.__write("GB\n") if baseloc != None: self.__write("%g %g T\n" % (baseloc[0], baseloc[1])) if angle != None and angle != 0: self.__write("%g R\n" % (angle)) if scale != None: self.__write("%g %g scale\n" % (scale[0], scale[1])) def pop_transformation(self, in_text=0): if self.__mtx_pushed == 0: raise ValueError, "mtx not pushed" self.__mtx_pushed -= 1 self.__write("GE\n") def text_begin(self): self.__txtmtx_pushed += 1 self.__write("TB\n") def text_end(self): self.__txtmtx_pushed -= 1 self.__write("TE\n") def text_moveto(self, x, y, angle): self.__write("%g %g T " % (x,y)) if angle != None and angle != 0: self.__write("%g R " % angle) self.moveto(0, 0) def text_show(self, font_name, size, color, str): self.set_fill_color(color) if (self.__font_name == font_name and self.__font_size == size): pass else: font_id = self.__intern_font(font_name) self.__write("%g %s\n" % (size, font_id)) self.__font_name = font_name self.__font_size = size self.__write("(") # Convert unicode to Postscript Latin code. for ch in str: # Note: Escaping of ()\ is done by the basecanvas.show, so # we need not worry about them here. Perhaps we should move # that code here?? n = ord(ch) if n > 128 or ch in ("'", "`"): ent = _unicode_latin1_conversion_table.get(n, None) if not ent: self.__write(ch) else: self.__write(") show /%s glyphshow (" % ent) else: self.__write(ch) self.__write(") show\n") def _path_polygon(self, points): if (len(points) == 4 and points[0][0] == points[1][0] and points[2][0] == points[3][0] and points[0][1] == points[3][1] and points[1][1] == points[2][1]): # a rectangle. (xmin, ymin, xmax, ymax) = basecanvas._compute_bounding_box(points) if basecanvas.invisible_p(xmax, ymax): return self.setbb(xmin, ymin) self.setbb(xmax, ymax) self.__write("%g %g %g %g RECT\n" % \ (xscale(points[0][0]), yscale(points[0][1]), xscale(points[2][0]), yscale(points[2][1]))) else: basecanvas.T._path_polygon(self, points) def lineto(self, x, y): self.__write("%g %g L\n" % (x, y)) def fill(self): self.__write("fill\n") def comment(self, str): if comment_p: self.verbatim("%" + str) def verbatim(self, str): self.__write(str) def close(self): basecanvas.T.close(self) if self.__output_lines == []: return fp, need_close = self.open_output(self.__out_fname) if self.__nr_gsave != 0: raise Exception, "gsave misnest (%d)" % (self.__nr_gsave) self.write_preamble(fp) fp.writelines(self.__output_lines) fp.writelines(["showpage end\n", "%%Trailer\n", "%%EOF\n"]) if need_close: fp.close() def __write(self, str): self.__output_lines.append(str) def writelines(self, l): self.__output_lines.extend(l) def write_preamble(self, fp): bbox = [self.__xmin-1, self.__ymin-1, self.__xmax+1, self.__ymax+1] fp.write("%!PS-Adobe-2.0 EPSF-1.2\n") fp.write("%%Title: " + self.title + "\n") fp.write("%%Creator: " + self.creator + "\n") if self.author: fp.write("%%Author: " + self.author + "\n") fp.write("%%CreationDate: " + self.creation_date + "\n") fp.write("%%DocumentFonts: " + " ".join(self.__font_ids.keys()) + "\n") fp.write("%%Pages: 1\n") bbox = theme.adjust_bounding_box(bbox) fp.write("%%%%BoundingBox: %d %d %d %d\n" % \ (round(xscale(bbox[0])), round(yscale(bbox[1])), round(xscale(bbox[2])), round(yscale(bbox[3])))) fp.write("%%EndComments\n") if self.aux_comments != "": for line in self.aux_comments.split("\n"): fp.write("% " + line + "\n") fp.write(preamble_text) for name, font_id in self.__font_ids.items(): fp.write("/%s {/%s findfont SF} def\n" % (font_id, name)) fp.write("%%EndProlog\n%%Page: 1 1\n") preamble_text=""" 40 dict begin /RECT {4 dict begin /y2 exch def /x2 exch def /y1 exch def /x1 exch def newpath x1 y1 moveto x2 y1 lineto x2 y2 lineto x1 y2 lineto closepath end } def /SF {exch scalefont setfont} def /TB {matrix currentmatrix} def /TE {setmatrix} def /GB {matrix currentmatrix} def /GE {setmatrix} def /SG {1 1 1 setrgbcolor setgray} def /SC {1 setgray setrgbcolor} def /SL {[] 0 setdash setlinejoin setlinecap setlinewidth} def /SLD {setdash setlinejoin setlinecap setlinewidth} def /M {moveto} def /L {lineto} def /T {translate} def /R {rotate} def /N {newpath} def /ST {stroke} def /CP {closepath} def /GR {grestore} def /GS {gsave} def """ # SL: set line style. # width [dash] x linecap linejoin SL -> # SF: set font. # name size SF -> PyChart-1.39/pychart/axis.py0000644000175000017500000002151310354321374017450 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import font import pychart_util import chart_object import line_style import math import theme import axis_doc from pychart_types import * from types import * class T(chart_object.T): keys = { "tic_interval" : (IntervalType, None, pychart_util.interval_desc("tick marks")), "tic_len" : (UnitType, 6, """The length of tick lines. The value can be negative, in which case the tick lines are drawn right of (or above) the axis."""), "minor_tic_interval" : (IntervalType, None, pychart_util.interval_desc("minor tick marks")), "minor_tic_len" : (UnitType, 3, """The length of minor tick marks. The value can be negative, in which case the tick lines are drawn right of (or above) the axis."""), "line_style": (line_style.T, line_style.default, "Specifies the style of axis and tick lines."), "label": (types.StringType, "axis label", "The descriptive string displayed below (or to the left of) the axis. <>."), "format": (FormatType, "%s", """The format string for tick labels. It can be a `printf' style format string, or a single-parameter function that takes an X (or Y) value and returns a string. """ + pychart_util.string_desc), "label_offset": (CoordType, (None,None), """The location for drawing the axis label, relative to the middle point of the axis. If the value is None, the label is displayed below (or to the left of) of axis at the middle."""), "tic_label_offset": (CoordType, (0,0), """The location for drawing tick labels, relative to the tip of the tick line."""), "offset": (UnitType, 0, """The location of the axis. The value of 0 draws the axis at the left (for the Y axis) or bottom (for the X axis) edge of the drawing area. """) } class X(T): keys = pychart_util.union_dict(T.keys, {"draw_tics_above": (IntType, 0, "If true, tick lines and labels are drawn above the axis line.")}) __doc__ = axis_doc.doc_x ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def draw_tics_and_labels(self, ar, can): assert self.check_integrity() y_base = ar.loc[1] + self.offset self.tic_interval = self.tic_interval or ar.x_grid_interval can.line(self.line_style, ar.loc[0], y_base, ar.loc[0]+ ar.size[0], y_base) tic_dic = {} max_tic_height = 0 if self.draw_tics_above: sign = 1 else: sign = -1 for i in ar.x_tic_points(self.tic_interval): tic_dic[i] = 1 ticx = ar.x_pos(i) string = "/hC" + pychart_util.apply_format(self.format, (i, ), 0) (total_height, base_height) = font.text_height(string) max_tic_height = max(max_tic_height, total_height) if self.draw_tics_above: base_height = 0 can.line(self.line_style, ticx, y_base, ticx, y_base + sign * self.tic_len) can.show(ticx + self.tic_label_offset[0], y_base + sign * (self.tic_len + base_height) + self.tic_label_offset[1], string) if self.minor_tic_interval: for i in ar.x_tic_points(self.minor_tic_interval): if tic_dic.has_key(i): # a major tic was drawn already. pass else: ticx = ar.x_pos(i) can.line(self.line_style, ticx, y_base, ticx, y_base + sign * self.minor_tic_len) self.draw_label(ar, can, (y_base + sign * (self.tic_len + max_tic_height + 10))) def draw_label(self, ar, can, ylabel): if self.label == None: return string = "/hC/vM" + self.label (label_height, base_height) = font.text_height(string) xlabel = ar.loc[0] + ar.size[0]/2.0 if self.label_offset[0] != None: xlabel += self.label_offset[0] if self.label_offset[1] != None: ylabel += self.label_offset[1] can.show(xlabel, ylabel, string) def draw(self, ar, can): assert self.check_integrity() self.tic_interval = self.tic_interval or ar.x_grid_interval y_base = ar.loc[1] + self.offset can.line(self.line_style, ar.loc[0], y_base, ar.loc[0]+ ar.size[0], y_base) self.draw_tics_and_labels(ar, can) class Y(T): __doc__ = axis_doc.doc_y keys = pychart_util.union_dict(T.keys, {"draw_tics_right": (IntType, 0, "If true, tick lines and labels are drawn right of the axis line.")}) def draw_left(self, ar, can): x_base = ar.loc[0] + self.offset xmin = 999999 tic_dic = {} for i in ar.y_tic_points(self.tic_interval): y_tic = ar.y_pos(i) tic_dic[i] = 1 can.line(self.line_style, x_base, y_tic, x_base - self.tic_len, y_tic) string = pychart_util.apply_format(self.format, (i,), 0) if self.tic_len > 0: string = "/hR" + string tic_height, base_height = font.text_height(string) x = x_base - self.tic_len + self.tic_label_offset[0] can.show(x, y_tic - tic_height/2.0 + self.tic_label_offset[1], string) xmin = min(xmin, x - font.text_width(string)) if self.minor_tic_interval: for i in ar.y_tic_points(self.minor_tic_interval): if tic_dic.has_key(i): # a major tic line was drawn already. pass else: y_tic = ar.y_pos(i) can.line(self.line_style, x_base, y_tic, x_base - self.minor_tic_len, y_tic) self.draw_label(ar, can, xmin - theme.default_font_size/2.0) def draw_right(self, ar, can): x_base = ar.loc[0] + self.offset xmax = 0 tic_dic = {} for i in ar.y_tic_points(self.tic_interval): y_tic = ar.y_pos(i) tic_dic[i] = 1 can.line(self.line_style, x_base, y_tic, x_base + self.tic_len, y_tic) string = pychart_util.apply_format(self.format, (i,), 0) if self.tic_len > 0: string = "/hL" + string tic_height, base_height = font.text_height(string) x = x_base + self.tic_len + self.tic_label_offset[0] can.show(x, y_tic - tic_height/2.0 + self.tic_label_offset[1], string) xmax = max(xmax, x + font.text_width(string)) if self.minor_tic_interval: for i in ar.y_tic_points(self.minor_tic_interval): if tic_dic.has_key(i): # a major tic line was drawn already. pass else: y_tic = ar.y_pos(i) can.line(self.line_style, x_base, y_tic, x_base + self.minor_tic_len, y_tic) self.draw_label(ar, can, xmax + theme.default_font_size) def draw_label(self, ar, can, xlabel): if self.label == None: return ylabel = ar.loc[1] + ar.size[1] / 2 if self.label_offset[0] != None: xlabel += self.label_offset[0] if self.label_offset[1] != None: ylabel += self.label_offset[1] can.show(xlabel, ylabel, "/a90/hC" + self.label) def draw(self, ar, can): assert self.check_integrity() self.tic_interval = self.tic_interval or ar.y_grid_interval x_base = ar.loc[0] + self.offset can.line(self.line_style, x_base, ar.loc[1], x_base, ar.loc[1]+ar.size[1]) if self.draw_tics_right: self.draw_right(ar, can) else: self.draw_left(ar, can) PyChart-1.39/pychart/interval_bar_plot.py0000644000175000017500000002233410354321374022214 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import line_style import fill_style import pychart_util import chart_object import legend import bar_plot_doc import theme from types import * from pychart_types import * fill_styles = None _keys = { "direction" : (StringType, "vertical", """The direction the growth of the bars. The value is either 'horizontal' or 'vertical'."""), "data" : (AnyType, None, """Specifes data points. Unlike other types of charts, the "hcol"th column of the data must be a sequence of numbers, not just a single number. See also the description of "hcol".""" ), "data_label_offset": (CoordType, (0, 5), "The location of data labels relative to the sample point. See also attribute data_label_format."), "data_label_format": (FormatType, None, """The format string for the label displayed besides each bar. It can be a `printf' style format string, or a two-parameter function that takes (x,y) values and returns a string. """ + pychart_util.string_desc), "label": (StringType, "???", pychart_util.label_desc), "bcol" : (IntType, 0, """Specifies the column from which base values (i.e., X values when attribute "direction" is "vertical", Y values otherwise) are extracted. The combination of "data", "bcol", and "hcol" attributes defines the set of boxes drawn by this chart. See also the descriptions of the 'bcol' and 'data' attributes. """), "hcol": (IntType, 1, """The column from which the base and height of bars are extracted. See the below example: @example d = [[5,[10,15,22]], [7,[22,23,5,10]], [8,[25,3]]] p = interval_bar_plot.T(data = d, bcol = 0, hcol = 1) @end example Here, three sequence of bars will be drawn. The X locations of the bars will be 5, 7, and 8. For example, at location X=7, three bars are drawn, one corresponding to Y values of 22 to 45 (=22+23), and the second one for values 45 to 50, and the third one for values 50 to 60. The line and fill styles of the bars are picked in a round-robin fashion from attributes "line_styles" and "fill_styles". """), "line_styles": (ListType, [line_style.default, None], """The list of line styles for bars. The style of each bar is chosen in a round-robin fashion, if the number of elements in "line_styles" is smaller than actual number of boxes."""), "fill_styles": (ListType, [lambda: fill_styles.next(), None], """List of fill styles for bars. The style of each bar is chosen in a round-robin fashion, if the number of elements in "line_styles" is smaller than actual number of boxes. If this attribute is omitted, a style is picked from standard styles round-robin. <>."""), "cluster": (TupleType, (0, 1), """This attribute is used to cluster multiple bar plots side by side in a single chart. The value should be a tuple of two integers. The second value should be equal to the total number of bar plots in the chart. The first value should be the relative position of this chart; 0 places this chart the leftmost, and N-1 (where N is the 2nd value of this attribute) places this chart the rightmost. Consider the below example: @example a = area.T(...) p1 = interval_bar_plot.T(data = [[1, [20,10]][2,[30,5]]], cluster=(0,2)) p2 = interval_bar_plot.T(data = [[1,[25,11,2]],[2,[10,5,3]]], cluster=(1,2)) a.add_plot(p1, p2) a.draw() @end example In this example, one group of bars will be drawn side-by-side at position x=1. Other two bars will be drawn side by side at position x=2. See also the description of attribute "cluster" for bar_plot.T. """), "width": (UnitType, 5, """Width of each box. The unit is in points. @cindex width!- of interval bar plot @cindex size!- interval bar plot """), "cluster_sep": (UnitType, 0, """The separation between clustered boxes. The unit is points."""), "stack_on": (AnyType, None, "The value must be either None or bar_plot.T. If not None, bars of this plot are stacked on top of another bar plot."), } class T(chart_object.T): __doc__ = bar_plot_doc.doc keys = _keys def check_integrity(self): chart_object.T.check_integrity(self) def get_value(self, bval): for pair in self.data: if pair[self.bcol] == bval: return pair[self.hcol] raise ValueError, str(bval) + ": can't find the xval" def __get_data_range(self, col): gmin = 99999999 gmax = -99999999 for item in self.data: seq = item[col] if seq[0] < gmin: gmin = seq[0] max = 0 for v in seq: max += v if max > gmax: gmax = max return (gmin, gmax) def get_data_range(self, which): if self.direction == 'vertical': if which == 'X': return pychart_util.get_data_range(self.data, self.bcol) else: return self.__get_data_range(self.hcol) else: assert self.direction == 'horizontal' if which == 'Y': return pychart_util.get_data_range(self.data, self.bcol) else: return self.__get_data_range(self.hcol) def get_style(self, nth): line_style = self.line_styles[nth % len(self.line_styles)] fill_style = self.fill_styles[nth % len(self.fill_styles)] return (line_style, fill_style) def draw_vertical(self, ar, can): for pair in self.data: xval = pair[self.bcol] yvals = pychart_util.get_sample_val(pair, self.hcol) if None in (xval, yvals): continue ybot = 0 totalWidth = (self.width+self.cluster_sep) * self.cluster[1] - self.cluster_sep first_x = ar.x_pos(xval) - totalWidth/2.0 this_x = first_x + (self.width+self.cluster_sep) * self.cluster[0] - self.cluster_sep cury = yvals[0] n = 0 for yval in yvals[1:]: (line_style, fill_style) = self.get_style(n) can.rectangle(line_style, fill_style, this_x, ar.y_pos(cury), this_x+self.width, ar.y_pos(cury + yval)) cury += yval n += 1 if self.data_label_format: can.show(this_x + self.width/2.0 + self.data_label_offset[0], ar.y_pos(cury) + self.data_label_offset[1], "/hC" + pychart_util.apply_format(self.data_label_format, (pair[self.bcol], pair[self.hcol]), 1)) def draw_horizontal(self, ar, can): for pair in self.data: yval = pair[self.bcol] xvals = pychart_util.get_sample_val(pair, self.hcol) if None in (xvals, yval): continue totalWidth = (self.width+self.cluster_sep) * self.cluster[1] - self.cluster_sep first_y = ar.y_pos(yval) - totalWidth/2.0 this_y = first_y + (self.width+self.cluster_sep) * self.cluster[0] - self.cluster_sep curx = xvals[0] n = 0 for xval in xvals[1:]: line_style, fill_style = self.get_style(n) can.rectangle(line_style, fill_style, ar.x_pos(curx), this_y, ar.x_pos(curx + xval), this_y + self.width) curx += xval n += 1 def get_legend_entry(self): if self.label: return legend.Entry(line_style=self.line_styles[0], fill_style=self.fill_styles[0], label=self.label) return None def draw(self, ar, can): assert chart_object.T.check_integrity(self) can.clip(ar.loc[0], ar.loc[1], ar.loc[0] + ar.size[0], ar.loc[1] + ar.size[1]) if self.direction == "vertical": self.draw_vertical(ar, can) else: self.draw_horizontal(ar, can) can.endclip() def init(): global fill_styles fill_styles = fill_style.standards.iterate() theme.add_reinitialization_hook(init) PyChart-1.39/pychart/__init__.py0000644000175000017500000000172010354321345020237 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # __all__ = [ "axis", "area", "basecanvas", "canvas", "line_plot", "pie_plot", "rose_plot", "tick_mark", "bar_plot", "chart_data", "arrow", "text_box", "color", "font", "fill_style", "error_bar", "range_plot", "chart_object", "line_style", "legend", "pychart_util", "theme", "scaling", "zap", "coord", "linear_coord", "log_coord", "category_coord", "afm", "interval_bar_plot" ] PyChart-1.39/pychart/tick_mark.py0000644000175000017500000001503710354321374020454 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import color import line_style import fill_style import chart_object import object_set import pychart_util import tick_mark_doc from pychart_types import * _keys = { "line_style": (line_style.T, line_style.default, "The line style of the tick mark."), "fill_style": (fill_style.T, fill_style.white, "The fill style."), "size": (UnitType, 5, "Size of the tick mark."), } class T(chart_object.T): __doc__ = tick_mark_doc.doc keys = _keys ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED class Circle(T): """Draws a circle. """ def draw(self, can, x, y): can.ellipsis(self.line_style, self.fill_style, x, y, self.size/2.0, 1) class Square(T): """Draws a square.""" def draw(self, can, x, y): # move to the bottom-left corner x = x - self.size/2.0 y = y - self.size/2.0 can.rectangle(self.line_style, self.fill_style, x, y, x+self.size, y+self.size) class Triangle(T): """Draws a triangle pointing up.""" def draw(self, can, x, y): can.polygon(self.line_style, self.fill_style, ((x-self.size/1.6, y-self.size/2.0), (x+self.size/1.6, y-self.size/2.0), (x, y+self.size/2.0))) class DownTriangle(T): """Draws a triangle pointing down.""" def draw(self, can, x, y): can.polygon(self.line_style, self.fill_style, ((x, y-self.size/2.0), (x-self.size/1.6, y+self.size/2.0), (x+self.size/1.6, y+self.size/2.0))) class X(T): """Draw a "X"-shaped tick mark. Attribute "fill-style" is ignored.""" keys = pychart_util.union_dict(T.keys, {"line_style": (line_style.T, line_style.T(width=0.7), "The line style of the tick mark")}) def draw(self, can, x, y): # move to the bottom-left corner x = x - self.size/2.0 y = y - self.size/2.0 can.line(self.line_style, x, y, x+self.size, y+self.size) can.line(self.line_style, x+self.size, y, x, y+self.size) class Plus(T): """Draw a "+"-shaped tick mark. Attribute "fill-style" is ignored.""" keys = pychart_util.union_dict(T.keys, {"line_style": (line_style.T, line_style.T(width=1), "The line style of the tick mark.")}) def draw(self, can, x, y): # move to the bottom-left corner can.line(self.line_style, x-self.size/1.4, y, x+self.size/1.4, y) can.line(self.line_style, x, y-self.size/1.4, x, y+self.size/1.4) class Diamond(T): """Draw a square rotated at 45 degrees.""" def draw(self, can, x, y): # move to the bottom-left corner can.polygon(self.line_style, self.fill_style, ((x-self.size/1.4, y), (x, y+self.size/1.4), (x+self.size/1.4, y), (x, y-self.size/1.4))) class Star(T): """Draw a "*". Attribute "fill-style" is ignored.""" keys = pychart_util.union_dict(T.keys, {"line_style": (line_style.T, line_style.T(width=1), "The line style of the tick mark.")}) def draw(self, can, x, y): # move to the bottom-left corner midx = x midy = y d_len = self.size / 2.0 r_len = self.size * 1.414 / 2.0 can.line(self.line_style, x-d_len, y-d_len, x+d_len, y+d_len) can.line(self.line_style, x+d_len, y-d_len, x-d_len, y+d_len) can.line(self.line_style, midx, y-r_len, midx, y+r_len) can.line(self.line_style, x-r_len, midy, x+r_len, midy) class Null(T): """This tickmark doesn't draw anything. All the attributes are ignored.""" def __init__ (self): self.line_style = None self.fill_style = None self.size = -1 def draw(self, can, x, y): pass standards = object_set.T() def _intern(style): standards.add(style) return style square = _intern(Square()) square3 = _intern(Square(size=3)) square5 = square x = _intern(X()) x3 = _intern(X(size=3)) x5 = x star = _intern(Star()) star3 = _intern(Star(size=3)) star5 = star plus = _intern(Plus()) plus3 = _intern(Plus(size=3)) plus5 = plus dia = _intern(Diamond()) dia3 = _intern(Diamond(size=3)) dia5 = dia tri = _intern(Triangle()) tri3 = _intern(Triangle(size=3)) tri5 = tri dtri = _intern(DownTriangle()) dtri3 = _intern(DownTriangle(size=3)) dtri5 = dtri circle1 = _intern(Circle(size=1)) circle2 = _intern(Circle(size=3)) circle3 = _intern(Circle(size=5)) blacksquare = _intern(Square(fill_style=fill_style.black)) blacksquare3 = _intern(Square(size=3, fill_style=fill_style.black)) blackdia = _intern(Diamond(fill_style=fill_style.black)) blackdia3 = _intern(Diamond(size=3, fill_style=fill_style.black)) blacktri = _intern(Triangle(fill_style=fill_style.black)) blacktri3 = _intern(Triangle(size=3, fill_style=fill_style.black)) blackdtri = _intern(DownTriangle(fill_style=fill_style.black)) blackdtri3 = _intern(DownTriangle(size=3, fill_style=fill_style.black)) blackcircle1 = _intern(Circle(size=1, fill_style=fill_style.black)) blackcircle3 = _intern(Circle(size=3, fill_style=fill_style.black)) gray70square = _intern(Square(fill_style=fill_style.gray70)) gray70square3 = _intern(Square(size=3, fill_style=fill_style.gray70)) gray70dia = _intern(Diamond(fill_style=fill_style.gray70)) gray70dia3 = _intern(Diamond(size=3, fill_style=fill_style.gray70)) gray70tri = _intern(Triangle(fill_style=fill_style.gray70)) gray70tri3 = _intern(Triangle(size=3, fill_style=fill_style.gray70)) gray70dtri = _intern(DownTriangle(fill_style=fill_style.gray70)) gray70dtri3 = _intern(DownTriangle(size=3, fill_style=fill_style.gray70)) gray70circle1 = _intern(Circle(size=1, fill_style=fill_style.gray70)) gray70circle3 = _intern(Circle(size=3, fill_style=fill_style.gray70)) default = _intern(Null()) PyChart-1.39/pychart/chart_data.py0000644000175000017500000003037210354321345020577 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import pychart_util import copy import math def _convert_item(v, typ, line): if typ == "a": try: i = float(v) except ValueError: # non-number i = v return i elif typ == "d": try: return int(v) except ValueError: raise ValueError, "Can't convert %s to int; line=%s" % (v, line) elif typ == "f": try: return float(v) except ValueError: raise ValueError, "Can't convert %s to float; line=%s" % (v, line) elif typ == "s": return v else: raise ValueError, "Unknown conversion type, type=%s; line=%s" % (typ,line) def parse_line(line, delim): if delim.find("%") < 0: return [ _convert_item(item, "a", None) for item in line.split(delim) ] data = [] idx = 0 # indexes delim ch = 'f' sep = ',' while idx < len(delim): if delim[idx] != '%': raise ValueError, 'Bad delimitor: "%s"' % delim ch = delim[idx+1] idx += 2 sep = "" while idx < len(delim) and delim[idx] != '%': sep += delim[idx] idx += 1 if sep != "": xx = line.split(sep, 1) else: # reached the end of the delimiter string. xx = (line, ) data.append(_convert_item(xx[0], ch, line)) if len(xx) >= 2: line = xx[1] else: line = "" break if line != "": for item in line.split(sep): data.append(_convert_item(item, ch, line)) return data def escape_string(str): return str.replace("/", "//") def extract_rows(data, *rows): """Extract rows specified in the argument list. >>> chart_data.extract_rows([[10,20], [30,40], [50,60]], 1, 2) [[30,40],[50,60]] """ try: # for python 2.2 # return [data[r] for r in rows] out = [] for r in rows: out.append(data[r]) return out except IndexError: raise IndexError, "data=%s rows=%s" % (data, rows) return out def extract_columns(data, *cols): """Extract columns specified in the argument list. >>> chart_data.extract_columns([[10,20], [30,40], [50,60]], 0) [[10],[30],[50]] """ out = [] try: # for python 2.2: # return [ [r[c] for c in cols] for r in data] for r in data: col = [] for c in cols: col.append(r[c]) out.append(col) except IndexError: raise IndexError, "data=%s col=%s" % (data, col) return out def moving_average(data, xcol, ycol, width): """Compute the moving average of YCOL'th column of each sample point in DATA. In particular, for each element I in DATA, this function extracts up to WIDTH*2+1 elements, consisting of I itself, WIDTH elements before I, and WIDTH elements after I. It then computes the mean of the YCOL'th column of these elements, and it composes a two-element sample consisting of XCOL'th element and the mean. >>> data = [[10,20], [20,30], [30,50], [40,70], [50,5]] ... chart_data.moving_average(data, 0, 1, 1) [(10, 25.0), (20, 33.333333333333336), (30, 50.0), (40, 41.666666666666664), (50, 37.5)] The above value actually represents: [(10, (20+30)/2), (20, (20+30+50)/3), (30, (30+50+70)/3), (40, (50+70+5)/3), (50, (70+5)/2)] """ out = [] try: for i in range(len(data)): n = 0 total = 0 for j in range(i-width, i+width+1): if j >= 0 and j < len(data): total += data[j][ycol] n += 1 out.append((data[i][xcol], float(total) / n)) except IndexError: raise IndexError, "bad data: %s,xcol=%d,ycol=%d,width=%d" % (data,xcol,ycol,width) return out def filter(func, data): """Parameter must be a single-argument function that takes a sequence (i.e., a sample point) and returns a boolean. This procedure calls on each element in and returns a list comprising elements for which returns True. >>> data = [[1,5], [2,10], [3,13], [4,16]] ... chart_data.filter(lambda x: x[1] % 2 == 0, data) [[2,10], [4,16]]. """ out = [] for r in data: if func(r): out.append(r) return out def transform(func, data): """Apply on each element in and return the list consisting of the return values from . >>> data = [[10,20], [30,40], [50,60]] ... chart_data.transform(lambda x: [x[0], x[1]+1], data) [[10, 21], [30, 41], [50, 61]] """ out = [] for r in data: out.append(func(r)) return out def aggregate_rows(data, col): out = copy.deepcopy(data) total = 0 for r in out: total += r[col] r[col] = total return out def empty_line_p(s): return s.strip() == "" def _try_open_file(path, mode, error_message): try: fd = open(path, mode) except TypeError: fd = path if not getattr(fd, "readline", None): raise TypeError, error_message + "(got %s)" % str(fd) return fd def _try_close_file(fd, path): if fd != path: fd.close() def read_csv(path, delim = ','): """This function reads comma-separated values from a file. Parameter is either a pathname or a file-like object that supports the |readline()| method. Empty lines and lines beginning with "#" are ignored. Parameter specifies how a line is separated into values. If it does not contain the letter "%", then marks the end of a value. Otherwise, this function acts like scanf in C: chart_data.read_csv('file', '%d,%s:%d') Paramter currently supports only three conversion format specifiers: "d"(int), "f"(double), and "s"(string).""" fd = _try_open_file(path, 'r', 'The first argument must be a pathname or an object that supports readline() method') data = [] line = fd.readline() while line != "": if line[0] != '#' and not empty_line_p(line): data.append(parse_line(line, delim)) line = fd.readline() _try_close_file(fd, path) return data def fread_csv(fd, delim = ','): """This function is deprecated. Use read_csv instead.""" pychart_util.warn("chart_data.fread_csv is deprecated. Use read_csv instead.") return read_csv(fd, delim) def write_csv(path, data): """This function writes comma-separated to . Parameter is either a pathname or a file-like object that supports the |write()| method.""" fd = _try_open_file(path, 'w', 'The first argument must be a pathname or an object that supports write() method') for v in data: fd.write(",".join([str(x) for x in v])) fd.write("\n") _try_close_file(fd, path) def fwrite_csv(fd, delim = ','): """This function is deprecated. Use write_csv instead.""" pychart_util.warn("chart_data.fwrite_csv is deprecated. Use write_csv instead.") return write_csv(fd, delim) def read_str(delim = ',', *lines): """This function is similar to read_csv, but it reads data from the list of . fd = open("foo", "r") data = chart_data.read_str(",", fd.readlines())""" data = [] for line in lines: com = parse_line(line, delim) data.append(com) return data def func(f, xmin, xmax, step = None): """Create sample points from function , which must be a single-parameter function that returns a number (e.g., math.sin). Parameters and specify the first and last X values, and specifies the sampling interval. >>> chart_data.func(math.sin, 0, math.pi * 4, math.pi / 2) [(0, 0.0), (1.5707963267948966, 1.0), (3.1415926535897931, 1.2246063538223773e-16), (4.7123889803846897, -1.0), (6.2831853071795862, -2.4492127076447545e-16), (7.8539816339744828, 1.0), (9.4247779607693793, 3.6738190614671318e-16), (10.995574287564276, -1.0)] """ data = [] x = xmin if not step: step = (xmax - xmin) / 100.0 while x < xmax: data.append((x, f(x))) x += step return data def _nr_data(data, col): nr_data = 0 for d in data: nr_data += d[col] return nr_data def median(data, freq_col=1): """Compute the median of the 'th column of the values is . >>> chart_data.median([(10,20), (20,4), (30,5)], 0) 20 >>> chart_data.median([(10,20), (20,4), (30,5)], 1) 5. """ nr_data = _nr_data(data, freq_col) median_idx = nr_data / 2 i = 0 for d in data: i += d[freq_col] if i >= median_idx: return d raise Exception, "??? median ???" def cut_extremes(data, cutoff_percentage, freq_col=1): nr_data = _nr_data(data, freq_col) min_idx = nr_data * cutoff_percentage / 100.0 max_idx = nr_data * (100 - cutoff_percentage) / 100.0 r = [] i = 0 for d in data: if i < min_idx: if i + d[freq_col] >= min_idx: x = copy.deepcopy(d) x[freq_col] = x[freq_col] - (min_idx - i) r.append(x) i += d[freq_col] continue elif i + d[freq_col] >= max_idx: if i < max_idx and i + d[freq_col] >= max_idx: x = copy.deepcopy(d) x[freq_col] = x[freq_col] - (max_idx - i) r.append(x) break i += d[freq_col] r.append(d) return r def mean(data, val_col, freq_col): nr_data = 0 sum = 0 for d in data: sum += d[val_col] * d[freq_col] nr_data += d[freq_col] if nr_data == 0: raise IndexError, "data is empty" return sum / float(nr_data) def mean_samples(data, xcol, ycollist): """Create a sample list that contains the mean of the original list. >>> chart_data.mean_samples([ [1, 10, 15], [2, 5, 10], [3, 8, 33] ], 0, (1, 2)) [(1, 12.5), (2, 7.5), (3, 20.5)] """ out = [] numcol = len(ycollist) try: for elem in data: v = 0 for col in ycollist: v += elem[col] out.append( (elem[xcol], float(v) / numcol) ) except IndexError: raise IndexError, "bad data: %s,xcol=%d,ycollist=%s" % (data,xcol,ycollist) return out def stddev_samples(data, xcol, ycollist, delta = 1.0): """Create a sample list that contains the mean and standard deviation of the original list. Each element in the returned list contains following values: [MEAN, STDDEV, MEAN - STDDEV*delta, MEAN + STDDEV*delta]. >>> chart_data.stddev_samples([ [1, 10, 15, 12, 15], [2, 5, 10, 5, 10], [3, 32, 33, 35, 36], [4,16,66, 67, 68] ], 0, range(1,5)) [(1, 13.0, 2.1213203435596424, 10.878679656440358, 15.121320343559642), (2, 7.5, 2.5, 5.0, 10.0), (3, 34.0, 1.5811388300841898, 32.418861169915807, 35.581138830084193), (4, 54.25, 22.094965489902897, 32.155034510097103, 76.344965489902904)] """ out = [] numcol = len(ycollist) try: for elem in data: total = 0 for col in ycollist: total += elem[col] mean = float(total) / numcol variance = 0 for col in ycollist: variance += (mean - elem[col]) ** 2 stddev = math.sqrt(variance / numcol) * delta out.append( (elem[xcol], mean, stddev, mean-stddev, mean+stddev) ) except IndexError: raise IndexError, "bad data: %s,xcol=%d,ycollist=%s" % (data,xcol,ycollist) return out def nearest_match(data, col, val): min_delta = None match = None for d in data: if min_delta == None or abs(d[col] - val) < min_delta: min_delta = abs(d[col] - val) match = d pychart_util.warn("XXX ", match) return match PyChart-1.39/pychart/linear_coord.py0000644000175000017500000000241010354321345021135 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import coord import math import pychart_util class T(coord.T): def get_canvas_pos(self, size, val, min, max): return size * (val - min) / float(max - min) def get_tics(self, min, max, interval): v = [] x = min while x <= max: v.append(x) x += interval return v def get_min_max(self, dmin, dmax, interval): if not interval: if dmax == dmin: interval = 10 else: interval = 10 ** (float(int(math.log(dmax-dmin)/math.log(10)))) dmin = min(dmin, pychart_util.round_down(dmin, interval)) dmax = max(dmax, pychart_util.round_up(dmax, interval) + interval/2.0) return dmin, dmax, interval PyChart-1.39/pychart/version.py0000644000175000017500000000113710352125052020162 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # version = "1.39" copyright = "Copyright 1999-2006 Yasushi Saito" PyChart-1.39/pychart/x11canvas.py0000644000175000017500000000137610354321345020314 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import os import gs_frontend import theme import sys class T(gs_frontend.T): def close(self): gs_frontend.T.close(self) self.start_gs("-sDEVICE=x11") sys.stdin.readline() self.close_gs() PyChart-1.39/pychart/basecanvas.py0000644000175000017500000004466210354321416020621 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import math import sys import time import re import font import pychart_util import theme import version from scaling import * def _compute_bounding_box(points): """Given the list of coordinates (x,y), this procedure computes the smallest rectangle that covers all the points.""" (xmin, ymin, xmax, ymax) = (999999, 999999, -999999, -999999) for p in points: xmin = min(xmin, p[0]) xmax = max(xmax, p[0]) ymin = min(ymin, p[1]) ymax = max(ymax, p[1]) return (xmin, ymin, xmax, ymax) def _intersect_box(b1, b2): xmin = max(b1[0], b2[0]) ymin = max(b1[1], b2[1]) xmax = min(b1[2], b2[2]) ymax = min(b1[3], b2[3]) return (xmin, ymin, xmax, ymax) def invisible_p(x, y): """Return true if the point (X, Y) is visible in the canvas.""" if x < -499999 or y < -499999: return 1 return 0 def to_radian(deg): return deg*2*math.pi / 360.0 def midpoint(p1, p2): return ( (p1[0]+p2[0])/2.0, (p1[1]+p2[1])/2.0 ) active_canvases = [] InvalidCoord = 999999 class T(object): def __init__(self): global active_canvases self.__xmax = -InvalidCoord self.__xmin = InvalidCoord self.__ymax = -InvalidCoord self.__ymin = InvalidCoord self.__clip_box = (-InvalidCoord, -InvalidCoord, InvalidCoord, InvalidCoord) self.__clip_stack = [] self.__nr_gsave = 0 self.title = theme.title or re.sub("(.*)\\.py$", "\\1", sys.argv[0]) self.creator = theme.creator or "pychart %s" % (version.version,) self.creation_date = theme.creation_date or \ time.strftime("(%m/%d/%y) (%I:%M %p)") self.author = theme.author self.aux_comments = theme.aux_comments or "" active_canvases.append(self) def set_title(self, s): """Define the string to be shown in EPS/PDF "Title" field. The default value is the name of the script that creates the EPS/PDF file.""" self.title = s def set_creator(self, tag): """Define the string to be shown in EPS %%Creator or PDF Producer field. The default value is "pychart".""" self.creator = tag def set_creation_date(self, s): """Define the string to be shown in EPS/PDF "CreationDate" field. Defalt value of this field is the current time.""" self.creation_date = s def set_author(self, s): """Set the author string. Unless this method is called, the Author field is not output in EPS or PDF.""" self.author = s def add_aux_comments(self, s): """Define an auxiliary comments to be output to the file, just after the required headers""" self.aux_comments += s def close(self): """This method closes the canvas and writes contents to the associated file. Calling this procedure is optional, because Pychart calls this procedure for every open canvas on normal exit.""" for i in range(0, len(active_canvases)): if active_canvases[i] == self: del active_canvases[i] return def open_output(self, fname): """Open the output file FNAME. Returns tuple (FD, NEED_CLOSE), where FD is a file (or file-like) object, and NEED_CLOSE is a boolean flag that tells whether FD.close() should be called after finishing writing to the file. FNAME can be one of the three things: (1) None, in which case (sys.stdout, False) is returned. (2) A file-like object, in which case (fname, False) is returned. (3) A string, in which case this procedure opens the file and returns (fd, True).""" if not fname: return (sys.stdout, False) elif isinstance(fname, str): return (file(fname, "wb"), True) else: if not hasattr(fname, "write"): raise Exception, "Expecting either a filename or a file-like object, but got %s" % fname return (fname, False) def setbb(self, x, y): """Call this method when point (X,Y) is to be drawn in the canvas. This methods expands the bounding box to include this point.""" self.__xmin = min(self.__xmin, max(x, self.__clip_box[0])) self.__xmax = max(self.__xmax, min(x, self.__clip_box[2])) self.__ymin = min(self.__ymin, max(y, self.__clip_box[1])) self.__ymax = max(self.__ymax, min(y, self.__clip_box[3])) def fill_with_pattern(self, pat, x1, y1, x2, y2): if invisible_p(x2, y2): return self.comment("FILL pat=%s (%d %d)-(%d %d)\n" % (pat, x1, y1, x2, y2)) self.set_fill_color(pat.bgcolor) self._path_polygon([(x1, y1), (x1, y2), (x2, y2), (x2, y1)]) self.fill() pat.draw(self, x1, y1, x2, y2) self.comment("end FILL.\n") def _path_polygon(self, points): "Low-level polygon-drawing routine." (xmin, ymin, xmax, ymax) = _compute_bounding_box(points) if invisible_p(xmax, ymax): return self.setbb(xmin, ymin) self.setbb(xmax, ymax) self.newpath() self.moveto(xscale(points[0][0]), yscale(points[0][1])) for point in points[1:]: self.lineto(xscale(point[0]), yscale(point[1])) self.closepath() def polygon(self, edge_style, pat, points, shadow = None): """Draw a polygon with EDGE_STYLE, fill with PAT, and the edges POINTS. POINTS is a sequence of coordinates, e.g., ((10,10), (15,5), (20,8)). SHADOW is either None or a tuple (XDELTA, YDELTA, fillstyle). If non-null, a shadow of FILLSTYLE is drawn beneath the polygon at the offset of (XDELTA, YDELTA).""" if pat: self.comment("POLYGON points=[%s] pat=[%s]" % (str(points), str(pat))) (xmin, ymin, xmax, ymax) = _compute_bounding_box(points) if shadow: xoff, yoff, shadow_pat = shadow self.gsave() self._path_polygon(map(lambda p, xoff=xoff, yoff=yoff: (p[0]+xoff, p[1]+yoff), points)) self.clip_sub() self.fill_with_pattern(shadow_pat, xmin+xoff, ymin+yoff, xmax+xoff, ymax+yoff) self.grestore() self.gsave() self._path_polygon(points) self.clip_sub() self.fill_with_pattern(pat, xmin, ymin, xmax, ymax) self.grestore() if edge_style: self.comment("POLYGON points=[%s] edge=[%s]" % (str(points), str(edge_style))) self.set_line_style(edge_style) self._path_polygon(points) self.stroke() def set_background(self, pat, x1, y1, x2, y2): xmax, xmin, ymax, ymin = self.__xmax, self.__xmin, self.__ymax, self.__ymin self.rectangle(None, pat, x1, y1, x2, y2) self.__xmax, self.__xmin, self.__ymax, self.__ymin = xmax, xmin, ymax, ymin def rectangle(self, edge_style, pat, x1, y1, x2, y2, shadow = None): """Draw a rectangle with EDGE_STYLE, fill with PAT, and the bounding box (X1, Y1, X2, Y2). SHADOW is either None or a tuple (XDELTA, YDELTA, fillstyle). If non-null, a shadow of FILLSTYLE is drawn beneath the polygon at the offset of (XDELTA, YDELTA).""" self.polygon(edge_style, pat, [(x1,y1), (x1,y2), (x2,y2), (x2, y1)], shadow) def _path_ellipsis(self, x, y, radius, ratio, start_angle, end_angle): self.setbb(x - radius, y - radius*ratio) self.setbb(x + radius, y + radius*ratio) oradius = nscale(radius) centerx, centery = xscale(x), yscale(y) startx, starty = centerx+oradius * math.cos(to_radian(start_angle)), \ centery+oradius * math.sin(to_radian(start_angle)) self.moveto(centerx, centery) if start_angle % 360 != end_angle % 360: self.moveto(centerx, centery) self.lineto(startx, starty) else: self.moveto(startx, starty) self.path_arc(xscale(x), yscale(y), nscale(radius), ratio, start_angle, end_angle) self.closepath() def ellipsis(self, line_style, pattern, x, y, radius, ratio = 1.0, start_angle=0, end_angle=360, shadow=None): """Draw an ellipsis with line_style and fill PATTERN. The center is \ (X, Y), X radius is RADIUS, and Y radius is RADIUS*RATIO, whose \ default value is 1.0. SHADOW is either None or a tuple (XDELTA, YDELTA, fillstyle). If non-null, a shadow of FILLSTYLE is drawn beneath the polygon at the offset of (XDELTA, YDELTA).""" if invisible_p(x + radius, y + radius*ratio): return if pattern: if shadow: x_off, y_off, shadow_pat = shadow self.gsave() self.newpath() self._path_ellipsis(x+x_off, y+y_off, radius, ratio, start_angle, end_angle) self.clip_sub() self.fill_with_pattern(shadow_pat, x-radius*2+x_off, y-radius*ratio*2+y_off, x+radius*2+x_off, y+radius*ratio*2+y_off) self.grestore() self.gsave() self.newpath() self._path_ellipsis(x, y, radius, ratio, start_angle, end_angle) self.clip_sub() self.fill_with_pattern(pattern, (x-radius*2), (y-radius*ratio*2), (x+radius*2), (y+radius*ratio*2)) self.grestore() if line_style: self.set_line_style(line_style) self.newpath() self._path_ellipsis(x, y, radius, ratio, start_angle, end_angle) self.stroke() def clip_ellipsis(self, x, y, radius, ratio = 1.0): """Create an elliptical clip region. You must call endclip() after you completed drawing. See also the ellipsis method.""" self.gsave() self.newpath() self.moveto(xscale(x)+nscale(radius), yscale(y)) self.path_arc(xscale(x), yscale(y), nscale(radius), ratio, 0, 360) self.closepath() self.__clip_stack.append(self.__clip_box) self.clip_sub() def clip_polygon(self, points): """Create a polygonal clip region. You must call endclip() after you completed drawing. See also the polygon method.""" self.gsave() self._path_polygon(points) self.__clip_stack.append(self.__clip_box) self.__clip_box = _intersect_box(self.__clip_box, _compute_bounding_box(points)) self.clip_sub() def clip(self, x1, y1, x2, y2): """Activate a rectangular clip region, (X1, Y1) - (X2, Y2). You must call endclip() after you completed drawing. canvas.clip(x,y,x2,y2) draw something ... canvas.endclip() """ self.__clip_stack.append(self.__clip_box) self.__clip_box = _intersect_box(self.__clip_box, (x1, y1, x2, y2)) self.gsave() self.newpath() self.moveto(xscale(x1), yscale(y1)) self.lineto(xscale(x1), yscale(y2)) self.lineto(xscale(x2), yscale(y2)) self.lineto(xscale(x2), yscale(y1)) self.closepath() self.clip_sub() def endclip(self): """End the current clip region. When clip calls are nested, it ends the most recently created crip region.""" self.__clip_box = self.__clip_stack[-1] del self.__clip_stack[-1] self.grestore() def curve(self, style, points): for p in points: self.setbb(p[0], p[1]) self.newpath() self.set_line_style(style) self.moveto(xscale(points[0][0]), xscale(points[0][1])) i = 1 n = 1 while i < len(points): if n == 1: x2 = points[i] n += 1 elif n == 2: x3 = points[i] n += 1 elif n == 3: x4 = midpoint(x3, points[i]) self.curveto(xscale(x2[0]), xscale(x2[1]), xscale(x3[0]), xscale(x3[1]), xscale(x4[0]), xscale(x4[1])) n = 1 i += 1 if n == 1: pass if n == 2: self.lineto(xscale(x2[0]), xscale(x2[1])) if n == 3: self.curveto(xscale(x2[0]), xscale(x2[1]), xscale(x2[0]), xscale(x2[1]), xscale(x3[0]), xscale(x3[1])) self.stroke() def line(self, style, x1, y1, x2, y2): if not style: return if invisible_p(x2, y2) and invisible_p(x1, y1): return self.setbb(x1, y1) self.setbb(x2, y2) self.newpath() self.set_line_style(style) self.moveto(xscale(x1), yscale(y1)) self.lineto(xscale(x2), yscale(y2)) self.stroke() def lines(self, style, segments): if not style: return (xmin, ymin, xmax, ymax) = _compute_bounding_box(segments) if invisible_p(xmax, ymax): return self.setbb(xmin, ymin) self.setbb(xmax, ymax) self.newpath() self.set_line_style(style) self.moveto(xscale(segments[0][0]), xscale(segments[0][1])) for i in range(1, len(segments)): self.lineto(xscale(segments[i][0]), yscale(segments[i][1])) self.stroke() def _path_round_rectangle(self, x1, y1, x2, y2, radius): self.moveto(xscale(x1 + radius), yscale(y1)) self.lineto(xscale(x2 - radius), yscale(y1)) self.path_arc(xscale(x2-radius), yscale(y1+radius), nscale(radius), 1, 270, 360) self.lineto(xscale(x2), yscale(y2-radius)) self.path_arc(xscale(x2-radius), yscale(y2-radius), nscale(radius), 1, 0, 90) self.lineto(xscale(x1+radius), yscale(y2)) self.path_arc(xscale(x1 + radius), yscale(y2 - radius), nscale(radius), 1, 90, 180) self.lineto(xscale(x1), xscale(y1+radius)) self.path_arc(xscale(x1 + radius), yscale(y1 + radius), nscale(radius), 1, 180, 270) def round_rectangle(self, style, fill, x1, y1, x2, y2, radius, shadow=None): """Draw a rectangle with rounded four corners. Parameter specifies the radius of each corner.""" if invisible_p(x2, y2): return self.setbb(x1, y1) self.setbb(x2, y2) if fill: if shadow: x_off, y_off, shadow_fill = shadow self.gsave(); self.newpath() self._path_round_rectangle(x1+x_off, y1+y_off, x2+x_off, y2+y_off, radius) self.closepath() self.clip_sub() self.fill_with_pattern(shadow_fill, x1+x_off, y1+y_off, x2+x_off, y2+y_off) self.grestore() self.gsave(); self.newpath() self._path_round_rectangle(x1, y1, x2, y2, radius) self.closepath() self.clip_sub() self.fill_with_pattern(fill, x1, y1, x2, y2) self.grestore() if style: self.set_line_style(style) self.newpath() self._path_round_rectangle(x1, y1, x2, y2, radius) self.closepath() self.stroke() def show(self, x, y, str): global out y_org = y org_str = str if invisible_p(x, y): return (xmin, xmax, ymin, ymax) = font.get_dimension(str) # rectangle(line_style.default, None, x+xmin, y+ymin, x+xmax, y+ymax) # ellipsis(line_style.default, None, x, y, 1) self.setbb(x+xmin, y+ymin) self.setbb(x+xmax, y+ymax) (halign, valign, angle) = font.get_align(str) base_x = x base_y = y # Handle vertical alignment if valign == "B": y = font.unaligned_text_height(str) elif valign == "T": y = 0 elif valign == "M": y = font.unaligned_text_height(str) / 2.0 (xmin, xmax, ymin, ymax) = font.get_dimension(org_str) self.setbb(x+xmin, y_org+y+ymin) self.setbb(x+xmax, y_org+y+ymax) itr = font.text_iterator(None) max_width = 0 lines = [] for line in str.split('\n'): cur_width = 0 cur_height = 0 itr.reset(line) strs = [] while 1: elem = itr.next() if not elem: break (font_name, size, line_height, color, _h, _v, _a, str) = elem cur_width += font.line_width(font_name, size, str) max_width = max(cur_width, max_width) cur_height = max(cur_height, line_height) # replace '(' -> '\(', ')' -> '\)' to make # Postscript string parser happy. str = str.replace("(", "\\(") str = str.replace(")", "\\)") strs.append((font_name, size, color, str)) lines.append((cur_width, cur_height, strs)) for line in lines: cur_width, cur_height, strs = line cur_y = y - cur_height y = y - cur_height self.comment("cury: %d hei %d str %s\n" % (cur_y, cur_height, strs)) if halign == 'C': cur_x = -cur_width/2.0 elif halign == 'R': cur_x = -cur_width else: cur_x = 0 rel_x, rel_y = pychart_util.rotate(cur_x, cur_y, angle) self.text_begin() self.text_moveto(xscale(base_x + rel_x), yscale(base_y + rel_y), angle) for segment in strs: font_name, size, color, str = segment self.text_show(font_name, nscale(size), color, str) self.text_end() PyChart-1.39/pychart/fill_style.py0000644000175000017500000002347410354321374020662 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Jockey is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Jockey is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import pychart_util import color import line_style import chart_object import object_set import types import theme import fill_style_doc from pychart_types import * from scaling import * _keys = { "bgcolor" : (color.T, color.white, "The background color."), "line_style": (line_style.T, line_style.default, pychart_util.line_desc), "line_interval": (NumberType, 3, "The interval between successive stitch lines.") } class T(chart_object.T): __doc__ = fill_style_doc.doc keys = _keys ##AUTOMATICALLY GENERATED ##END AUTOMATICALLY GENERATED def __str__(self): s = name_table().lookup(self) if s: return s return "" % \ (self.bgcolor, self.line_style, self.line_interval) class Plain(T): """This class just fills the region with solid background color. Attributes line_style and line_interval are ignored.""" def draw(self, can, x1, y1, x2, y2): pass class Diag(T): "This class fills the region with diagonal lines." def draw(self, can, x1, y1, x2, y2): line_width = self.line_style.width interval = self.line_interval * 1.414 x1 -= line_width y1 -= line_width x2 += line_width y2 += line_width length = max(y2 - y1, x2 - x1) curx = x1 - length while curx < x2: can.line(self.line_style, curx, y1, curx+length, y1+length) curx += interval class Rdiag(T): """Fills the region with diagonal lines, but tilted in the opposite direction from fill_style.Diag.""" def draw(self, can, x1, y1, x2, y2): line_width = self.line_style.width interval = self.line_interval * 1.414 x1 -= line_width y1 -= line_width x2 += line_width y2 += line_width length = max(y2 - y1, x2 - x1) curx = x1 while curx < x2 + length: can.line(self.line_style, curx, y1, curx-length, y1+length) curx += interval class Vert(T): "Fills the region with vertical lines" def draw(self, can, x1, y1, x2, y2): interval = self.line_interval curx = x1 while curx < x2: can.line(self.line_style, curx, y1, curx, y2) curx += interval class Horiz(T): "Fills the region with horizontal lines" def draw(self, can, x1, y1, x2, y2): interval = self.line_interval cury = y1 while cury < y2: can.line(self.line_style, x1, cury, x2, cury) cury += interval class Stitch(T): "Fills the region with horizontal and vertical lines." def draw(self, can, x1, y1, x2, y2): interval = self.line_interval cury = y1 while cury < y2: can.line(self.line_style, x1, cury, x2, cury) cury += interval curx = x1 while curx < x2: can.line(self.line_style, curx, y1, curx, y2) curx += interval class Wave(T): "Fills the region with horizontal wavy lines." def draw(self, can, x1, y1, x2, y2): x1 = xscale(x1) x2 = xscale(x2) y1 = yscale(y1) y2 = yscale(y2) line_width = nscale(self.line_style.width) interval = nscale(self.line_interval) can.set_line_style(self.line_style) x1 -= line_width x2 += line_width cury = y1 half = interval/2.0 while cury < y2: curx = x1 can.newpath() can.moveto(curx, cury) while curx < x2: can.lineto(curx + half, cury + half) can.lineto(curx + interval, cury) curx += interval can.stroke() cury += interval class Vwave(T): """Fills the region with vertical wavy lines.""" def draw(self, can, x1, y1, x2, y2): x1 = xscale(x1) x2 = xscale(x2) y1 = yscale(y1) y2 = yscale(y2) line_width = nscale(self.line_style.width) interval = nscale(self.line_interval) can.set_line_style(self.line_style) y1 -= line_width y2 += line_width curx = x1 half = interval/2.0 while curx < x2: cury = y1 can.newpath() can.moveto(curx, cury) while cury < y2: can.lineto(curx + half, cury + half) can.lineto(curx, cury + interval) cury += interval can.stroke() curx += interval class Lines(T): """Fills the region with a series of short line segments.""" def draw(self, can, x1, y1, x2, y2): interval = nscale(self.line_interval) cury = y1 j = 0 while cury < y2: curx = x1 if j % 2 == 1: curx += interval/2.0 while curx < x2: can.line(self.line_style, curx, cury, curx+interval/2.0, cury) curx += interval * 1.5 j += 1 cury += interval default = Plain() color_standards = object_set.T() grayscale_standards = object_set.T() def _intern_both(style): global color_standards, grayscale_standards color_standards.add(style) grayscale_standards.add(style) return style def _intern_color(style): global color_standards, grayscale_standards color_standards.add(style) return style def _intern_grayscale(style): global color_standards, grayscale_standards grayscale_standards.add(style) return style black = _intern_both(Plain(bgcolor=color.gray_scale(0.0), line_style=None)) red = _intern_color(Plain(bgcolor=color.red)) darkseagreen = _intern_color(Plain(bgcolor=color.darkseagreen)) blue = _intern_color(Plain(bgcolor=color.blue)) aquamarine1 = _intern_color(Plain(bgcolor=color.aquamarine1)) gray70 = _intern_both(Plain(bgcolor=color.gray70, line_style=None)) brown = _intern_color(Plain(bgcolor=color.brown)) darkorchid = _intern_color(Plain(bgcolor=color.darkorchid)) diag = _intern_both(Diag(line_style=line_style.T(cap_style=2))) green = _intern_color(Plain(bgcolor=color.green)) gray50 = _intern_both(Plain(bgcolor=color.gray50, line_style=None)) white = _intern_both(Plain(bgcolor=color.gray_scale(1.0), line_style=None)) goldenrod = _intern_color(Plain(bgcolor=color.goldenrod)) rdiag = _intern_both(Rdiag(line_style=line_style.T(cap_style=2))) vert = _intern_both(Vert(line_interval=1.8)) gray30 = _intern_both(Plain(bgcolor=color.gray30, line_style=None)) gray20 = _intern_both(Plain(bgcolor=color.gray20, line_style=None)) gray10 = _intern_both(Plain(bgcolor=color.gray10, line_style=None)) diag2 = _intern_both(Diag(line_style=line_style.T(width=3, cap_style=2), line_interval=6)) rdiag2 = _intern_both(Rdiag(line_style=line_style.T(width=3, cap_style=2), line_interval=6)) yellow = _intern_color(Plain(bgcolor=color.yellow)) diag3 = _intern_both(Diag(line_style=line_style.T(width=3, color=color.gray50, cap_style=2), line_interval=6)) horiz = _intern_both(Horiz(line_interval=1.8)) gray90 = _intern_both(Plain(bgcolor=color.gray90, line_style=None)) rdiag3 = _intern_both(Rdiag(line_style=line_style.T(width=3, color=color.gray50, cap_style=2), line_interval=6)) wave = _intern_both(Wave(line_style=line_style.T(cap_style=2, join_style=1))) vwave = _intern_both(Vwave(line_style=line_style.T(cap_style=2, join_style=1))) stitch = _intern_both(Stitch(line_style=line_style.T(cap_style=2, join_style=1))) lines = _intern_both(Lines(line_style=line_style.T())) diag_fine = _intern_both(Diag(line_style=line_style.T(width=0.75,cap_style=2), line_interval = 1.5)) diag2_fine = _intern_both(Diag(line_style=line_style.T(width=0.75, cap_style=2), line_interval=1.5)) diag3_fine = _intern_both(Diag(line_style=line_style.T(width=0.75, color = color.gray50, cap_style=2), line_interval=1.5)) rdiag_fine = _intern_both(Rdiag(line_style=line_style.T(width=0.75,cap_style=2), line_interval = 1.5)) rdiag2_fine = _intern_both(Rdiag(line_style=line_style.T(width=0.75, cap_style=2), line_interval=1.5)) rdiag3_fine = _intern_both(Rdiag(line_style=line_style.T(width=0.75, color = color.gray50, cap_style=2), line_interval=1.5)) horiz_fine = _intern_both(Horiz(line_interval=1.5)) vert_fine = _intern_both(Vert(line_interval=1.5)) # # Fill styles for color charts. # standards = None _name_table = None def init(): global standards, _name_table if theme.use_color: standards = color_standards else: standards = grayscale_standards _name_table = None def name_table(): global _name_table if not _name_table: _name_table = pychart_util.symbol_lookup_table(globals(), standards) return _name_table init() theme.add_reinitialization_hook(init) PyChart-1.39/Makefile0000644000175000017500000000107010354321345016112 0ustar santiagosantiago00000000000000SUBDIRS=doc demos PyChart dist: python setup.py sdist clean: rm -f *~ -for dir in $(SUBDIRS); do $(MAKE) -C$$dir clean; done WWW_DIR=$(HOME)/gna/pychart install: #rm -f $(WWW_DIR)/doc/* #rm -f $(WWW_DIR)/examples/* cp -r doc/pychart/* $(WWW_DIR)/doc cp -r doc/examples/* $(WWW_DIR)/examples baz changelog >$(WWW_DIR)/ChangeLog copy: rm -rf ,,download mkdir ,,download (cd doc; tar czf ../,,download/pychart-doc.tar.gz pychart) cp dist/PyChart-1.38.tar.gz ,,download rsync --delete -avr --rsh="ssh" ,,download/* ysaito@download.gna.org:/upload/pychart PyChart-1.39/demos/0000755000175000017500000000000010352125054015560 5ustar santiagosantiago00000000000000PyChart-1.39/demos/rangetest.py0000644000175000017500000000257410354321416020140 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * data = [ (0, 10, 30, 40, 60), (10, 20, 40, 50, 55), (20, 10, 35, 38, 43), (30, 8, 30, 35, 39), (40, 8, 20, 28, 39) ] ar = area.T(x_axis = axis.X(label="X axis"), y_grid_interval = 10, y_grid_style = line_style.white, y_axis = axis.Y(label="Y axis"), y_grid_over_plot=1, legend = legend.T()) if theme.use_color: colors = [ fill_style.darkseagreen, fill_style.white, fill_style.brown ] else: colors = [ fill_style.gray90, fill_style.white, fill_style.gray50 ] ar.add_plot(range_plot.T(label="foo", data=data, fill_style = colors[0])) ar.add_plot(range_plot.T(label="bar", data=data, min_col=2, max_col=3, fill_style = colors[1])) ar.add_plot(range_plot.T(label="baz", data=data, min_col=3, max_col=4, fill_style = colors[2])) ar.draw() PyChart-1.39/demos/failure.csv0000644000175000017500000001112410354321345017726 0ustar santiagosantiago00000000000000-10,549.322542,554.0771826,544,550.5740128,1526 0,550.1689208,558.0013579,531,550.2591991,1536 10,551.0439893,548.5938002,528,581.7291869,1546 20,551.3170268,549.7579841,520,582.4131114,1556 30,551.4488436,535.5779497,531,581.4612781,1566 40,551.0648716,553.7668505,561,576.7626846,1576 50,552.4073557,562.4751056,552,570.3366522,1586 60,553.6183998,553.2065355,532.6959698,564.7836345,1596 70,553.626403,555.1535749,546.7355281,556.2261953,1606 80,553.238784,564.4926586,546.8560702,548.9216739,1616 90,551.6243917,564.4045969,554.5733306,553.7718142,1626 100,553.3043693,577.5023826,543.2137624,564.0693525,1636 110,555.5334771,570.3642804,558.4198872,547.2747365,1646 120,558.1924476,585.3389807,555.2272059,558.7711288,1656 130,559.1810813,583.8276876,554.3646553,560.4275611,1666 140,557.6219669,578.5476411,533.5447327,573.322894,1676 150,557.9429458,571.7778854,527.2044784,546.6651863,1686 160,557.0798402,569.3191677,537.9334991,544.5470956,1696 170,558.2354731,554.0718177,547.0924164,541.0497262,1706 180,562.5319411,554.2713205,561.719106,560.7482854,1716 190,562.6711657,548.9081592,550.8806671,575.4409863,1726 200,557.0655415,561.7577889,536.3039593,590.6631478,1736 210,556.4791832,570.7903599,531.4283199,547.0590161,1746 220,557.3116405,567.4639887,538.018888,545.328665,1756 230,556.943354,568.0384624,550.6461196,538.7110776,1766 240,559.5863364,560.1887897,526.180926,557.716471,1776 250,565.5517187,557.5975677,531.9427893,535.2963572,1786 260,564.3353422,555.2334648,539.7710251,529.7784764,1796 271,561.03751,564.1424772,568.0610528,525.1544124,1807 281,557.3249861,568.1231924,570.4277075,538.6915869,1817 290,556.9825896,569.887807,571.5334557,530.7251693,1826 300,556.1015176,534.6388379,569.6606387,524.1458113,1836 323,509.2898234,526.2720843,448.3444622,558.9739786,1859 323,509.2898234,527.0580779,375.6306656,552.7968822,1859 330,505.5775354,521.0963665,376.7816339,533.0247462,1866 342,511.6311535,487.7999614,381.3608494,542.389553,1878 350,518.9029817,486.7509025,415.1419046,549.2414235,1886 360,518,476.0735013,431.9027709,561.8869093,1896 370,544.0980955,495.8921263,451.6400704,564.0144182,1906 380,540.8236062,516.7251178,441.5587784,545.5167003,1916 390,542.7851785,527.0228329,435.3481338,563.2581325,1926 400,548.004636,499.2902163,439.037595,566.4507763,1936 410,541.8884887,508.8968406,432.0884451,560.0250109,1946 420,537.148991,521.9017869,418.4552833,547.1200663,1956 430,545.5380131,534.8341638,453.6292633,553.1202376,1966 440,552.180058,519.0678006,454.673405,539.2912378,1976 450,558.6886075,501.2371496,427.0939687,546.5907837,1986 460,547.2345643,503.8622147,432.1395796,575.8022993,1996 470,549.0391426,498.3982328,437.7675681,569.3698743,2006 480,548.5608974,514.5806241,443.1246291,560.5718772,2016 490,550.7041032,511.0390115,425.3368387,567.0224593,2026 500,551.6297248,504.9708657,435.6104259,573.3356526,2036 510,549.2239557,475.169685,456.6668123,556.6997747,2046 520,549.5613061,475.5112106,454.9469473,567.1613249,2056 530,547.2373294,491.4731455,412.0560916,584.6841656,2066 540,539.2986844,500.5239804,426.2600493,543.7680839,2076 550,540.3599609,509.6507499,423.0646928,561.452403,2086 560,541.7090954,507.5446361,438.7697517,548.5118602,2096 570,546.102404,494.1262234,430.5040031,544.3222222,2106 580,548.7302097,504.683931,436.7848812,541.0972195,2116 590,544.0771826,491.8678371,446.9912979,542.2923072,2126 600,548.0013579,488.1085506,431.4294805,566.7874443,2136 610,538.5938002,483.9920398,425.3750061,572.3962968,2146 620,539.7579841,495.7153117,416.7606362,587.9047767,2156 630,525.5779497,534.6686217,409.4120369,588.5593077,2166 640,553.7668505,552.6082713,479.7660942,582.4234865,2176 650,562.4751056,532.6959698,507.7250702,575.9998553,2186 660,563.2065355,546.7355281,525.2127134,536.2479212,2196 670,575.1535749,546.8560702,559.3367363,542.8119938,2206 680,564.4926586,554.5733306,527.0536364,540.1921498,2216 690,564.4045969,543.2137624,537.3757216,544.3085319,2226 700,577.5023826,558.4198872,522.8112533,561.4163827,2236 710,560.3642804,555.2272059,534.9607244,561.5123424,2246 720,575.3389807,554.3646553,535.9114479,544.2998774,2256 730,573.8276876,533.5447327,542.8645855,556.1971323,2266 740,568.5476411,527.2044784,535.1628036,586.5944751,2276 750,561.7778854,537.9334991,536.9907376,576,2286 760,559.3191677,547.0924164,545.5965264,559,2296 770,544.0718177,561.719106,548.2674272,564,2306 780,554.2713205,550.8806671,552.5211405,563,2316 790,548.9081592,536.3039593,533.234,578,2326 800,551.7577889,531.4283199,540.234,557,2336 810,550.7903599,538.018888,548.834,532,2346 820,547.4639887,550.6461196,525.234,563,2356 PyChart-1.39/demos/date.py0000644000175000017500000000234110354321416017051 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import sys import datetime from pychart import * def date_to_ordinal(s): month, day, year = map(int, s.split("/")) return datetime.date(year, month, day).toordinal() def format_date(ordinal): d = datetime.date.fromordinal(int(ordinal)) return "/a60{}" + d.strftime("%b %d, %y") data = [["10/5/1983", 10], ["3/5/1984", 15], ["11/10/1984", 16], ["2/22/1985", 20]] data = chart_data.transform(lambda x: [date_to_ordinal(x[0]), x[1]], data) ar = area.T(x_coord = category_coord.T(data, 0), y_range = (0, None), x_axis = axis.X(label = "Date", format = format_date), y_axis = axis.Y(label = "Value")) ar.add_plot(bar_plot.T(data = data)) ar.draw() PyChart-1.39/demos/colors.py0000644000175000017500000000250110354321345017434 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import chartdemo import re x = 100 y = 500 can = canvas.default_canvas() def draw_rect(color): global x, y name = pychart.doc_support.stringify_value(color) name = re.sub("color\\.", "", name) name = pychart.doc_support.break_string(name) fill = fill_style.Plain(bgcolor = color) can.rectangle(line_style.default, fill, x, y, x+15, y+15) height = font.text_height(name)[0] + 5 tb = text_box.T(text="/hL" + name, loc=(x, y-height), line_style=None) x = x + 50 tb.draw() for style in color.standards.list(): if (not theme.use_color and style.r == style.g and style.g == style.b) or \ theme.use_color: draw_rect(style) if x >= chartdemo.MaxWidth: x=100 y=y-60 PyChart-1.39/demos/Makefile0000644000175000017500000000257710352124714017235 0ustar santiagosantiago00000000000000# Works only for gmake. # # Just typing "make" creates all eps, pdf, color eps, color pdf files. # # SAMPLEFILES=$(shell python ./list_sources.py) PSFILES=$(SAMPLEFILES:.py=.eps) PDFFILES=$(SAMPLEFILES:.py=.pdf) COLOR_PSFILES=$(SAMPLEFILES:.py=-c.eps) COLOR_PDFFILES=$(SAMPLEFILES:.py=-c.pdf) COLOR_PNGFILES=$(SAMPLEFILES:.py=-c.png) PNGFILES=$(SAMPLEFILES:.py=.png) SVGFILES=$(SAMPLEFILES:.py=.svg) all: $(PSFILES) $(PDFFILES) $(COLOR_PSFILES) $(COLOR_PDFFILES) $(COLOR_PNGFILES) ps: $(PSFILES) pdf: $(PDFFILES) svg: $(SVGFILES) colorps: $(COLOR_PSFILES) colorpdf: $(COLOR_PDFFILES) png: $(PNGFILES) colorpng: $(COLOR_PNGFILES) regression: all for psfile in *.eps; do echo $$psfile; ps2ps $$psfile /dev/null; done clean: rm -f *.eps *~ *.pyc *.ps foo.* *.bak *.gif *.png *.pdf *.svg PYTHON?=python #PYTHON=jython #PYTHON=python2 coverage.py -x %.eps: %.py PYTHONPATH=.. PYCHART_OPTIONS="output=$@" $(PYTHON) $*.py %.pdf: %.py PYTHONPATH=.. PYCHART_OPTIONS="output=$@" $(PYTHON) $*.py %.svg: %.py PYTHONPATH=.. PYCHART_OPTIONS="output=$@" $(PYTHON) $*.py %-c.eps: %.py PYTHONPATH=.. PYCHART_OPTIONS="output=$@ color=yes" $(PYTHON) $*.py %-c.pdf: %.py PYTHONPATH=.. PYCHART_OPTIONS="output=$@ color=yes" $(PYTHON) $*.py %.png: %.py PYTHONPATH=.. PYCHART_OPTIONS="scale=2 output=$@" $(PYTHON) $*.py %-c.png: %.py PYTHONPATH=.. PYCHART_OPTIONS="scale=2 output=$@ color=yes" $(PYTHON) $*.py PyChart-1.39/demos/unevenbars.py0000644000175000017500000000341510354321345020310 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [(10, 20, 30, 5), (20, 65, 33, 5), (30, 55, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3), (60, 75, 30, 5), (70, 80, 42, 5), (80, 62, 32, 5), (90, 42, 39, 5), (100, 32, 39, 4)] # The attribute y_coord_system="category" tells that the Y axis values # should be taken from samples, y_category_col'th column of # y_category_data. Thus, in this example, Y values will be # [40,50,60,70,80]. ar = area.T(y_coord = category_coord.T(data[3:8], 0), x_grid_style=line_style.gray50_dash1, x_grid_interval=20, x_range = (0,100), x_axis=axis.X(label="X label"), y_axis=axis.Y(label="Y label"), bg_style = fill_style.gray90, border_line_style = line_style.default, legend = legend.T(loc=(80,10))) # Below call sets the default attributes for all bar plots. chart_object.set_defaults(bar_plot.T, direction="horizontal", data=data) ar.add_plot(bar_plot.T(label="foo", width=3, cluster_sep=2, cluster=(0,3))) ar.add_plot(bar_plot.T(label="bar", width=7, cluster_sep=1, hcol=2, cluster=(1,3))) ar.add_plot(bar_plot.T(label="baz", width=5, hcol=3, cluster=(2,3))) ar.draw() PyChart-1.39/demos/tocsturbo.py0000644000175000017500000000414610354321345020166 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib def create_line_plot(label, ycol): return line_plot.T(label=label, tick_mark=tocslib.get_tick_mark(label), line_style=tocslib.get_line_style(label), data=data, ycol=ycol) def create_graph(data): ar = area.T(size=(tocslib.width, tocslib.height), x_range = (1,3), x_axis = axis.X(label="/bNumber of nodes with fast disks"), y_axis = axis.Y(label="/bIncrease in\nMessages//second", label_offset=(tocslib.xlabel_offset, None)), legend=legend.T()) ar.add_plot(create_line_plot("D4", 2), create_line_plot("D2", 1), create_line_plot("S4", 5), create_line_plot("S2", 4), create_line_plot("R", 3)) return ar data = chart_data.read_str(" ", "0 0 0 0 0 0 0", "1 45 63 2 9 30", "2 118 133 3 20 53", "3 174 194 3 31 71") ar = create_graph(data) ar.y_range = (0,200) ar.y_axis.tic_interval=50 ar.legend=None ar.draw() tocslib.label(ar, "(a)").draw() data = chart_data.read_str(" ", "0 0 0 0 0 0 0", "1 10 26.5 2 4 9", "2 29 53 3 10 18", "3 48 79 3 16 28") ar = create_graph(data) ar.y_range = (0,100) ar.y_axis.label=None ar.y_axis.tic_interval=25 ar.loc = tocslib.loc2 ar.draw() tocslib.label(ar, "(b)").draw() PyChart-1.39/demos/tocslib.py0000644000175000017500000000652510354321345017604 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import copy width=pychart_util.inch_to_point(1.7) height=pychart_util.inch_to_point(1.2) loc2 = (width+36, 0) def label(ar, text): return text_box.T(text=text, line_style = None, loc=(ar.loc[0]+ar.size[0]/2, ar.loc[1]-40)) tickSize=3 lWidth=1.2 def get_tick_mark(p): if p == "PN": return tick_mark.Diamond(size=tickSize) elif p == "PRV": return tick_mark.Triangle(size=tickSize) elif p == "PR": return tick_mark.X(size=tickSize*1.2,line_style=line_style.T(width=1)) elif p == "SP" or p == "SM": return tick_mark.Square(size=tickSize) elif p == "D4": return tick_mark.Diamond(size=tickSize) elif p == "D2": return tick_mark.DownTriangle(size=tickSize) elif p == "D1": return tick_mark.Square(size=tickSize) elif p == "R": return tick_mark.Circle(size=tickSize) elif p == "S4": return tick_mark.Diamond(size=tickSize) elif p == "S2": return tick_mark.Plus(size=tickSize) elif p == "S1": return tick_mark.Square(size=tickSize) else: return None #else: # pychart_util.error("tick_mark:", p) greyscale_line_styles = { "PN" : line_style.T(width=lWidth), "PRV": line_style.T(width=lWidth,color=color.gray50), "PR": line_style.T(width=lWidth,dash=line_style.dash1), "D4": line_style.T(width=lWidth), "D2": line_style.T(width=lWidth,dash=line_style.dash1, color=color.gray70), "D1": line_style.T(width=lWidth,dash=line_style.dash2), "S4": line_style.T(width=lWidth), "S2": line_style.T(width=lWidth,dash=line_style.dash1,color=color.gray70), "S1": line_style.T(width=lWidth,dash=line_style.dash2,color=color.gray70), "R": line_style.T(width=lWidth,color=color.gray50), "SM": line_style.T(width=lWidth), "SP": line_style.T(width=lWidth), } def hack(l): x = copy.deepcopy(l) x.width = lWidth return x color_line_styles = { "PN" : hack(line_style.standards.nth(0)), "PRV": hack(line_style.standards.nth(1)), "PR": hack(line_style.standards.nth(2)), "D4": hack(line_style.standards.nth(3)), "D2": hack(line_style.standards.nth(4)), "D1": hack(line_style.standards.nth(5)), "S4": hack(line_style.standards.nth(6)), "S2": hack(line_style.standards.nth(7)), "S1": hack(line_style.standards.nth(8)), "R": hack(line_style.standards.nth(9)), "SM": hack(line_style.standards.nth(10)), "SP": hack(line_style.standards.nth(11)), } def get_line_style(p): if not theme.use_color: styles = greyscale_line_styles else: styles = color_line_styles if styles.has_key(p): return styles[p] else: pychart_util.error("unknown policy:", p) width2=pychart_util.inch_to_point(2.1) height=pychart_util.inch_to_point(1.2) xlabel_offset=-35 PyChart-1.39/demos/tocsfake.py0000644000175000017500000000310210354321345017730 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib data = chart_data.read_str(" ", "2 663.8954 466.1732719", "4 1136.591805 767.7338263", "8 1975.892086 1562.30366", "16 3095.491197 2401.061551", "30 4838.670793 3836.058") ar = area.T(size=(tocslib.width2, tocslib.height), x_axis = axis.X(label="/bCluster size"), y_axis = axis.Y(label="/bMessages//second", tic_interval=1000, label_offset=(tocslib.xlabel_offset*1.2, None)), legend=legend.T()) ar.add_plot(line_plot.T(label="No replication", tick_mark=tocslib.get_tick_mark("PN"), line_style=tocslib.get_line_style("PN"), data=data, ycol=1), line_plot.T(label="With replication", tick_mark=tocslib.get_tick_mark("PR"), line_style=tocslib.get_line_style("PR"), data=data, ycol=2)) ar.draw() PyChart-1.39/demos/tocsskew.py0000644000175000017500000000562310354321345020005 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib ymin=0 width=tocslib.width height=tocslib.height def CreateSkewGraph(data, ymax, interval): return area.T(x_coord=category_coord.T(data, 0), size=(width, height), x_axis = axis.X(label="/bSkew"), y_axis = axis.Y(label="", tic_interval=interval, label_offset=(-40,None)), y_range=(ymin, ymax), legend=None) data = chart_data.read_str(" ", "0 689.2780916 791.9442379 778.0596226 693.2 734.99 766.8875721 753.09 289.93", "0.25 690.984838 801.0757878 812.0217771 705.3 383.4590857 418.7825131 463.6420009 148.26", "0.5 683.2219825 769.5098419 784.2037828 710.23 190.9876947 217.3046324 274.7908102 75.13", "1 694.9 780.03 780.02 716 26.37 49.13 89.86 12.03784649") def create_line_plot(label, data, col): return line_plot.T(label=label, data=data, ycol=col, tick_mark=tocslib.get_tick_mark(label), line_style=tocslib.get_line_style(label)) ar = CreateSkewGraph(data, 1000, 200) ar.y_axis.label = "/bMessages//second" ar.legend = legend.T(loc=(50+width*2, 0), shadow=(2,-2,fill_style.gray50)) ar.add_plot(create_line_plot("D4", data, 3), create_line_plot("D2", data, 2), create_line_plot("D1", data, 1), create_line_plot("R", data, 4), create_line_plot("S4", data, 7), create_line_plot("S2", data, 6), create_line_plot("S1", data, 5), create_line_plot("SM", data, 8)) ar.draw() tocslib.label(ar, "(a)").draw() data = chart_data.read_str(" ", "0 327.88 362.53 373.34 325.0067623 322.89 360.4 363.23", "0.25 330.2 355.671277 353.1399808 315.9811765 165.0281937 177.9464914 192.3867494", "0.5 325.8804905 345.7156968 351.6724777 318.34 78.83 109.29 138.27", "1 323.0343 352.83 353.31 323.93 20.37 48.334 77.45") ar = CreateSkewGraph(data, 400, 100) ar.loc = tocslib.loc2 ar.add_plot(create_line_plot("D4", data, 3), create_line_plot("D2", data, 2), create_line_plot("D1", data, 1), create_line_plot("R", data, 4), create_line_plot("S4", data, 7), create_line_plot("S2", data, 6), create_line_plot("S1", data, 5)) ar.draw() tocslib.label(ar, "(b)").draw() PyChart-1.39/demos/zaptest2.py0000644000175000017500000000403710354321374017717 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import random random.seed(0) theme.get_options() can = canvas.default_canvas() class zap_x_coord(linear_coord.T): # Method get_data_range is inherited from linear_coord.T. def get_canvas_pos(self, size, val, min, max): # Zap X values between 15 and 35. if val <= 15: return linear_coord.T.get_canvas_pos(self, size, val, 0, 30) elif val <= 35: return linear_coord.T.get_canvas_pos(self, size, 15, 0, 30) else: return linear_coord.T.get_canvas_pos(self, size, val - 20, 0, 30) def get_tics(self, min, max, interval): # Don't draw tick marks between 20 and 30. tics = linear_coord.T.get_tics(self, min, max, interval) newtics = [] # XXX should be using for..if construction .. for item in tics: if item < 20 or item > 30: newtics.append(item) return newtics data = map(lambda x: (x, random.random() * 2 * x, random.random() * 4 * x), range(1,50)) ar = area.T(x_axis = axis.X(label = "X"), x_coord = zap_x_coord(), y_axis = axis.Y(label = "Y")) ar.add_plot(line_plot.T(label = "foo", data = data, ycol = 1), line_plot.T(label = "bar", data = data, ycol = 2)) ar.draw() zap.zap_vertically(can, line_style.default, fill_style.white, ar.x_pos(14), ar.y_pos(0), ar.x_pos(14) + 6, ar.y_pos(200), 4, 6) PyChart-1.39/demos/failure.py0000644000175000017500000000371310354321345017570 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.line_style theme.get_options() chartSize = (180, 110) can = canvas.default_canvas() font.defaultSize = 9 chart_object.set_defaults(legend.Entry) xaxis = axis.X(label="Timeline\n(seconds)", label_offset = (120, 30), format="/a-30{}%d", tic_interval = 100) yaxis = axis.Y(label = "Messages//second") ar = area.T(size=chartSize, x_axis=xaxis, x_range=(0,800), y_grid_interval = 100, y_axis=yaxis, y_range=(400,700)) ar.legend = legend.T(loc = (ar.loc[0] + chartSize[0]+30, ar.loc[1] + chartSize[1]/2)) data = chart_data.read_csv("failure.csv") ar.add_plot(line_plot.T(label="no failure", data=data, ycol=4, line_style=line_style.gray50)) ar.add_plot(line_plot.T(label="one failure", data=data, ycol=1)) ar.add_plot(line_plot.T(label="three failures", data=data, ycol=2, line_style=line_style.black_dash2)) ar.draw() yloc = ar.loc[1] + ar.size[1] + 50 ytip = ar.loc[1] + ar.size[1] ybot = ar.loc[1] def describeEvent(seconds, label, off): x1 = ar.x_pos(seconds) can.line(line_style.black_dash1, x1, ybot, x1, ytip) tb = text_box.T(text=label, loc=(x1+off, yloc), shadow=(2,-2,fill_style.gray70)) tb.add_arrow((x1, ytip)) tb.draw() describeEvent(300, "Nodes\nfail", -100) describeEvent(320, "New membership\ndetermined", -50) describeEvent(600, "Nodes\nrecover", 0) describeEvent(620, "New membership\ndetermined", 50) PyChart-1.39/demos/errorbars.py0000644000175000017500000000304310354321345020136 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import re can = canvas.default_canvas() x = 100 y = 500 ar = area.T() q=30 m=60 def draw_error_bar(e): global x, y name = pychart.doc_support.stringify_value(e) name = re.sub("error_bar\\.", "", name) tb = text_box.T(text="/hC" + name, loc=(x, y-m-20), line_style=None) tb.draw() e.draw(can, (x, y), y-m, y+m, y-q, y+q) x = x + 50 xmin = x for e in error_bar.standards.list(): draw_error_bar(e) xmax = x can.line(line_style.gray70_dash1, xmin-20, y, xmax, y) can.line(line_style.gray70_dash1, xmin-20, y-q, xmax, y-q) can.line(line_style.gray70_dash1, xmin-20, y+q, xmax, y+q) tb = text_box.T(text="quartile", loc=(xmax+40, y), line_style=None) tb.add_arrow(tipLoc=(xmax+55, y+q)) #, tail='tc') tb.add_arrow(tipLoc=(xmax+55, y-q)) #, tail='bc') tb.draw() tb = text_box.T(text="min//\nmax", loc=(xmax+80, y), line_style=None) tb.add_arrow(tipLoc=(xmax+95, y+m)) #, tail='tc') tb.add_arrow(tipLoc=(xmax+95, y-m)) #, tail='bc') tb.draw() PyChart-1.39/demos/failureannot.py0000644000175000017500000000235310354321345020627 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import failure can = canvas.default_canvas() can.round_rectangle(line_style.gray70_dash1, None, -60, 140, 280, 180, 10) can.show(200, 142, "/H{}/14{}text_box.T") tb = text_box.T(text="/H{}/14{}axis.X", loc=(-80, 0), line_style = None) tb.add_arrow((0, 25), "rm", arrow=arrow.fat1) tb.draw() tb = text_box.T(text="/H{}/14{}axis.Y", loc=(00, -45), line_style = None) tb.add_arrow((30, 0), "ct", arrow=arrow.fat1) tb.draw() tb = text_box.T(text="/H{}/14{}legend.T", loc=(240, 100), line_style = None) tb.add_arrow((250, 80), "cb", arrow=arrow.fat1) tb.draw() tb = text_box.T(text="/o{}/14{}plots", loc=(180, 100), line_style = None) tb.add_arrow((170, 70), "lb", arrow=arrow.fat1) tb.draw() PyChart-1.39/demos/list_sources.py0000644000175000017500000000136210354321374020657 0ustar santiagosantiago00000000000000import glob import os.path def list_sources(dir): """Return the list of Python source files under demos/ directory. Parameter "dir" specifies the locatino of the demos/ directory.""" l = glob.glob(dir + "/*.py") r = [] for path in l: basename = os.path.basename(path) if basename in ("tocslib.py", "twographs.py", "chartdemo.py", "list_sources.py"): continue if basename.startswith(",,"): # tla/baz temp file. continue r.append(basename) r.sort() return r if __name__ == '__main__': # When invoked from the cmdline, just print the list of files to # the stdout. r = list_sources(".") print " ".join(r) PyChart-1.39/demos/twoaxes.py0000644000175000017500000000205510354321374017633 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # import random from pychart import * random.seed(0) data1 = [] data2 = [] x1 = 0 x2 = 0 for i in range(0, 100, 5): x1 += random.randrange(0,3) x2 += random.randrange(0,3) data1.append([i, x1]) data2.append([i, x2]) ar = area.T(size = (150, 120), x_axis = axis.X(format="%d"), y_axis = axis.Y(offset = 0, format="%d"), y_axis2 = axis.Y(offset = 150, format="%d", draw_tics_right = 1)) ar.add_plot(line_plot.T(data = data2)) ar.add_plot(bar_plot.T(data = data1)) ar.draw() PyChart-1.39/demos/zaptest.py0000644000175000017500000000440510354321416017631 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * class zap_y_coord(linear_coord.T): # Method get_data_range is inherited from linear_coord.T. def get_canvas_pos(self, size, val, min, max): # Zap Y values between 70 and 240. # Thus, Y axis will display 0..70 and 240..280, 110 points total. if val <= 70: return linear_coord.T.get_canvas_pos(self, size, val, 0, 110) elif val <= 240: return linear_coord.T.get_canvas_pos(self, size, 70, 0, 110) else: return linear_coord.T.get_canvas_pos(self, size, val - 170, 0, 110) def get_tics(self, min, max, interval): # Don't draw tick marks between 65 and 245. tics = linear_coord.T.get_tics(self, min, max, interval) return [x for x in tics if x < 65 or x > 256] can = canvas.default_canvas() theme.get_options() data = [(10, 20, 30, 5), (20, 265, 33, 5), (30, 255, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3)] chart_object.set_defaults(area.T, size = (150, 120), y_range = (0, 280), y_coord = zap_y_coord(), x_coord = category_coord.T(data, 0)) chart_object.set_defaults(bar_plot.T, data = data) bar_plot.fill_styles.reset(); plot1=bar_plot.T(label="foo", cluster=(0,3)) plot2=bar_plot.T(label="bar", hcol=2, cluster=(1,3)) plot3=bar_plot.T(label="baz", hcol=3, cluster=(2,3)) ar = area.T(loc=(250,0), x_axis=axis.X(label="X label", format="/a-30{}%d"), y_axis=axis.Y(label="Y label", tic_interval=10)) ar.add_plot(plot1, plot2, plot3) ar.draw() for x in (ar.x_pos(10) - 20, ar.x_pos(20)- 10, ar.x_pos(30) - 10): zap.zap_horizontally(can, line_style.default, fill_style.white, x, ar.y_pos(65), x+16, ar.y_pos(65) + 4, 4, 4) PyChart-1.39/demos/barline.py0000644000175000017500000000177510354321416017562 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [(10, 20, 30), (20, 65, 33), (30, 55, 30), (40, 45, 51), (50, 25, 27), (60, 75, 30)] ar = area.T(size = (150,120), y_grid_interval=10, x_axis=axis.X(label="X label", label_offset=(0,-7)), y_axis=axis.Y(label="Y label"), legend = legend.T(), y_range = (0, None)) ar.add_plot(bar_plot.T(label="foo", data=data), line_plot.T(label="bar", data=data, ycol=2)) ar.draw() PyChart-1.39/demos/recoverycost.py0000644000175000017500000000222010354321345020660 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib data = [[128, 637], [256, 651], [512, 680], [1024, 737], [2048, 851]] ar = area.T(x_axis = axis.X(label="Hash map size", tic_interval=lambda x,y: [128,256,512,1024,2048]), y_axis = axis.Y(label="Recovery cost(ms)", tic_interval=lambda x,y: (600,700,800,900,1000)), x_grid_interval = 2, y_range = (0, 1000), x_range = (100, 2400), legend = None, x_coord = log_coord.T()) ar.add_plot(bar_plot.T(data=data, label=None, data_label_format="/o/7{}%d")) ar.draw() PyChart-1.39/demos/tocssingle.py0000644000175000017500000000252210354321345020310 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib data = chart_data.read_str(",", "/8No\nReplication,23,105", "/8Replication,9,38", "/8Replication\nwith NVRAM,13,48") ar = area.T(y_range=(0,150), size=(tocslib.width*1.3, tocslib.height), x_coord=category_coord.T(data, 0), y_axis = axis.Y(label="/bMessages//second", tic_interval=50), x_axis = axis.X(label=None), legend=legend.T(loc=(70,50))) ar.add_plot(bar_plot.T(label="With one disk//node", cluster = (0,2), data = data, width=15, fill_style=fill_style.white), bar_plot.T(label="With three disks//node", cluster = (1,2), data = data, width=15, hcol=2)) ar.draw() PyChart-1.39/demos/roseplottest.py0000644000175000017500000000224710354321374020713 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.use_color = 1 data1 = [ 0.27027027, 0.74324324, 0. , 0.34459459 ,0.47297297 ,0.06756757, 0.90540541 ,1. ,0.40540541 , 0.33783784 ,0.33783784 ,0.16216216] data2 = [ 0.93333333, 0.46666667 ,0.26666667 , 0.60666667 ,0.6 ,0.73333333, 0.22666667, 0.72 ,0.13333333 , 0.46666667 ,1. ,0.29333333] data = [('/7Model', data1), ('/7Station', data2)] ar = area.T(legend=legend.T(loc=(100,-5), right_fudge=0, left_fudge=3)) plot = rose_plot.T(data=data, sector_centred=True) ar.add_plot(plot) ar.draw() PyChart-1.39/demos/intvlbartestv.py0000644000175000017500000000321310354321416021042 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [("Foo", (10, 7, 10, 5, 5, 12, 13, 5, 10, 3), (7,10,8,16,9,3)), ("Bar", (5, 10, 12, 10, 9, 3), (10,10,13,6,9,13),)] ar = area.T(y_coord = category_coord.T(data, 0), x_grid_style=line_style.gray50_dash1, x_grid_interval=20, x_range = (0,100), x_axis=axis.X(label="X label"), y_axis=axis.Y(label="Y label"), legend = legend.T(loc=(80, 40))) chart_object.set_defaults(interval_bar_plot.T, direction="horizontal", width=3, cluster_sep = 5, data=data) ar.add_plot(interval_bar_plot.T(line_styles = [line_style.default, None], fill_styles = [fill_style.red, None], label="foo", cluster=(0,2)), interval_bar_plot.T(line_styles = [line_style.default, None], fill_styles = [fill_style.blue, None], label="bar", hcol=2, cluster=(1,2))) can = canvas.default_canvas() can.set_title("Interval bar test") can.set_author("John Doe") ar.draw() PyChart-1.39/demos/tocsscale.py0000644000175000017500000000415210354321345020117 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib data = chart_data.read_str(" ", "2 56.11176043 19.72962276 26.27090859 14.99", "4 108.040603 41.39483239 55.59 47.5618015", "8 224.4335486 80.348324 110.23 89.62", "16 425.6517423 148.7731912 207.34 169.24", "30 790.9817461 273.8225464 385.24 289.93") ar = area.T(size=(tocslib.width2, tocslib.height), x_axis = axis.X(label="/bCluster size"), y_axis = axis.Y(label="/bMessages//second", tic_interval=200, label_offset=(tocslib.xlabel_offset, None)), legend=legend.T()) ar.add_plot(line_plot.T(label="Porcupine no replication", tick_mark=tocslib.get_tick_mark("PN"), line_style=tocslib.get_line_style("PN"), data=data, ycol=1), line_plot.T(label="Porcupine with\nreplication, NVRAM", tick_mark=tocslib.get_tick_mark("PRV"), line_style=tocslib.get_line_style("PRV"), data=data, ycol=3), line_plot.T(label="Porcupine with replication", tick_mark=tocslib.get_tick_mark("PR"), line_style=tocslib.get_line_style("PR"), data=data, ycol=2), line_plot.T(label="Sendmail+popd", data=data, ycol=4, tick_mark=tocslib.get_tick_mark("SP"), line_style=tocslib.get_line_style("SP"))) ar.draw() PyChart-1.39/demos/annotations.py0000644000175000017500000000216510354321345020476 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * tb = text_box.T(loc=(100,100), text="Without frame") tb.add_arrow((50, 100)) tb.add_arrow((180, 100)) tb.draw() tb = text_box.T(loc=(100,130), text="/hCMulti\n/bLine") tb.add_arrow((50, 120)) tb.add_arrow((180, 100)) tb.draw() tb = text_box.T(loc=(100,160), text="Fat arrow", line_style=None) tb.add_arrow((180, 140), tail='rm', arrow = arrow.fat1) tb.draw() text_box.T(loc=(180, 100), text="/a90Funny background", fill_style = fill_style.gray70).draw() text_box.T(loc=(180, 140), text="/hL/20Big/oText\n/24/bHuge/oText", fill_style = None).draw() PyChart-1.39/demos/unicodetest.py0000644000175000017500000000151310352123246020461 0ustar santiagosantiago00000000000000# -*- coding: utf-8 -*- # # Copyright (C) 2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * can = canvas.default_canvas() x, y = (100, 500) def show_text(str): global x, y can.show(x, y, str) can.show(x + 200, y, "/12/C" + font.quotemeta(str)) y -= 20 show_text(unicode('Zürich', 'utf-8')) show_text(unicode('X äöü Y', 'utf-8')) PyChart-1.39/demos/linetest3.py0000644000175000017500000000265410354321416020055 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = chart_data.read_csv("lines.csv") xaxis=axis.X(label="X", tic_interval=10) yaxis=axis.Y(label="Y", tic_interval=10) ar = area.T(x_range=(0,100), y_range=(0,100), x_axis=xaxis, y_axis=yaxis) eb = error_bar.error_bar2(tic_len=5, hline_style=line_style.gray50) ar.add_plot(line_plot.T(label="foo", data=data, error_bar=eb, y_error_minus_col=3), line_plot.T(label="bar", data=data, ycol=2, error_bar=eb, y_error_minus_col=3)) ar.draw() tb = text_box.T(loc=(40, 130), text="This is\nimportant!", line_style=None) tb.add_arrow((ar.x_pos(data[6][0]), ar.y_pos(data[6][1])), "cb") tb.draw() ar = area.T(loc=(200, 0), x_range=(0,100), y_range=(0,100), x_axis=xaxis, y_axis=yaxis, legend=legend.T()) ar.add_plot(line_plot.T(label="foo", data=data, data_label_format="/8{}%d"), line_plot.T(label="bar", data=data, ycol=2)) ar.draw() PyChart-1.39/demos/comparison.py0000644000175000017500000000241710354321345020313 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib size=120 can = canvas.default_canvas() arrow.T(line_style=line_style.T(width=1)).draw([(0,0),(0,size)]) arrow.T(line_style=line_style.T(width=1)).draw([(0,0),(size,0)]) font.defaultSize=10 font.defaultLineHeight=8 can.show(-5,60,"/hC/a90/oManageability") can.show(10,-3, "/hL/vT/oPerformance&availability\n/o//cost") def circle(x,y,str): can.ellipsis(line_style.default, fill_style.black, x, y, 2) can.show(x+5,y, "/T/vM" + str) circle(size*0.2,size*0.8,"/l8Monolithic\n/l8Server") circle(size*0.4,size*0.6,"/l8Cluster-based\n/l8operating system") circle(size*0.6,size*0.4,"/l8Distributed\n/l8file system") circle(size*0.8,size*0.2,"/l8Static\n/l8partitioning") circle(size*0.8,size*0.8,"Porcupine"); PyChart-1.39/demos/fillstyles.py0000644000175000017500000000233310354321345020330 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import chartdemo import re x = 100 y = 500 can = canvas.default_canvas() def drawRect(fill): global x, y name = pychart.doc_support.stringify_value(style) #print "name=", name name = re.sub("fill_style\\.", "", name) name = pychart.doc_support.break_string(name) height = font.text_height(name)[0] + 5 can.rectangle(line_style.default, fill, x, y, x+15, y+15) tb = text_box.T(text=name, loc=(x, y-height), line_style=None, fill_style = None) x = x + 50 tb.draw() for style in fill_style.standards.list(): drawRect(style) if x >= chartdemo.MaxWidth: x=100 y=y-40 PyChart-1.39/demos/scattertest.py0000644000175000017500000000325010354321416020501 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import random random.seed(0) def randomdata(): data = [] for i in range(0, 30): data.append((random.random() * 1000, random.random() * 1000)) return data theme.get_options() chart_object.set_defaults(line_plot.T, line_style=None) tick1 = tick_mark.Circle(size=2) tick2 = tick_mark.Circle(size=2, fill_style=fill_style.black) xaxis = axis.X(label="foo", format="/a-60{}%d") yaxis = axis.Y(label="bar") ar = area.T(x_axis=xaxis, y_axis=yaxis, x_grid_interval=100, x_grid_style=line_style.gray70_dash3, legend = legend.T(loc=(350, 50)), loc = (0, 0)) ar.add_plot(line_plot.T(label="plot1", data=randomdata(), tick_mark=tick1)) ar.add_plot(line_plot.T(label="plot2", data=randomdata(), tick_mark=tick2)) ar.draw() xaxis = axis.X(label="foo", format="/a-30{}%d") yaxis = axis.Y(label="bar") ar = area.T(x_axis=xaxis, y_axis=yaxis, x_coord=log_coord.T(), y_coord=log_coord.T(), loc = (200, 0), legend = None) ar.add_plot(line_plot.T(label="plot1", data=randomdata(), tick_mark=tick1)) ar.add_plot(line_plot.T(label="plot2", data=randomdata(), tick_mark=tick2)) ar.draw() PyChart-1.39/demos/arrows.py0000644000175000017500000000165410354321345017460 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import re x = 100 y = 500 def draw(obj): global x, y name = pychart.doc_support.stringify_value(obj) name = re.sub("arrow\\.", "", name) obj.draw(((x, y), (x, y+30))) tb = text_box.T(text="/hC" + name, loc=(x, y-12), line_style=None) tb.draw() x = x + 50 for style in arrow.standards.list(): draw(style) PyChart-1.39/demos/categbar.py0000644000175000017500000000153210354321416017705 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [["Jan", 10], ["Feb", 22], ["Mar", 30]] ar = area.T(x_coord = category_coord.T(data, 0), y_range = (0, None), x_axis = axis.X(label="Month"), y_axis = axis.Y(label="Value")) ar.add_plot(bar_plot.T(data = data, label = "Something")) ar.draw() PyChart-1.39/demos/bartest.py0000644000175000017500000000315710354321416017606 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [(10, 20, 30, 5), (20, 65, 33, 5), (30, 55, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3)] chart_object.set_defaults(area.T, size = (150, 120), y_range = (0, None), x_coord = category_coord.T(data, 0)) chart_object.set_defaults(bar_plot.T, data = data) # Draw the 1st graph. The Y upper bound is calculated automatically. ar = area.T(x_axis=axis.X(label="X label", format="/a-30{}%d"), y_axis=axis.Y(label="Y label", tic_interval=10)) ar.add_plot(bar_plot.T(label="foo", cluster=(0, 3)), bar_plot.T(label="bar", hcol=2, cluster=(1, 3)), bar_plot.T(label="baz", hcol=3, cluster=(2, 3))) ar.draw() ar = area.T(legend = legend.T(), loc=(250,0), x_axis=axis.X(label="X label", format="/a-30{}%d"), y_axis=axis.Y(label="Y label", tic_interval=10)) bar_plot.fill_styles.reset(); plot1 = bar_plot.T(label="foo") plot2 = bar_plot.T(label="bar", hcol=2, stack_on = plot1) plot3 = bar_plot.T(label="baz", hcol=3, stack_on = plot2) ar.add_plot(plot1, plot2, plot3) ar.draw() PyChart-1.39/demos/cliptest.py0000644000175000017500000000205710354321345017770 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * can = canvas.default_canvas() data = [(10, 20), (20, 65), (30, 55), (40, 45)] # tic_angle is the angle X values are displayed below the axis. xaxis = axis.X(label="Stuff") yaxis = axis.Y(label="Value") ar = area.T(x_axis=xaxis, y_axis=yaxis) plot = line_plot.T(label="foo", data=data, xcol=0, ycol=1, tick_mark=tick_mark.star) ar.add_plot(plot) can.ellipsis(line_style.T(width=1.5,dash=(4,4)), None, 30, 20, 80, 0.8) can.clip_ellipsis(30, 20, 80, 0.8) ar.draw(can) can.endclip() PyChart-1.39/demos/lines.csv0000644000175000017500000000021510354321345017410 0ustar santiagosantiago0000000000000010, 20, 30, 5 20, 65, 33, 5 30, 55, 30, 5 40, 45, 51, 7 50, 25, 27, 3 60, 75, 30, 5 70, 80, 42, 5 80, 62, 32, 5 90, 42, 39, 5 100, 32, 39, 4 PyChart-1.39/demos/bgtest.py0000644000175000017500000000210210354321345017420 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * data = [(10, 20, 5, 5), (20, 65, 5, 5), (30, 55, 4, 4), (40, 45, 2, 2), (50, 25, 3, 3)] ar = area.T(x_axis = axis.X(label = "X label"), y_axis = axis.Y(label = "Y label")) ar.add_plot(bar_plot.T(label="foo", data = data, fill_style = fill_style.gray90, error_bar = error_bar.bar3, error_minus_col = 2, error_plus_col = 3)) canvas.default_canvas().set_background(fill_style.diag, -100, -100, 300, 300) ar.draw() PyChart-1.39/demos/double.py0000644000175000017500000000263210354321345017412 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import sys theme.get_options() can = canvas.default_canvas() size = (300, 200) ar = area.T(size = size, legend=None, y_range = (9000, 9500), x_axis = axis.X(format="7//%d//2002", label="Date"), y_axis = axis.Y(format="%d", label="Dow Jones")) ar.add_plot(line_plot.T(data=[ [1,9379], [2, 9054], [3, 9007], [4, 9109], [5, 9243] ])) ar.draw() can.show(ar.x_pos(4), ar.y_pos(9070), "/a45{}Dow Jones") ar = area.T(size = size, legend=None, y_range = (940, 990), x_axis = None, y_axis = axis.Y(format="%d", offset=300, tic_len=-6, label_offset=(50, 0), label="S&P 500")) ar.add_plot(line_plot.T(data=[ [1,989], [2, 953], [3, 948], [4, 968], [5, 989] ])) ar.draw() can.show(ar.x_pos(4), ar.y_pos(970), "/a50{}S&P 500") PyChart-1.39/demos/linetest.py0000644000175000017500000000366210354321345017773 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() # We have 10 sample points total. The first value in each tuple is # the X value, and subsequent values are Y values for different lines. data = [(10, 20, 30), (20, 65, 33), (30, 55, 30), (40, 45, 51), (50, 25, 27), (60, 75, 30), (70, 80, 42), (80, 62, 32), (90, 42, 39), (100, 32, 39)] # The format attribute specifies the text to be drawn at each tick mark. # Here, texts are rotated -60 degrees ("/a-60"), left-aligned ("/hL"), # and numbers are printed as integers ("%d"). xaxis = axis.X(format="/a-60/hL%d", tic_interval = 20, label="Stuff") yaxis = axis.Y(tic_interval = 20, label="Value") # Define the drawing area. "y_range=(0,None)" tells that the Y minimum # is 0, but the Y maximum is to be computed automatically. Without # y_ranges, Pychart will pick the minimum Y value among the samples, # i.e., 20, as the base value of Y axis. ar = area.T(x_axis=xaxis, y_axis=yaxis, y_range=(0,None)) # The first plot extracts Y values from the 2nd column # ("ycol=1") of DATA ("data=data"). X values are takes from the first # column, which is the default. plot = line_plot.T(label="foo", data=data, ycol=1, tick_mark=tick_mark.star) plot2 = line_plot.T(label="bar", data=data, ycol=2, tick_mark=tick_mark.square) ar.add_plot(plot, plot2) # The call to ar.draw() usually comes at the end of a program. It # draws the axes, the plots, and the legend (if any). ar.draw() PyChart-1.39/demos/twographs.py0000644000175000017500000000314310354321345020154 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * can = canvas.init("graph1.pdf") data = chart_data.read_csv("lines.csv") ar = area.T(x_range = (0,100), y_range = (0,100), x_axis = axis.X(label="X", tic_interval=10), y_axis = axis.Y(label="Y", tic_interval=10)) eb = error_bar.error_bar2(tic_len=5, hline_style=line_style.gray50) ar.add_plot(line_plot.T(label="foo", data=data, error_bar=eb, y_error_minus_col=3), line_plot.T(label="bar", data=data, ycol=2, error_bar=eb, y_error_minus_col=3)) ar.draw(can) tb = text_box.T(loc=(40, 130), text="This is\nimportant!", line_style=None) tb.add_arrow((ar.x_pos(data[6][0]), ar.y_pos(data[6][1])), "cb") tb.draw(can) can = canvas.init("graph2.pdf") ar = area.T(loc=(200, 0), x_range=(0,100), y_range=(0,100), x_axis = axis.X(label="X", tic_interval=10), y_axis = axis.Y(label="Y", tic_interval=10)) ar.add_plot(line_plot.T(label="foo", data=data, data_label_format="/8{}%d"), line_plot.T(label="bar", data=data, ycol=2)) ar.draw(can) # Note: can.close() is called automatically for every open canvas. PyChart-1.39/demos/sincos.py0000644000175000017500000000256410354321345017442 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import math def format_x_axis(x): return str(int(x*2/math.pi)) + "//2" ar = area.T(x_axis=axis.X(label="X (unit is Pi)", format=format_x_axis, tic_interval=math.pi/2.0), y_axis = axis.Y(label="Y"), y_range=(-1,1), x_range=(0, math.pi*4), legend = legend.T()) sindata = chart_data.func(lambda x: math.sin(x), 0, math.pi*4, 0.1) cosdata = chart_data.func(lambda x: math.cos(x), 0, math.pi*4, 0.1) sin2data = chart_data.func(lambda x: math.sin(x)/2, 0, math.pi*4, 0.1) cos2data = chart_data.func(lambda x: math.cos(x)/2, 0, math.pi*4, 0.1) ar.add_plot(line_plot.T(label="sin(x)", data=sindata), line_plot.T(label="sin(x)//2", data=sin2data), line_plot.T(label="cos(x)", data=cosdata), line_plot.T(label="cos(x)//2", data=cos2data)) ar.draw() PyChart-1.39/demos/tickmarks.py0000644000175000017500000000221710354321345020127 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import chartdemo import re can = canvas.default_canvas() x = 100 y = 100 def draw_tick(tick): global x, y name = pychart.doc_support.stringify_value(tick) name = re.sub("tick_mark\\.", "", name) name = pychart.doc_support.break_string(name) height = font.text_height(name)[0] + 10 tick.draw(can, x, y+tick.size/2) tb = text_box.T(text="/12" + name, loc=(x, y-height), line_style=None) x = x + 70 tb.draw(can) for tick in tick_mark.standards.list(): draw_tick(tick) if x >= chartdemo.MaxWidth: x = 100 y = y + 45 PyChart-1.39/demos/bartest2.py0000644000175000017500000000171210354321416017663 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [(10, 20, 3.0), (20, 65, 2.5), (30, 55, 5.0), (40, 45, 3.0), (50, 25, 2.0)] ar = area.T(x_axis=axis.X(label="X", format="/a-30{}%d", tic_interval=20), y_axis = axis.Y()) ar.add_plot(bar_plot.T(data=data, line_style=None, fill_style = fill_style.gray50, error_bar = error_bar.bar2, error_minus_col=2)) ar.draw() PyChart-1.39/demos/bartest3.py0000644000175000017500000000174710354321345017675 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * data = [(10, 20, 5, 5), (20, 65, 5, 5), (30, 55, 4, 4), (40, 45, 2, 2), (50, 25, 3, 3)] ar = area.T(x_axis = axis.X(label = "X label"), y_axis = axis.Y(label = "Y label")) ar.add_plot(bar_plot.T(label="foo", data = data, fill_style = None, error_bar = error_bar.bar3, error_minus_col = 2, error_plus_col = 3)) ar.draw() PyChart-1.39/demos/chartdemo.py0000644000175000017500000000121510354321345020102 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * ChartSize = (120, 110) MaxWidth=500 chart_object.set_defaults(area.T, size = ChartSize) PyChart-1.39/demos/bartestv.py0000644000175000017500000000350710354321416017773 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * theme.get_options() data = [(10, 20, 30, 5), (20, 65, 33, 5), (30, 55, 30, 5), (40, 45, 51, 7), (50, 25, 27, 3), (60, 75, 30, 5), (70, 80, 42, 5), (80, 62, 32, 5), (90, 42, 39, 5), (100, 32, 39, 4)] # The attribute y_coord=... tells that the Y axis values # should be taken from samples. # In this example, Y values will be [40,50,60,70,80]. ar = area.T(y_coord = category_coord.T(data[3:8], 0), x_grid_style=line_style.gray50_dash1, x_grid_interval=20, x_range = (0,100), x_axis=axis.X(label="X label"), y_axis=axis.Y(label="Y label"), bg_style = fill_style.gray90, border_line_style = line_style.default, legend = legend.T(loc=(80,10))) # Below call sets the default attributes for all bar plots. chart_object.set_defaults(bar_plot.T, direction="horizontal", data=data) # Attribute cluster=(0,3) tells that you are going to draw three bar # plots side by side. The plot labeled "foo" will the leftmost (i.e., # 0th out of 3). Attribute hcol tells the column from which to # retrive sample values from. It defaults to one. ar.add_plot(bar_plot.T(label="foo", cluster=(0,3))) ar.add_plot(bar_plot.T(label="bar", hcol=2, cluster=(1,3))) ar.add_plot(bar_plot.T(label="baz", hcol=3, cluster=(2,3))) ar.draw() PyChart-1.39/demos/fonttest.py0000644000175000017500000000247010354321345020006 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * can = canvas.default_canvas() x, y = (100, 500) def show_text(str): global x, y can.show(x, y, str) can.show(x + 200, y, "/12/C" + font.quotemeta(str)) y -= 20 show_text("/12/hLLeft align") show_text("/12/hRRight align") show_text("/12/hCCenter align") show_text("/a20/12/hRAngled text") def show_textv(str): global x, y can.show(x, y, str) x += 150 y -= 40 x = 100 show_textv("/12/vT//12//vTTop align") show_textv("/12/vM//12//vT/12Middle align") show_textv("/12/vB//12//vT/12Bottom align") y -= 40 x = 100 show_text("/16/HHelvetica") show_text("/12/CCourier") show_text("/12/NHelvetica-Narrow") show_text("/12/PPalatino-Roman") show_text("/12/AAvantgarde") show_text("/12/T/iTimes-Italic") show_text("/12/F{ZapfDingbats}ZapfDingbats") PyChart-1.39/demos/linestyles.py0000644000175000017500000000223110354321345020326 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import pychart.doc_support import chartdemo import re can = canvas.default_canvas() x = 100 y = 500 def drawLine(style): global x, y name = pychart.doc_support.stringify_value(style) name = re.sub("line_style\\.", "", name) name = pychart.doc_support.break_string(name) can.line(style, x, y, x+40, y) #print "name=", name height = font.text_height(name)[0] + 5 tb = text_box.T(text=name, loc=(x, y-height), line_style=None) x = x + 60 tb.draw() for style in line_style.standards.list(): drawLine(style) if x >= chartdemo.MaxWidth: x=100 y=y-40 PyChart-1.39/demos/tocsturbo2.py0000644000175000017500000000556310354321345020254 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import tocslib def createbar_plot(ar, label, ycol, base, clu): baseBar = bar_plot.T(label=None, fill_style = None, line_style=None, data=base, hcol=ycol, cluster=(clu,5)) bar = bar_plot.T(label=label, fill_style = fill_style.standards.nth(ycol), data=data, hcol=ycol, cluster=(clu,5), stack_on = baseBar) ar.add_plot(baseBar, bar) def createGraph(data, base): ar = area.T(size=(tocslib.width, tocslib.height), x_range = (0.5,3.5), x_axis = axis.X(label="/bNumber of nodes with fast disks", tic_interval=lambda x,y: range(1, 3, 1)), y_axis = axis.Y(label="/bMessages//second", label_offset=(tocslib.xlabel_offset, None)), legend=legend.T()) createbar_plot(ar, "D4", 2, base, 0) createbar_plot(ar, "D2", 1, base, 1) createbar_plot(ar, "S4", 5, base, 2) createbar_plot(ar, "S2", 4, base, 3) createbar_plot(ar, "R", 3, base, 4) return ar base_nonrepl = [ [0, 791, 778, 693.2, 766.88, 753.09], [1, 791, 778, 693.2, 766.88, 753.09], [2, 791, 778, 693.2, 766.88, 753.09], [3, 791, 778, 693.2, 766.88, 753.09]] base_repl = [[0, 362.53, 373.34, 325.00, 360.4, 363.23], [1, 362.53, 373.34, 325.00, 360.4, 363.23], [2, 362.53, 373.34, 325.00, 360.4, 363.23], [3, 362.53, 373.34, 325.00, 360.4, 363.23]] data = chart_data.read_str(" ", "0 0 0 0 0 0 0", "1 45 63 2 9 30", "2 118 133 3 20 53", "3 174 194 3 31 71") ar = createGraph(data, base_nonrepl) #area.y_range = (0,200) ar.y_range = (600,1000) ar.y_axis.tic_interval=50 ar.legend=None ar.draw() tocslib.label(ar, "(a)").draw() data = chart_data.read_str(" ", "0 0 0 0 0 0 0", "1 10 26.5 2 4 9", "2 29 53 3 10 18", "3 48 79 3 16 28") ar = createGraph(data, base_repl) #area.y_range = (0,100) ar.y_range = (300,500) ar.y_axis.label=None ar.y_axis.tic_interval=25 ar.loc = tocslib.loc2 ar.draw() tocslib.label(ar, "(b)").draw() PyChart-1.39/demos/pietest.py0000644000175000017500000000167410354321345017622 0ustar santiagosantiago00000000000000# # Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) # # Pychart is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2, or (at your option) any # later version. # # Pychart is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # from pychart import * import sys data = [("foo", 10),("bar", 20), ("baz", 30), ("ao", 40)] ar = area.T(size=(150,150), legend=legend.T(), x_grid_style = None, y_grid_style = None) plot = pie_plot.T(data=data, arc_offsets=[0,10,0,10], shadow = (2, -2, fill_style.gray50), label_offset = 25, arrow_style = arrow.a3) ar.add_plot(plot) ar.draw() PyChart-1.39/README0000644000175000017500000000343610354321345015342 0ustar santiagosantiago00000000000000* What is this package? PyChart is a Python library for creating professional quality PS, PDF, PNG, or SVG charts. It supports line plots, bar plots, range-fill plots, and pie charts. Because it is based on Python, you can make the full use of Python's scripting power. The PyChart home page is at http://www.hpl.hp.com/personal/Yasushi_Saito/pychart * What you need You need Python (http://www.python.org) version 2.2 or later (on Debian GNU/Linux, you need, python-xml package as well). You also need Ghostscript (http://www.cs.wisc.edu/~ghost/) to produce PNG files. Pychart used to require Ghostscript during PS and PDF generation to obtain font metric information, but that's no longer the case. * Platforms supported In theory, PyChart works on any platform with Python. In practice, I've run PyChart on Linux and Win2000. * Installation Become a root and do: # python setup.py install Or, you can set PYTHONPATH environment variable before you start Python. For example (in bash): % PYTHONPATH=~/PyChart-1.33/pychart python mumbo.py * Documentation A detailed documentation is found in doc/pychart. * Examples All the *.py files in the demos/ directory can be run directly. For example, setenv PYTHONPATH .. python linetest.py >foo.eps gs foo.eps or setenv PYTHONPATH .. setenv PYCHART_OPTIONS="format=pdf" python linetest.py >foo.pdf acroread foo.pdf * About the author Yasushi Saito (ysaito@hpl.hp.com), a full-time researcher and part-time hacker. This program is created mainly to serve my personal needs to write pretty charts for research papers. As such, it is updated only when I'm writing a paper, which happens about once every half year or so. Anyway, if you have comments, requests, or (even better) fixes/enhancements, feel free to email me. PyChart-1.39/PKG-INFO0000644000175000017500000000070110352125056015546 0ustar santiagosantiago00000000000000Metadata-Version: 1.0 Name: PyChart Version: 1.39 Summary: Python Chart Generator Home-page: http://www.hpl.hp.com/personal/Yasushi_Saito/pychart Author: Yasushi Saito Author-email: yasushi@cs.washington.edu License: GPL Description: Pychart is a Python library for creating high-quality charts in Postscript, PDF, PNG, and SVG. It produces line plots, bar plots, range-fill plots, and pie charts. Platform: UNKNOWN PyChart-1.39/setup.py0000644000175000017500000000113010354321345016161 0ustar santiagosantiago00000000000000from distutils.core import setup import pychart.version setup (name = "PyChart", version = pychart.version.version, description = "Python Chart Generator", author = "Yasushi Saito", author_email = "yasushi@cs.washington.edu", url = "http://www.hpl.hp.com/personal/Yasushi_Saito/pychart", license = "GPL", long_description = """ Pychart is a Python library for creating high-quality charts in Postscript, PDF, PNG, and SVG. It produces line plots, bar plots, range-fill plots, and pie charts.""", packages = ['pychart', 'pychart.afm'] ) PyChart-1.39/COPYING0000644000175000017500000004312710354321345015516 0ustar santiagosantiago00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.