1
2
3 """ SimPlot 1.8 Provides basic plotting services based on Tk/Tkinter.
4
5 LICENSE:
6 Copyright (C) 2002, 2005,2006,2007 Klaus G. Muller, Tony Vignaux
7 mailto: kgmuller@xs4all.nl and Tony.Vignaux@vuw.ac.nz
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 END OF LICENSE
23
24 Derived from plotting package in Grayson's Tkinter book.
25 The idea to use this package came from Prof. Simon Frost
26 of U of California, San Diego who also strongly contributed
27 to the design and implementation of SimPlot.
28
29
30 Change history:
31
32 Nov 2, 2003 : Combined utils.py (also from Grayson) with plotting package.
33 Nov 11, 2003: Made totally OO
34 Dec 16, 2003: Completion of SimPlot 1.4alpha
35 Feb 2004: Release with SimPy 1.4
36 Aug 27, 2005: Added tests for empty point sets to plotXXX functions.
37
38 """
39 __version__= '1.8 $Revision: 1.1.1.14 $ $Date: 2007/01/08 14:47:12 $'
40 from Tkinter import *
41 from Canvas import Line, CanvasText, Rectangle
42 from tkMessageBox import *
43 from tkSimpleDialog import askinteger,askstring,askfloat
44 from tkFileDialog import *
45 import string, math
46 from math import pi
47 from SimPy.Simulation import Monitor
48
50 if len(clist) < 2: return clist[0]
51 try:
52 x, y = clist[0]
53 for x1, y1 in clist[1:]:
54 if x1 <= x or y1 <= y:
55 x, y = x1, y1
56 except:
57 x, y = 0, 0
58
59 return x,y
60
62 if len(clist) < 2: return clist[0]
63 try:
64 x, y = clist[0]
65 for x1, y1 in clist[1:]:
66 if x1 >= x or y1 >= y:
67 x, y = x1, y1
68 except:
69 x, y = 0, 0
70
71 return x,y
72
74 x = 10000000
75 y = 10000000
76 for x1, y1 in clist:
77 if x1 < x: x = x1
78 if y1 < y: y = y1
79 return x,y
80
82 x = -10000000
83 y = -10000000
84 for x1, y1 in clist:
85 if x1 > x: x = x1
86 if y1 > y: y = y1
87 return x,y
88
93
96
100
101 step0=points[:]
102 step1=[[0,0]]*2*len(step0)
103 prev=[step0[0][0],0]
104 for x in range(len(step0)):
105 step1[2*x]=[step0[x][0],prev[1]]
106 step1[2*x+1]=step0[x]
107 prev=step0[x]
108
109 return self.makeLine(step1,smooth=False, **attr)
110
112 """Makes a histogram graph. 'points' must be a Histogram-like
113 object.
114 """
115
116 step0=points[:]
117 step1=[[0,0]]*3*len(step0)
118 prev=[step0[0][0],0]
119 for x in range(len(step0)):
120 step1[3*x]=[step0[x][0],prev[1]]
121 step1[3*x+1]=[step0[x][0],0.0]
122 step1[3*x+2]=step0[x]
123 prev=step0[x]
124 deltax=step0[1][0]-step0[0][0]
125 step1.append([prev[0]+deltax,prev[1]])
126 step1.append([prev[0]+deltax,0])
127
128 return self.makeLine(step1,smooth=False,
129 xaxis=(step1[0][0],step1[-1][0]),
130 **attr)
131
138 - def makeGraphBase(self, master, width, height,
139 background='white',title="",xtitle='',ytitle='', **kw):
140 return GraphBase(master, width, height,
141 background,title,xtitle,ytitle,**kw)
142
144 """To provide a File menu (postscript output, more to come)
145 to the plotxxxx plots"""
146 mainMenu=Menu(root)
147 root.config(menu=mainMenu)
148 def postscriptout():
149 graph.postscr()
150 file=Menu(mainMenu)
151 file.add_command(label="Postscript",command=postscriptout)
152 mainMenu.add_cascade(label='File',menu=file,underline=0)
153
154 - def plotLine(self,points,windowsize=(500,300),title='',width=1,color='black',
155 smooth=0,background='white',xlab='x',ylab='y',
156 xaxis='automatic',yaxis='automatic'):
157 """Generates a line chart, with menu to save as Postscript file.
158 'points' can be a Monitor instance.
159 """
160 if points!=[]:
161 root=Toplevel()
162 f=Frame(root)
163 try:
164 ylab=points.ylab
165 xlab=points.tlab
166 if not title: title=points.name
167 except:
168 pass
169 line=self.makeLine(points, width=width,color=color,smooth=smooth)
170 gr=self.makeGraphObjects([line])
171 graph = self.makeGraphBase(f, windowsize[0], windowsize[1],
172 title=title,xtitle=xlab,
173 ytitle=ylab,background=background)
174 graph.pack(side=LEFT, fill=BOTH, expand=YES)
175 graph.draw(gr,xaxis=xaxis, yaxis=yaxis)
176
177 self.graphMenu(root,graph)
178 f.pack()
179 return graph
180 else:
181 print "SimPlot.plotline: dataset empty, no plot."
182 return None
183
184 - def plotStep(self,points,windowsize=(500,300),title='',width=1,color='black',
185 background='white',xlab='x',ylab='y',
186 xaxis='automatic',yaxis='automatic'):
187 """Generates a step chart, with menu to save as Postscript file.
188 'points' can be a Monitor instance.
189 """
190 if points!=[]:
191
192 step0=points[:]
193 step1=[[0,0]]*2*len(step0)
194 prev=[step0[0][0],0]
195 for x in range(len(step0)):
196 step1[2*x]=[step0[x][0],prev[1]]
197 step1[2*x+1]=step0[x]
198 prev=step0[x]
199
200 try:
201 ylab=points.ylab
202 xlab=points.tlab
203 if not title: title=points.name
204 except:
205 pass
206
207 smooth=False
208 return self.plotLine(step1,windowsize,title,width,color,
209 smooth,background,xlab,ylab,
210 xaxis,yaxis)
211 else:
212 print "SimPlot.plotStep: dataset empty, no plot."
213 return None
214
215 - def plotHistogram(self,points,windowsize=(500,300),title='',width=1,color='black',
216 background='white',xlab='x',ylab='y',
217 xaxis='automatic',yaxis='automatic'):
218 """Makes a histogram plot. 'points' can be a Monitor instance.
219 """
220 if points!=[]:
221
222 step0=points[:]
223 step1=[[0,0]]*3*len(step0)
224 prev=[step0[0][0],0]
225 for x in range(len(step0)):
226 step1[3*x]=[step0[x][0],prev[1]]
227 step1[3*x+1]=[step0[x][0],0.0]
228 step1[3*x+2]=step0[x]
229 prev=step0[x]
230 deltax=step0[1][0]-step0[0][0]
231 step1.append([prev[0]+deltax,prev[1]])
232 step1.append([prev[0]+deltax,0])
233
234 try:
235 ylab=points.ylab
236 xlab=points.tlab
237 if not title: title=points.name
238 except:
239 pass
240
241 smooth=False
242 return self.plotLine(step1,windowsize=windowsize,title=title,width=width,
243 color=color,smooth=smooth,background=background,
244 xlab=xlab,ylab=ylab,xaxis=(step1[0][0],step1[-1][0]),
245 yaxis=yaxis)
246 else:
247 print "SimPlot.plotHistogram: dataset empty, no plot."
248 return None
249
250 - def plotBars(self,points,windowsize=(500,300),title='',color='black',
251 width=1,size=3,fillcolor='black',fillstyle='',
252 outline='black',background='white',xlab='x',ylab='y',
253 xaxis='automatic',yaxis='automatic',anchor=0.0):
254 """Generates a bar chart, with menu to save as Postscript file.
255 'points' can be a Monitor instance.
256 """
257 if points!=[]:
258 root=Toplevel()
259 f=Frame(root)
260 try:
261 ylab=points.ylab
262 xlab=points.tlab
263 if not title: title=points.name
264 except:
265 pass
266 bars=self.makeBars(points, width=width,size=size,color=color,
267 fillcolor=fillcolor,fillstyle=fillstyle,
268 outline=outline,anchor=anchor)
269 gr=self.makeGraphObjects([bars])
270 graph = self.makeGraphBase(f, windowsize[0],windowsize[1],
271 title=title,xtitle=xlab,
272 ytitle=ylab,background=background)
273 graph.pack(side=LEFT, fill=BOTH, expand=YES)
274 graph.draw(gr,xaxis=xaxis, yaxis=yaxis)
275
276 self.graphMenu(root,graph)
277 f.pack()
278 return graph
279 else:
280 print "SimPlot.plotBars dataset empty, no plot."
281 return None
282
283 - def plotScatter(self,points,windowsize=(500,300),title='',width=1,color='black',
284 fillcolor='black',size=2,fillstyle='',
285 outline='black',marker='circle',
286 background='white',xlab='x',ylab='y',
287 xaxis='automatic',yaxis='automatic'):
288 if points!=[]:
289 root=Toplevel()
290 f=Frame(root)
291 try:
292 ylab=points.ylab
293 xlab=points.tlab
294 if not title: title=points.name
295 except:
296 pass
297 scat=self.makeSymbols(points, width=width,color=color,size=size,
298 marker=marker,fillcolor=fillcolor,
299 fillstyle=fillstyle,outline=outline)
300 gr=self.makeGraphObjects([scat])
301 graph = self.makeGraphBase(f, windowsize[0],windowsize[1],
302 title=title,xtitle=xlab,
303 ytitle=ylab,background=background)
304 graph.pack(side=LEFT, fill=BOTH, expand=YES)
305 graph.draw(gr,xaxis=xaxis, yaxis=yaxis)
306
307 self.graphMenu(root,graph)
308 f.pack()
309 return graph
310 else:
311 print "SimPlot.plotScatter: dataset empty, no plot."
312 return None
313
314 - def mainloop(self):
316
319 self.points = points
320 self.scaled = self.points
321 self.attributes = {}
322 for name, value in self._attributes.items():
323 try:
324 value = attr[name]
325 except KeyError: pass
326 self.attributes[name] = value
327
330
332 self.scaled = []
333 for x,y in self.points:
334 self.scaled.append(((scale[0]*x)+shift[0],\
335 (scale[1]*y)+shift[1]))
336 self.attributes.get('anchor', 0.0)
337 self.anchor = scale[1]*self.attributes.get('anchor', 0.0)+\
338 shift[1]
339
343
344 _attributes = {'color': 'black',
345 'width': 1,
346 'smooth': 0,
347 'splinesteps': 12}
348
349 - def draw(self, canvas):
350 color = self.attributes['color']
351 width = self.attributes['width']
352 smooth = self.attributes['smooth']
353 steps = self.attributes['splinesteps']
354 arguments = (canvas,)
355 if smooth:
356 for i in range(len(self.points)):
357 x1, y1 = self.scaled[i]
358 arguments = arguments + (x1, y1)
359 else:
360 for i in range(len(self.points)-1):
361 x1, y1 = self.scaled[i]
362 x2, y2 = self.scaled[i+1]
363 arguments = arguments + (x1, y1, x2, y2)
364 apply(Line, arguments, {'fill': color, 'width': width,
365 'smooth': smooth, 'splinesteps':steps})
366
370
371 _attributes = {'color': 'black',
372 'width': 1,
373 'fillcolor': 'black',
374 'size': 2,
375 'fillstyle': '',
376 'outline': 'black',
377 'marker': 'circle'}
378
379 - def draw(self, canvas):
380 color = self.attributes['color']
381 size = self.attributes['size']
382 fillcolor = self.attributes['fillcolor']
383 marker = self.attributes['marker']
384 fillstyle = self.attributes['fillstyle']
385
386 self._drawmarkers(canvas, self.scaled, marker, color,
387 fillstyle, fillcolor, size)
388
389 - def _drawmarkers(self, c, coords, marker='circle', color='black',
390 fillstyle='', fillcolor='', size=2):
391 l = []
392 f = eval('self._' +marker)
393 for xc, yc in coords:
394 id = f(c, xc, yc, outline=color, size=size,
395 fill=fillcolor, fillstyle=fillstyle)
396 if type(id) is type(()):
397 for item in id: l.append(item)
398 else:
399 l.append(id)
400 return l
401
402 - def _circle(self, c, xc, yc, size=1, fill='', outline='black',
403 fillstyle=''):
404 id = c.create_oval(xc-0.5, yc-0.5, xc+0.5, yc+0.5,
405 fill=fill, outline=outline,
406 stipple=fillstyle)
407 c.scale(id, xc, yc, size*5, size*5)
408 return id
409
410 - def _dot(self, c, xc, yc, size=1, fill='', outline='black',
411 fillstyle=''):
412 id = c.create_oval(xc-0.5, yc-0.5, xc+0.5, yc+0.5,
413 fill=fill, outline=outline,
414 stipple=fillstyle)
415 c.scale(id, xc, yc, size*2.5, size*2.5)
416 return id
417
418 - def _square(self, c, xc, yc, size=1, fill='', outline='black',
419 fillstyle=''):
420 id = c.create_rectangle(xc-0.5, yc-0.5, xc+0.5, yc+0.5,
421 fill=fill, outline=outline,
422 stipple=fillstyle)
423 c.scale(id, xc, yc, size*5, size*5)
424 return id
425
426 - def _triangle(self, c, xc, yc, size=1, fill='', outline='black',
427 fillstyle=''):
428 id = c.create_polygon(-0.5, 0.288675134595,
429 0.5, 0.288675134595,
430 0.0, -0.577350269189, fill=fill,
431 outline=outline, stipple=fillstyle)
432 c.move(id, xc, yc)
433 c.scale(id, xc, yc, size*5, size*5)
434 return id
435
436 - def _triangle_down(self, c, xc, yc, size=1, fill='',
437 outline='black', fillstyle=''):
438 id = c.create_polygon(-0.5, -0.288675134595,
439 0.5, -0.288675134595,
440 0.0, 0.577350269189, fill=fill,
441 outline=outline, stipple=fillstyle)
442 c.move(id, xc, yc)
443 c.scale(id, xc, yc, size*5, size*5)
444 return id
445
446 - def _cross(self, c, xc, yc, size=1, fill='black', outline=None,
447 fillstyle=''):
448 if outline: fill=outline
449 id1 = c.create_line(xc-0.5, yc-0.5, xc+0.5, yc+0.5,
450 fill=fill)
451 id2 = c.create_line(xc-0.5, yc+0.5, xc+0.5, yc-0.5,
452 fill=fill)
453 c.scale(id1, xc, yc, size*5, size*5)
454 c.scale(id2, xc, yc, size*5, size*5)
455 return id1, id2
456
457 - def _plus(self, c, xc, yc, size=1, fill='black', outline=None,
458 fillstyle=''):
459 if outline: fill=outline
460 id1 = c.create_line(xc-0.5, yc, xc+0.5, yc, fill=fill)
461 id2 = c.create_line(xc, yc+0.5, xc, yc-0.5, fill=fill)
462 c.scale(id1, xc, yc, size*5, size*5)
463 c.scale(id2, xc, yc, size*5, size*5)
464 return id1, id2
465
469
470 _attributes = {'color': 'black',
471 'width': 1,
472 'fillcolor': 'black',
473 'size': 3,
474 'fillstyle': '',
475 'outline': 'black'}
476
477 - def draw(self, canvas):
478 color = self.attributes['color']
479 width = self.attributes['width']
480 fillstyle = self.attributes['fillstyle']
481 outline = self.attributes['outline']
482 spread = self.attributes['size']
483 arguments = (canvas,)
484 p1, p2 = self.boundingBox()
485 for i in range(len(self.points)):
486 x1, y1 = self.scaled[i]
487 canvas.create_rectangle(x1-spread, y1, x1+spread,
488 self.anchor, fill=color,
489 width=width, outline=outline,
490 stipple=fillstyle)
491
494 self.objects = objects
495
497 c1, c2 = self.objects[0].boundingBox()
498 for object in self.objects[1:]:
499 c1o, c2o = object.boundingBox()
500 c1 = minBound([c1, c1o])
501
502 c2 = maxBound([c2, c2o])
503 return c1, c2
504
506 for object in self.objects:
507 object.fitToScale(scale, shift)
508
509 - def draw(self, canvas):
510 for object in self.objects:
511 object.draw(canvas)
512
514 - def __init__(self, master, width, height,
515 background='white',title="",xtitle='',ytitle='', **kw):
516 apply(Frame.__init__, (self, master), kw)
517 self.title=title
518 self.xtitle=xtitle
519 self.ytitle=ytitle
520 self.canvas = Canvas(self, width=width, height=height,
521 background=background)
522 self.canvas.pack(fill=BOTH, expand=YES)
523 border_w = self.canvas.winfo_reqwidth() - \
524 string.atoi(self.canvas.cget('width'))
525 border_h = self.canvas.winfo_reqheight() - \
526 string.atoi(self.canvas.cget('height'))
527 self.border = (border_w, border_h)
528 self.canvas.bind('<Configure>', self.configure)
529 self.plotarea_size = [None, None]
530 self._setsize()
531 self.last_drawn = None
532 self.font = ('Verdana', 10)
533
545
546 - def bind(self, *args):
547 apply(self.canvas.bind, args)
548
550 self.width = string.atoi(self.canvas.cget('width'))
551 self.height = string.atoi(self.canvas.cget('height'))
552
553
554 self.plotarea_size[0] = 0.90 * self.width
555 self.plotarea_size[1] = 0.90 * -self.height
556 xo = 0.5*(self.width-self.plotarea_size[0])
557 yo = self.height-0.5*(self.height+self.plotarea_size[1])
558 self.plotarea_origin = (xo, yo)
559
560 - def draw(self, graphics, xaxis = 'automatic', yaxis = 'automatic'):
561
562 self.last_drawn = (graphics, xaxis, yaxis)
563 p1, p2 = graphics.boundingBox()
564 xaxis = self._axisInterval(xaxis, p1[0], p2[0])
565 yaxis = self._axisInterval(yaxis, p1[1], p2[1])
566 text_width = [0., 0.]
567 text_height = [0., 0.]
568 if xaxis is not None:
569 p1 = xaxis[0], p1[1]
570 p2 = xaxis[1], p2[1]
571 xticks = self._ticks(xaxis[0], xaxis[1])
572 bb = self._textBoundingBox(xticks[0][1])
573 text_height[1] = bb[3]-bb[1]
574 text_width[0] = 0.5*(bb[2]-bb[0])
575 bb = self._textBoundingBox(xticks[-1][1])
576 text_width[1] = 0.5*(bb[2]-bb[0])
577 else:
578 xticks = None
579 if yaxis is not None:
580 p1 = p1[0], yaxis[0]
581 p2 = p2[0], yaxis[1]
582 yticks = self._ticks(yaxis[0], yaxis[1])
583 for y in yticks:
584 bb = self._textBoundingBox(y[1])
585 w = bb[2]-bb[0]
586 text_width[0] = max(text_width[0], w)
587 h = 0.5*(bb[3]-bb[1])
588 text_height[0] = h
589 text_height[1] = max(text_height[1], h)
590 else:
591 yticks = None
592 text1 = [text_width[0], -text_height[1]]
593 text2 = [text_width[1], -text_height[0]]
594 scale = ((self.plotarea_size[0]-text1[0]-text2[0]) / \
595 (p2[0]-p1[0]),
596 (self.plotarea_size[1]-text1[1]-text2[1]) / \
597 (p2[1]-p1[1]))
598 shift = ((-p1[0]*scale[0]) + self.plotarea_origin[0] + \
599 text1[0],
600 (-p1[1]*scale[1]) + self.plotarea_origin[1] + \
601 text1[1])
602 self._drawAxes(self.canvas, xaxis, yaxis, p1, p2,
603 scale, shift, xticks, yticks)
604 graphics.fitToScale(scale, shift)
605 graphics.draw(self.canvas)
606
608 if spec is None:
609 return None
610 if spec == 'minimal':
611 if lower == upper:
612 return lower-0.5, upper+0.5
613 else:
614 return lower, upper
615 if spec == 'automatic':
616 range = upper-lower
617 if range == 0.:
618 return lower-0.5, upper+0.5
619 log = math.log10(range)
620 power = math.floor(log)
621 fraction = log-power
622 if fraction <= 0.05:
623 power = power-1
624 grid = 10.**power
625 lower = lower - lower % grid
626 mod = upper % grid
627 if mod != 0:
628 upper = upper - mod + grid
629 return lower, upper
630 if type(spec) == type(()):
631 lower, upper = spec
632 if lower <= upper:
633 return lower, upper
634 else:
635 return upper, lower
636 raise ValueError, str(spec) + ': illegal axis specification'
637
638 - def _drawAxes(self, canvas, xaxis, yaxis,
639 bb1, bb2, scale, shift, xticks, yticks):
640 dict = {'anchor': N, 'fill': 'black'}
641 if self.font is not None:
642 dict['font'] = self.font
643 if xaxis is not None:
644
645 lower, upper = xaxis
646 text = 1
647 once=1
648 for y, d in [(bb1[1], -3), (bb2[1], 3)]:
649
650 p1 = (scale[0]*lower)+shift[0], (scale[1]*y)+shift[1]
651 if once: pp1=p1
652 p2 = (scale[0]*upper)+shift[0], (scale[1]*y)+shift[1]
653 if once: pp2=p2
654 once = 0
655 Line(self.canvas, p1[0], p1[1], p2[0], p2[1],
656 fill = 'black', width = 1)
657 if xticks:
658 for x, label in xticks:
659 p = (scale[0]*x)+shift[0], \
660 (scale[1]*y)+shift[1]
661 Line(self.canvas, p[0], p[1], p[0], p[1]+d,
662 fill = 'black', width = 1)
663 if text:
664 dict['text'] = label
665 apply(CanvasText, (self.canvas, p[0],
666 p[1]+2), dict)
667 text = 0
668
669 CanvasText(self.canvas,(pp2[0]-pp1[0])/2.+pp1[0],pp1[1]+22,text=self.xtitle)
670
671 CanvasText(self.canvas,(pp2[0]-pp1[0])/2.+pp1[0],7,text=self.title)
672 dict['anchor'] = E
673 if yaxis is not None:
674
675 lower, upper = yaxis
676 text = 1
677 once = 1
678 for x, d in [(bb1[0], -3), (bb2[0], 3)]:
679 p1 = (scale[0]*x)+shift[0], (scale[1]*lower)+shift[1]
680 p2 = (scale[0]*x)+shift[0], (scale[1]*upper)+shift[1]
681 if once: pp1=p1 ;pp2=p2
682 once = 0
683 Line(self.canvas, p1[0], p1[1], p2[0], p2[1],
684 fill = 'black', width = 1)
685 if yticks:
686 for y, label in yticks:
687 p = (scale[0]*x)+shift[0], \
688 (scale[1]*y)+shift[1]
689 Line(self.canvas, p[0], p[1], p[0]-d, p[1],
690 fill = 'black', width = 1)
691 if text:
692 dict['text'] = label
693 apply(CanvasText,(self.canvas,
694 p[0]-4,p[1]+2), dict)
695 text = 0
696
697 CanvasText(self.canvas,pp2[0],pp2[1] - 10,text=self.ytitle)
698
699 - def _ticks(self, lower, upper):
700 ideal = (upper-lower)/7.
701 log = math.log10(ideal)
702 power = math.floor(log)
703 fraction = log-power
704 factor = 1.
705 error = fraction
706 for f, lf in self._multiples:
707 e = math.fabs(fraction-lf)
708 if e < error:
709 error = e
710 factor = f
711 grid = factor * 10.**power
712 if power > 3 or power < -3:
713 format = '%+7.0e'
714 elif power >= 0:
715 digits = max(1, int(power))
716 format = '%' + `digits`+'.0f'
717 else:
718 digits = -int(power)
719 format = '%'+`digits+2`+'.'+`digits`+'f'
720 ticks = []
721 t = -grid*math.floor(-lower/grid)
722 while t <= upper and len(ticks) < 200:
723 ticks.append((t, format % (t,)))
724 t = t + grid
725 return ticks
726
727 _multiples = [(2., math.log10(2.)), (5., math.log10(5.))]
728
729 - def _textBoundingBox(self, text):
730 bg = self.canvas.cget('background')
731 dict = {'anchor': NW, 'text': text, 'fill': bg}
732 if self.font is not None:
733 dict['font'] = self.font
734 item = apply(CanvasText, (self.canvas, 0., 0.), dict)
735 bb = self.canvas.bbox(item)
736 self.canvas.delete(item)
737 return bb
738
740 if self.last_drawn is not None:
741 apply(self.draw, self.last_drawn)
742
744 self.canvas.delete('all')
745
746 - def postscr(self,filename=None):
747 """Write to Postscript file given by 'filename'. If none provided,
748 ask user.
749 """
750 from tkFileDialog import asksaveasfilename
751 if not filename:
752 filename=asksaveasfilename()
753 if filename:
754 if not filename[-3:] == '.ps':
755 filename+=".ps"
756 self.canvas.postscript(width=self.width,height=self.height,file=filename)
757
758 -class TextBox(Frame):
759 - def __init__(self, master, width, height,
760 background='white',boxtext='', **kw):
761 apply(Frame.__init__, (self, master), kw)
762 self.width=width
763 self.height=height
764 self.canvas=Canvas(self, width=width, height=height,
765 background=background)
766 self.canvas.pack(fill=BOTH, expand=YES)
767
768
770
771
772 filename=asksaveasfilename()
773 if filename:
774 if not filename[-3:] == '.ps':
775 filename+=".ps"
776 self.canvas.postscript(width=self.width,height=self.height,file=filename)
777
778 if __name__ == '__main__':
779 print "SimPlot.py %s"%__version__
780 root=Tk()
781 plt=SimPlot()
782 root.title('SimPlot example - First frame')
783
784 root1 = Tk()
785 root1.title('SimPlot example - Second frame')
786
787 """PARAMETER DEFAULTS:
788 GraphBase
789 ---------
790 background='white',
791 title="",
792 xtitle='',
793 ytitle=''
794
795 GraphBase.draw
796 --------------
797 xaxis = 'automatic',
798 yaxis = 'automatic')
799
800 GraphLine
801 ---------
802 color: 'black',
803 width: 1,
804 smooth: 0,
805 splinesteps: 12
806
807 GraphSymbols:
808 -------------
809 color: 'black',
810 width: 1,
811 fillcolor: 'black',
812 size: 2,
813 fillstyle: '',
814 outline: 'black',
815 marker: 'circle'}
816
817 GraphBars
818 ---------
819 color: 'black',
820 width: 1,
821 fillcolor: 'black',
822 size: 3,
823 fillstyle: '',
824 outline: 'black'
825 """
826
827 di = 5.0*pi/40.
828 data = []
829 for i in range(40):
830 data.append((float(i)*di,
831 (math.sin(float(i)*di)-math.cos(float(i)*di))))
832 line1 = plt.makeLine(data, color='black', width=1,
833 smooth=1)
834 line1a = plt.makeBars(data[1:], color='blue', fillstyle='gray25',
835 anchor=0.0)
836
837
838 graphObject=plt.makeGraphObjects([line1a,line1])
839
840 line2 = plt.makeBars([(0,0),(1,145),(2,-90),(3,147),(4,22),(5,31),
841 (6,77),(7,125),(8,220),(9,550),(10,560),(11,0)],
842 outline='green',color='red', size=7)
843
844
845 graphObject2=plt.makeGraphObjects([line2])
846
847
848 line3 = plt.makeLine([(1,145+100),(2,151+100),(3,147+100),(4,22+100),(5,31+100),
849 (6,77+100),(7,125+100),(8,220+100),(9,550+100),(10,560+100)],
850 color='blue', width=2, smooth=1)
851 line3a = plt.makeLine([(1,145),(2,151),(3,147),(4,22),(5,31),
852 (6,77),(7,125),(8,220),(9,550),(10,560)],
853 color='green', width=2, smooth=0)
854 line3b = plt.makeStep([(1,145+100),(2,151+100),(3,147+100),(4,22+100),(5,31+100),
855 (6,77+100),(7,125+100),(8,220+100),(9,550+100),(10,560+100)],
856 color='red', width=2)
857
858 graphObject3 = plt.makeGraphObjects([line3, line3a, line3b])
859
860
861
862
863 line4 = plt.makeSymbols([(1,100),(2,100),(3,100),(4,100),(5,100),
864 (6,100),(7,100),(8,100),(9,100),(10,100)],
865 color='black',fillcolor='red', width=2,marker='triangle')
866 line5 = plt.makeSymbols([(1,200),(2,200),(3,200),(4,200),(5,200),
867 (6,200),(7,200),(8,200),(9,200),(10,200)],
868 color='red', width=2,marker='circle')
869 line6 = plt.makeSymbols([(1,300),(2,300),(3,300),(4,300),(5,300),
870 (6,300),(7,300),(8,300),(9,300),(10,300)],
871 color='green', width=2,marker='dot')
872 line7 = plt.makeSymbols([(1,400),(2,400),(3,400),(4,400),(5,400),
873 (6,400),(7,400),(8,400),(9,400),(10,400)],
874 color='blue', fillcolor='white',
875 size=2, width=2,marker='square')
876 line8 = plt.makeSymbols([(1,500),(2,500),(3,500),(4,500),(5,500),
877 (6,500),(7,500),(8,500),(9,500),(10,500)],
878 color='yellow', width=2,marker='triangle')
879 line9 = plt.makeSymbols([(1,600),(2,600),(3,600),(4,600),(5,600),
880 (6,600),(7,600),(8,600),(9,600),(10,600)],
881 color='magenta', width=2,marker='cross')
882 line10 = plt.makeSymbols([(1,700),(2,700),(3,700),(4,700),(5,700),
883 (6,700),(7,700),(8,700),(9,700),(10,700)],
884 color='brown', width=2,marker='plus')
885 line11 = plt.makeSymbols([(1,800),(2,800),(3,800),(4,800),(5,800),
886 (6,800),(7,800),(8,800),(9,800),(10,800)],
887 color='black', fillcolor='orange',
888 width=2,marker='triangle_down')
889
890
891 graphObject4 = GraphObjects([line4, line5, line6, line7, line8,
892 line9, line10, line11])
893
894
895 f1 = Frame(root)
896 f2 = Frame(root1)
897
898 graph={}
899
900 graph[1]= plt.makeGraphBase(f1, 500, 300, title="Plot 1: 1 makeLine call, 1 makeBars call",
901 xtitle='the x-axis',ytitle='the y-axis')
902 graph[1].pack(side=LEFT, fill=BOTH, expand=YES)
903 graph[1].draw(graphObject,xaxis='minimal', yaxis='minimal')
904
905 graph[2] = plt.makeGraphBase(f1, 500, 300,title="Plot 2: 1 makeBars call",
906 xtitle='time',ytitle='pulse [volt]')
907
908 graph[2].pack(side=LEFT, fill=BOTH, expand=YES)
909 graph[2].draw(graphObject2, 'minimal', 'automatic')
910
911
912 f1.pack()
913
914
915 graph[3] = plt.makeGraphBase(f2, 500, 300,
916 title="Plot 3: 2 makeLine call (smooth, not smooth); 1 makeStep call")
917 graph[3].pack(side=TOP, fill=BOTH, expand=YES)
918 graph[3].draw(graphObject3)
919
920 graph[4] = plt.makeGraphBase(f2, 500, 300, border=3,title="Plot 4: 8 makeSymbols calls")
921
922 graph[4].pack(side=TOP, fill=BOTH, expand=YES)
923 graph[4].draw(graphObject4)
924
925
926 f2.pack()
927
928
929 graph[1].postscr()
930
931
932
933
934 plt.mainloop()
935