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