1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 from mglutil.util.callback import CallBackFunction
28 from NetworkEditor.widgets import TkPortWidget, PortWidget
29 import Pmw,math,os
30 from matplotlib.colors import cnames
31 from matplotlib.lines import Line2D,lineStyles,TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN
32 from matplotlib.transforms import Value
33 from matplotlib import rcParams
34 from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel
35 from Numeric import array
36 """
37 This module implements Vision nodes exposing matplotlib functionatility.
38
39 MPLBaseNE:
40 ---------
41 The class provides a base class for all nodes exposing matplotlib functionality
42
43 its purpose is to to create the attributes described below and implement
44 methods shared by all nodes.
45
46 Attributes:
47 self.figure = None: # node's figure object
48 # This attribute always points to the matplotlib Figure object which has
49 # a FigureCanvasTkAgg object in its .canvas attribute
50
51 # self.canvas FigureCanvasTkAgg
52
53 self.axes = None
54 # This attribute points to the matplotlib Axes instance used by this node
55
56 self.axes.figure # figure in which the axes is currently drawn
57
58 Methods:
59 def createFigure(self, master=None, width=None, height=None, dpi=None,
60 facecolor=None, edgecolor=None, frameon=None,
61 packOpts=None, toolbar=True):
62
63 # This method is used by all nodes if they need to create a Figure object
64 # from the matplotlib library and a FigureCanvasTkAgg object for this
65 # figure.
66
67 def setFigure(self, figure):
68 # This method place the node's axes object into the right Figure
69
70
71 def beforeRemovingFromNetwork(self):
72 # this method is called when a node is deleted from a network. Its job is
73 # to delete FigureCanvasTkAgg and Axes when appropriate.
74
75
76 MPLFigure:
77 -----------
78 The MPLFigure node allows the creation of a plotting area in which one
79 or more Axes can be added, where an Axes is a 2D graphical representation
80 of a data set (i.e. 2D plot). A 'master' can be apecified to embed the figure
81 in other panels. This node provides control over parameter that apply to the
82 MPLFigure such, width, height, dpi, etc.
83
84
85 Plotting Node:
86 -------------
87 Plotting nodes such as Histogram, Plot, Scatter, Pie, etc. take adtasets and
88 render them as 2D plots. They alwas own the axes.
89 If the data to be rendered is the only input to these nodes, they will create
90 a default Figure, add a default Plot2D to this figure, and draw the data in
91 this default 2D plot.
92 """
93
94 from Vision import UserLibBuild
95 from NetworkEditor.items import NetworkNode
96
97 import Tkinter
98 import matplotlib
99 import types
100 import weakref
101
102
103
104 matplotlib.use('TkAgg')
105
106 from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
107 from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg
108 from matplotlib.figure import Figure as OriginalFigure
109 from matplotlib.axes import Axes, Subplot, PolarSubplot, PolarAxes
110 from matplotlib.pylab import *
111 from Vision.colours import get_colours
112 from Vision.posnegFill import posNegFill
113 from matplotlib import numerix
114 from matplotlib.artist import setp
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152 from matplotlib.cbook import iterable, popd
153 try:
154 from matplotlib.dates import DayLocator, HourLocator, \
155 drange, date2num, timezone
156 except:
157 pass
158 try:
159 from pytz import common_timezones
160 except:
161 common_timezones=[]
162
163 locations={'best' : 0,
164 'upper right' : 1,
165 'upper left' : 2,
166 'lower left' : 3,
167 'lower right' : 4,
168 'right' : 5,
169 'center left' : 6,
170 'center right' : 7,
171 'lower center' : 8,
172 'upper center' : 9,
173 'center' : 10,}
174 colors={
175 'blue' : 'b',
176 'green' : 'g',
177 'red' : 'r',
178 'cyan' : 'c',
179 'magenta' :'m',
180 'yellow' :'y',
181 'black': 'k',
182 'white' : 'w',
183 }
184
185 markers= {
186 'square' : 's',
187 'circle' : 'o',
188 'triangle up' : '^',
189 'triangle right' : '>',
190 'triangle down' : 'v',
191 'triangle left' : '<',
192 'diamond' : 'd',
193 'pentagram' : 'p',
194 'hexagon' : 'h',
195 'octagon' : '8',
196 }
197
198 cmaps=['autumn','bone', 'cool','copper','flag','gray','hot','hsv','jet','pink', 'prism', 'spring', 'summer', 'winter']
199
201 styles={}
202 for ls in Line2D._lineStyles.keys():
203 styles[Line2D._lineStyles[ls][6:]]=ls
204 for ls in Line2D._markers.keys():
205 styles[Line2D._markers[ls][6:]]=ls
206
207 if styles.has_key('steps'):
208 del styles['steps']
209 for s in styles.keys():
210 if s =="nothing":
211 del styles['nothing']
212 if s[:4]=='tick':
213 del styles[s]
214 return styles
215
259
260
261
263 """Base class for node wrapping the maptlotlib objects
264
265 """
266 - def __init__(self, name='MPLBase', **kw):
267 kw['name'] = name
268 apply( NetworkNode.__init__, (self,), kw )
269
270 self.figure = None
271 self.axes = None
272
273
274
275
276 self.ownsMaster = False
277
278
280 ax = self.axes
281
282 if kw.has_key('left'):
283 rect = [kw['left'], kw['bottom'], kw['width'], kw['height']]
284 ax.set_position(rect)
285 if kw.has_key('frameon'):
286 ax.set_frame_on(kw['frameon'])
287
288 if kw.has_key("title"):
289 if type(kw['title'])==types.StringType:
290 ax.set_title(kw['title'])
291 else:
292 print 'Set title as Object'
293 if kw.has_key("xlabel"):
294 ax.set_xlabel(kw['xlabel'])
295 if kw.has_key("ylabel"):
296 ax.set_ylabel(kw['ylabel'])
297 if kw.has_key("xlimit"):
298 if kw['xlimit']!='':
299 ax.set_xlim(eval(kw['xlimit']))
300 if kw.has_key("ylimit"):
301 if kw['ylimit']!='':
302 ax.set_ylim(eval(kw['ylimit']))
303 if kw.has_key("xticklabels"):
304 if not kw['xticklabels']:
305 ax.set_xticklabels([])
306 if kw.has_key("yticklabels"):
307 if not kw['yticklabels']:
308 ax.set_yticklabels([])
309 if kw.has_key("axison"):
310 if kw['axison']:
311 ax.set_axis_on()
312 else:
313 ax.set_axis_off()
314 if kw.has_key("autoscaleon"):
315 if kw['autoscaleon']:
316 ax.set_autoscale_on(True)
317 else:
318 ax.set_autoscale_on(False)
319 if kw.has_key("adjustable"):
320 ax.set_adjustable(kw['adjustable'])
321 if kw.has_key("aspect"):
322 ax.set_aspect(kw['aspect'])
323 if kw.has_key("anchor"):
324 ax.set_anchor(kw['anchor'])
325
326 if kw.has_key("axisbelow"):
327 if kw['axisbelow']==1:
328 val=True
329 else:
330 val=False
331 rcParams['axes.axisbelow']=val
332 ax.set_axisbelow(val)
333
334 if kw.has_key("gridOn"):
335 if kw['gridOn']==1:
336 ax._gridOn=True
337 val=True
338 if kw.has_key('gridcolor'):
339 gcolor=kw['gridcolor']
340 else:
341 gcolor=rcParams['grid.color']
342 if kw.has_key('gridlinestyle'):
343 glinestyle=kw['gridlinestyle']
344 else:
345 glinestyle=rcParams['grid.linestyle']
346 if kw.has_key('gridlinewidth'):
347 glinewidth=kw['gridlinewidth']
348 else:
349 glinewidth=rcParams['grid.linewidth']
350 if kw.has_key('whichgrid'):
351 whichgrid=kw['whichgrid']
352 else:
353 whichgrid='major'
354 ax.grid(val,color=gcolor, linestyle=glinestyle, linewidth=glinewidth,which=whichgrid)
355 else:
356 val=False
357 ax.grid(val)
358
359 if kw.has_key("facecolor"):
360 ax.set_axis_bgcolor(kw['facecolor'])
361 if kw.has_key("edgecolor"):
362 ax.axesFrame.set_color(kw['edgecolor'])
363 if kw.has_key('zoomx'):
364
365 ax.zoomx(kw['zoomx'])
366
367 if kw.has_key('zoomy'):
368
369 ax.zoomy(kw['zoomy'])
370
371 if kw.has_key("xtick.color"):
372 for i in ax.xaxis.get_ticklabels():
373 i.set_color(kw['xtick.color'])
374 if kw.has_key("ytick.color"):
375 for i in ax.yaxis.get_ticklabels():
376 i.set_color(kw['ytick.color'])
377
378 if kw.has_key('xtick.labelrotation'):
379 for i in ax.xaxis.get_ticklabels():
380 i.set_rotation(float(kw['xtick.labelrotation']))
381 if kw.has_key('ytick.labelrotation'):
382 for i in ax.yaxis.get_ticklabels():
383 i.set_rotation(float(kw['ytick.labelrotation']))
384 if kw.has_key("xtick.labelsize"):
385 for i in ax.xaxis.get_ticklabels():
386 i.set_size(float(kw['xtick.labelsize']))
387 if kw.has_key("ytick.labelsize"):
388 for i in ax.yaxis.get_ticklabels():
389 i.set_size(float(kw['ytick.labelsize']))
390 if kw.has_key("linewidth"):
391 ax.axesFrame.set_linewidth(float(kw['linewidth']))
392
393
394 if kw.has_key("markeredgewidth"):
395 for i in ax.get_xticklines():
396 i.set_markeredgewidth(kw['markeredgewidth'])
397 for i in ax.get_yticklines():
398 i.set_markeredgewidth(kw['markeredgewidth'])
399
400 if kw.has_key("markeredgecolor"):
401 for i in ax.get_xticklines():
402 i.set_markeredgecolor(kw['markeredgecolor'])
403 for i in ax.get_yticklines():
404 i.set_markeredgecolor(kw['markeredgecolor'])
405
406 if kw.has_key("markerfacecolor"):
407 for i in ax.get_xticklines():
408 i.set_markerfacecolor(kw['markerfacecolor'])
409 for i in ax.get_yticklines():
410 i.set_markerfacecolor(kw['markerfacecolor'])
411
412
413 if kw.has_key("figpatch_linewidth"):
414 ax.figure.figurePatch.set_linewidth(kw['figpatch_linewidth'])
415 if kw.has_key("figpatch_facecolor"):
416 ax.figure.figurePatch.set_facecolor(kw['figpatch_facecolor'])
417 if kw.has_key("figpatch_edgecolor"):
418 ax.figure.figurePatch.set_edgecolor(kw['figpatch_edgecolor'])
419 if kw.has_key("figpatch_antialiased"):
420 ax.figure.figurePatch.set_antialiased(kw['figpatch_antialiased'])
421
422
423 if kw.has_key('text'):
424 for i in kw['text']:
425 if type(i)==types.DictType:
426 tlab=i['textlabel']
427 posx=i['posx']
428 posy=i['posy']
429 horizontalalignment=i['horizontalalignment']
430 verticalalignment=i['verticalalignment']
431 rotation=i['rotation']
432 ax.text(x=posx,y=posy,s=tlab,horizontalalignment=horizontalalignment,verticalalignment=verticalalignment,rotation=rotation,transform = ax.transAxes)
433 if kw.has_key("text.color"):
434 for t in ax.texts:
435 t.set_color(kw['text.color'])
436 if kw.has_key("text.usetex"):
437 rcParams['text.usetex']=kw['text.usetex']
438 if kw.has_key("text.dvipnghack"):
439 rcParams['text.dvipnghack']=kw['text.dvipnghack']
440 if kw.has_key("text.fontstyle"):
441 for t in ax.texts:
442 t.set_fontstyle(kw['text.fontstyle'])
443 if kw.has_key("text.fontangle"):
444 for t in ax.texts:
445 t.set_fontangle(kw['text.fontangle'])
446 if kw.has_key("text.fontvariant"):
447 for t in ax.texts:
448 t.set_fontvariant(kw['text.fontvariant'])
449 if kw.has_key("text.fontweight"):
450 for t in ax.texts:
451 t.set_fontweight(kw['text.fontweight'])
452 if kw.has_key("text.fontsize"):
453 for t in ax.texts:
454 t.set_fontsize(kw['text.fontsize'])
455
456
457 if kw.has_key("Font.fontfamily"):
458 for t in ax.texts:
459 t.set_family(kw['Font.fontfamily'])
460 if kw.has_key("Font.fontstyle"):
461 for t in ax.texts:
462 t.set_fontstyle(kw['Font.fontstyle'])
463 if kw.has_key("Font.fontangle"):
464 for t in ax.texts:
465 t.set_fontangle(kw['Font.fontangle'])
466 if kw.has_key("Font.fontvariant"):
467 for t in ax.texts:
468 t.set_fontvariant(kw['Font.fontvariant'])
469 if kw.has_key("Font.fontweight"):
470 for t in ax.texts:
471 t.set_fontweight(kw['Font.fontweight'])
472 if kw.has_key("Font.fontsize"):
473 for t in ax.texts:
474 t.set_fontsize(kw['Font.fontsize'])
475
476
477 if kw.has_key('legendlabel'):
478 if ',' in kw['legendlabel']:
479 x=kw['legendlabel'].split(",")
480 else:
481 x=(kw['legendlabel'],)
482 if kw.has_key('legend.isaxes'):
483 isaxes=kw['legend.isaxes']
484 else:
485 isaxes=rcParams['legend.isaxes']
486
487 if kw.has_key('legend.numpoints'):
488 numpoints=kw['legend.numpoints']
489 else:
490 numpoints=rcParams['legend.numpoints']
491
492 if kw.has_key('legend.pad'):
493 pad=kw['legend.pad']
494 else:
495 pad=rcParams['legend.pad']
496
497 if kw.has_key('legend.markerscale'):
498 markerscale=kw['legend.markerscale']
499 else:
500 markerscale=rcParams['legend.markerscale']
501 if kw.has_key('legend.labelsep'):
502 labelsep=kw['legend.labelsep']
503 else:
504 labelsep=rcParams['legend.labelsep']
505 if kw.has_key('legend.handlelen'):
506 handlelen=kw['legend.handlelen']
507 else:
508 handlelen=rcParams['legend.handlelen']
509 if kw.has_key('legend.handletextsep'):
510 handletextsep=kw['legend.handletextsep']
511 else:
512 handletextsep=rcParams['legend.handletextsep']
513 if kw.has_key('legend.axespad'):
514 axespad=kw['legend.axespad']
515 else:
516 axespad=rcParams['legend.axespad']
517 if kw.has_key('legend.shadow'):
518 shadow=kw['legend.shadow']
519 else:
520 shadow=rcParams['legend.shadow']
521 leg=self.axes.legend(tuple(x),loc=kw['legendlocation'],isaxes=isaxes,numpoints=numpoints,pad=pad,labelsep=labelsep,handlelen=handlelen,handletextsep=handletextsep,axespad=axespad,shadow=shadow,markerscale=markerscale)
522 if kw.has_key('legend.fontsize'):
523 setp(ax.get_legend().get_texts(),fontsize=kw['legend.fontsize'])
524
525
526 if kw.has_key('xtick.major.pad'):
527 for i in ax.xaxis.majorTicks:
528 i.set_pad(kw['xtick.major.pad'])
529 if kw.has_key('xtick.minor.pad'):
530 for i in ax.xaxis.minorTicks:
531 i.set_pad(kw['xtick.minor.pad'])
532 if kw.has_key('ytick.major.pad'):
533 for i in ax.yaxis.majorTicks:
534 i.set_pad(kw['ytick.major.pad'])
535 if kw.has_key('ytick.minor.pad'):
536 for i in ax.yaxis.minorTicks:
537 i.set_pad(kw['ytick.minor.pad'])
538 if kw.has_key('xtick.major.size'):
539 rcParams['xtick.major.size']=kw['xtick.major.size']
540 if kw.has_key('xtick.minor.size'):
541 rcParams['xtick.minor.size']=kw['xtick.minor.size']
542 if kw.has_key('xtick.direction'):
543 rcParams['xtick.direction']=kw['xtick.direction']
544 if kw.has_key('ytick.major.size'):
545 rcParams['ytick.major.size']=kw['ytick.major.size']
546 if kw.has_key('ytick.minor.size'):
547 rcParams['ytick.minor.size']=kw['ytick.minor.size']
548 if kw.has_key('ytick.direction'):
549 rcParams['ytick.direction']=kw['ytick.direction']
550
551
552
554
555 NetworkNode.beforeRemovingFromNetwork(self)
556
557 if self.axes:
558
559 self.axes.figure.delaxes(self.axes)
560 self.canvas._tkcanvas.master.destroy()
561 elif self.canvas:
562 self.canvas._tkcanvas.master.destroy()
563
564
566 """returns true if only he first port (i.e. data) has new data.
567 """
568
569
570
571 ports = self.inputPorts
572 if not ports[0].hasNewData():
573 return False
574 for p in self.inputPorts:
575 if p.hasNewData():
576 return False
577
578 return True
579
580
581
763
765 """This node creates a PIL image
766
767 Input:
768 plots - Matplotlib Axes objects
769 figwidth - width in inches
770 figheigh - height in inches
771 dpi - resolution; defaults to rc figure.dpi
772 facecolor - the background color; defaults to rc figure.facecolor
773 edgecolor - the border color; defaults to rc figure.edgecolor
774 faceAlpha - alpha value of background
775 edgeAlpha - alpha value of edge
776 frameon - boolean
777 hold - boolean
778 toolbar - boolean (init option only)
779 packOpts - string representation of packing options
780
781 Output:
782 canvas: MPLFigure Object
783
784 Todo:
785 legend
786 text
787 image ?
788 """
789
790 - def __init__(self, name='imageFigure', **kw):
791 kw['name'] = name
792 apply( MPLBaseNE.__init__, (self,), kw )
793
794 codeBeforeDisconnect = """def beforeDisconnect(self, c):
795 node1 = c.port1.node
796 node2 = c.port2.node
797 if node1.figure.axes:
798 node1.figure.delaxes(node1.axes)
799 node1.figure.add_axes(node1.axes)
800 """
801 ip = self.inputPortsDescr
802 ip.append(datatype='MPLAxes', required=False, name='plots',
803 singleConnection=False,
804 beforeDisconnect=codeBeforeDisconnect)
805 ip.append(datatype='float', required=False, name='width')
806 ip.append(datatype='float', required=False, name='height')
807 ip.append(datatype='int', required=False, name='dpi')
808 ip.append(datatype='colorsRGB', required=False, name='facecolor')
809 ip.append(datatype='colorsRGB', required=False, name='edgecolor')
810 ip.append(datatype='float', required=False, name='alphaFace')
811 ip.append(datatype='float', required=False, name='alphaEdge')
812 ip.append(datatype='boolean', required=False, name='frameon')
813 ip.append(datatype='boolean', required=False, name='hold')
814
815 op = self.outputPortsDescr
816 op.append(datatype='image', name='image')
817
818 self.widgetDescr['width'] = {
819 'class':'NEThumbWheel','master':'ParamPanel',
820 'width':75, 'height':21, 'oneTurn':2, 'type':'float',
821 'wheelPad':2, 'initialValue':6.4,
822 'labelCfg':{'text':'width in inches'} }
823
824 self.widgetDescr['height'] = {
825 'class':'NEThumbWheel','master':'ParamPanel',
826 'width':75, 'height':21, 'oneTurn':2, 'type':'float',
827 'wheelPad':2, 'initialValue':4.8,
828 'labelCfg':{'text':'height in inches'} }
829
830 self.widgetDescr['dpi'] = {
831 'class':'NEThumbWheel','master':'ParamPanel',
832 'width':75, 'height':21, 'oneTurn':10, 'type':'int',
833 'wheelPad':2, 'initialValue':80,
834 'labelCfg':{'text':'DPI'} }
835
836 self.widgetDescr['alphaFace'] = {
837 'class':'NEThumbWheel','master':'ParamPanel',
838 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
839 'wheelPad':2, 'initialValue':0.5, 'min':0.0, 'max':1.0,
840 'labelCfg':{'text':'alpha Face'} }
841
842 self.widgetDescr['alphaEdge'] = {
843 'class':'NEThumbWheel','master':'ParamPanel',
844 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
845 'wheelPad':2, 'initialValue':0.5, 'min':0.0, 'max':1.0,
846 'labelCfg':{'text':'alphaEdge'} }
847
848 self.widgetDescr['frameon'] = {
849 'class':'NECheckButton', 'master':'ParamPanel',
850 'initialValue':1, 'labelCfg':{'text':'frame'} }
851
852 self.widgetDescr['hold'] = {
853 'class':'NECheckButton', 'master':'ParamPanel',
854 'initialValue':0, 'labelCfg':{'text':'hold'} }
855
856 code = """def doit(self, plots=None, width=None, height=None, dpi=None, facecolor=None, edgecolor=None, alphaFace=0.5, alphaEdge=0.5, frameon=True, hold=False):
857 figure = self.figure
858 try:
859 self.canvas.renderer.clear()
860 except AttributeError:
861 pass
862 figure.clear()
863
864 # Powers of 2 image to be clean
865 if width>height:
866 htc = float(height)/width
867 w = 512
868 h = int(512*htc)
869 else:
870 wtc = float(width)/height
871 w = int(512*wtc)
872 h = 512
873
874 dpi = figure.get_dpi()
875
876
877 #figure.set_figsize_inches(width,height)
878 figure.set_figsize_inches(w / dpi, h / dpi)
879
880 for p in plots:
881 if hasattr(p,"figure"):
882 p.figure.set_figwidth(w / dpi)
883 p.figure.set_figheight(h / dpi)
884 figure.add_axes(p)
885 p.set_figure(figure)
886 p.axesPatch.set_alpha(alphaFace)
887
888 # configure dpi
889 if dpi is not None:
890 figure.set_dpi(dpi)
891
892 # configure facecolor
893 if facecolor is not None:
894 figure.set_facecolor(tuple(facecolor[0]))
895
896 # configure edgecolor
897 if edgecolor is not None:
898 figure.set_edgecolor(tuple(edgecolor[0]))
899
900 # configure frameon
901 if frameon is not None:
902 figure.set_frameon(frameon)
903
904 figure.hold(hold)
905
906 figure.figurePatch.set_alpha(alphaEdge)
907 self.canvas.draw() # force a draw
908
909 import Image
910 im = self.canvas.buffer_rgba(0,0)
911 ima = Image.frombuffer("RGBA", (w,h), im)
912 ima = ima.transpose(Image.FLIP_TOP_BOTTOM)
913
914 self.outputData(image=ima)
915 """
916 self.setFunction(code)
917
918
925
927 self.figure = Figure()
928 from matplotlib.backends.backend_agg import FigureCanvasAgg
929 self.canvas = FigureCanvasAgg(self.figure)
930
931
932
934 """Class for configuring the axes.
935 The following options can be set.
936 left,bottom,width,height ----allows to set the position of the axes.
937 frame on/off --- allows to on or off frame
938 hold on/off --- allows to on or off hold.When hold is True, subsequent plot commands will be added to
939 the current axes. When hold is False, the current axes and figure will be cleared on
940 the next plot command
941 title --- allows to set title of the figure
942 xlabel ---allows to set xlabel of the figure
943 ylabel ---allows to set ylabel of the figure
944 xlimit --- set autoscale off before setting xlimit.
945 y limit --- set autoscale off before setting ylimit.
946 xticklabels on/off --- allows to on or off xticklabels
947 yticklabels on/off --- allows to on or off yticklabels
948 axis on/off --- allows to on or off axis
949 autoscale on/off --- when on sets default axes limits ,when off sets limit from xlimit and ylimit entries.
950 """
951
952 - def __init__(self, name='Draw Area', **kw):
953 kw['name'] = name
954 apply( NetworkNode.__init__, (self,), kw )
955
956 ip = self.inputPortsDescr
957 ip.append(datatype='float', required=False, name='left')
958 ip.append(datatype='float', required=False, name='bottom')
959 ip.append(datatype='float', required=False, name='width')
960 ip.append(datatype='float', required=False, name='height')
961 ip.append(datatype='boolean', required=False, name='frameon')
962 ip.append(datatype='boolean', required=False, name='hold')
963 ip.append(datatype='string', required=False, name='title')
964 ip.append(datatype='string', required=False, name='xlabel')
965 ip.append(datatype='string', required=False, name='ylabel')
966 ip.append(datatype='string', required=False, name='xlimit')
967 ip.append(datatype='string', required=False, name='ylimit')
968 ip.append(datatype='boolean', required=False, name='xticklabels')
969 ip.append(datatype='boolean', required=False, name='yticklabels')
970 ip.append(datatype='boolean', required=False, name='axison')
971 ip.append(datatype='boolean', required=False, name='autoscaleon')
972 self.widgetDescr['left'] = {
973 'class':'NEThumbWheel','master':'ParamPanel',
974 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
975 'labelGridCfg':{'sticky':'w'},
976 'wheelPad':2, 'initialValue':0.1,
977 'labelCfg':{'text':'left (0. to 1.)'} }
978
979 self.widgetDescr['bottom'] = {
980 'class':'NEThumbWheel','master':'ParamPanel',
981 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
982 'labelGridCfg':{'sticky':'w'},
983 'wheelPad':2, 'initialValue':0.1,
984 'labelCfg':{'text':'bottom (0. to 1.)'} }
985
986 self.widgetDescr['width'] = {
987 'class':'NEThumbWheel','master':'ParamPanel',
988 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
989 'labelGridCfg':{'sticky':'w'},
990 'wheelPad':2, 'initialValue':0.8,
991 'labelCfg':{'text':'width (0. to 1.)'} }
992
993 self.widgetDescr['height'] = {
994 'class':'NEThumbWheel','master':'ParamPanel',
995 'width':75, 'height':21, 'oneTurn':1., 'type':'float',
996 'labelGridCfg':{'sticky':'w'},
997 'wheelPad':2, 'initialValue':0.8,
998 'labelCfg':{'text':'height (0. to 1.0)'} }
999
1000 self.widgetDescr['frameon'] = {
1001 'class':'NECheckButton', 'master':'ParamPanel',
1002 'labelGridCfg':{'sticky':'w'},
1003 'initialValue':1, 'labelCfg':{'text':'frame'} }
1004
1005 self.widgetDescr['hold'] = {
1006 'class':'NECheckButton', 'master':'ParamPanel',
1007 'labelGridCfg':{'sticky':'w'},
1008 'initialValue':0, 'labelCfg':{'text':'hold'} }
1009
1010 self.widgetDescr['title'] = {
1011 'class':'NEEntry', 'master':'ParamPanel',
1012 'labelCfg':{'text':'title'},'labelGridCfg':{'sticky':'w'},
1013 'initialValue':'Figure:'}
1014
1015 self.widgetDescr['xlabel'] = {
1016 'class':'NEEntry', 'master':'ParamPanel',
1017 'labelCfg':{'text':'X label'},'labelGridCfg':{'sticky':'w'},
1018 'initialValue':'X'}
1019
1020 self.widgetDescr['ylabel'] = {
1021 'class':'NEEntry', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},
1022 'labelCfg':{'text':'Y label'},
1023 'initialValue':'Y'}
1024
1025 self.widgetDescr['xlimit'] = {
1026 'class':'NEEntry', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},
1027 'labelCfg':{'text':'X limit'},
1028 'initialValue':''}
1029
1030 self.widgetDescr['ylimit'] = {
1031 'class':'NEEntry', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},
1032 'labelCfg':{'text':'Y limit'},
1033 'initialValue':''}
1034
1035 self.widgetDescr['xticklabels'] = {
1036 'class':'NECheckButton', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},
1037 'initialValue':1, 'labelCfg':{'text':'xticklabels'} }
1038
1039 self.widgetDescr['yticklabels'] = {
1040 'class':'NECheckButton', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},'labelGridCfg':{'sticky':'w'},
1041 'initialValue':1, 'labelCfg':{'text':'yticklabels'} }
1042
1043
1044 self.widgetDescr['axison'] = {
1045 'class':'NECheckButton', 'master':'ParamPanel',
1046 'initialValue':1, 'labelCfg':{'text':'axis on'} }
1047 self.widgetDescr['autoscaleon'] = {
1048 'class':'NECheckButton', 'master':'ParamPanel','labelGridCfg':{'sticky':'w'},
1049 'initialValue':1, 'labelCfg':{'text':'autoscale on'} }
1050 op = self.outputPortsDescr
1051 op.append(datatype='MPLDrawArea', name='drawAreaDef')
1052
1053 code = """def doit(self, left=.1, bottom=.1,
1054 width=.8, height=.8, frameon=True, hold=False, title='Figure', xlabel='X',
1055 ylabel='Y', xlimit='',ylimit='',xticklabels=True,yticklabels=True,axison=True,autoscaleon=True):
1056
1057 kw = {'left':left, 'bottom':bottom, 'width':width, 'height':height,
1058 'frameon':frameon, 'hold':hold, 'title':title, 'xlabel':xlabel,
1059 'ylabel':ylabel, 'axison':axison, 'xticklabels': xticklabels,'yticklabels': yticklabels,'xlimit':xlimit,'ylimit':ylimit,'autoscaleon':autoscaleon}
1060
1061 self.outputData(drawAreaDef=kw)
1062 """
1063 self.setFunction(code)
1064
1065
1066 -class MPLMergeTextNE(NetworkNode):
1067 """Class for writting multiple labels in the axes.Takes input from Text
1068 nodes.
1069 """
1070 - def __init__(self, name='MergeText', **kw):
1071 kw['name'] = name
1072 apply( NetworkNode.__init__, (self,), kw )
1073 ip = self.inputPortsDescr
1074 ip.append(datatype='MPLDrawArea', required=False,name='textlist',singleConnection=False)
1075 op = self.outputPortsDescr
1076 op.append(datatype='MPLDrawArea', name='drawAreaDef')
1077 code = """def doit(self,textlist):
1078 kw={'text':textlist}
1079 self.outputData(drawAreaDef=kw)"""
1080 self.setFunction(code)
1081
1083 """Base class for plotting nodes"""
1084
1086
1087 self.figure = Figure()
1088 self.axes = self.figure.add_subplot( 111 )
1089 self.axes.node = weakref.ref(self)
1090
1091 master = Tkinter.Toplevel()
1092 master.title(self.name)
1093 self.canvas = FigureCanvasTkAgg(self.figure, master)
1094 self.figure.set_canvas(self.canvas)
1095
1096 packOptsDict = {'side':'top', 'fill':'both', 'expand':1}
1097 self.canvas.get_tk_widget().pack( *(), **packOptsDict )
1098 self.canvas._master.protocol('WM_DELETE_WINDOW',self.canvas._master.iconify)
1099 toolbar = NavigationToolbar2TkAgg(self.canvas, master)
1100
1102 newdrawAreaDef={}
1103 if drawAreaDef:
1104 if len(drawAreaDef)==1 and drawAreaDef[0]!=None:
1105 for d in drawAreaDef[0].keys():
1106 newdrawAreaDef[d]=drawAreaDef[0][d]
1107 elif len(drawAreaDef)>1:
1108 for dAD in drawAreaDef:
1109 if type(dAD)== types.DictType:
1110 for j in dAD.keys():
1111 newdrawAreaDef[j]=dAD[j]
1112 self.setDrawArea(newdrawAreaDef)
1113
1114 codeBeforeDisconnect ="""def beforeDisconnect(self,c):
1115 node=c.port2.node
1116 node.axes.clear()
1117 node.canvas.draw() """
1118
1119
1120
1121
1122
1123
1124
1125 -class FillNE(MPLPlottingNode):
1126 """plots filled polygons.
1127 x - list of x vertices
1128 y - list of y vertices
1129 fillcolor - color
1130 """
1131
1132 - def __init__(self, name='Fill', **kw):
1133 kw['name'] = name
1134 apply( MPLPlottingNode.__init__, (self,), kw )
1135 ip = self.inputPortsDescr
1136 ip.append(datatype='list', name='x',beforeDisconnect=self.codeBeforeDisconnect)
1137 ip.append(datatype='list',name='y',beforeDisconnect=self.codeBeforeDisconnect)
1138 ip.append(datatype='string', required=False, name='fillcolor')
1139 ip.append(datatype='MPLDrawArea', required=False,name='drawAreaDef',singleConnection=False)
1140 self.widgetDescr['fillcolor'] = {
1141 'class':'NEComboBox', 'master':'node',
1142 'choices':cnames.keys(),
1143 'fixedChoices':True,
1144 'initialValue':'white',
1145 'entryfield_entry_width':7,
1146 'labelGridCfg':{'sticky':'w'},
1147 'widgetGridCfg':{'sticky':'we'},
1148 'labelCfg':{'text':'fillcolor:'}}
1149 op = self.outputPortsDescr
1150 op.append(datatype='MPLAxes', name='axes')
1151 op.append(datatype='None', name='fig')
1152 code = """def doit(self,x,y,fillcolor='w',drawAreaDef=None):
1153 self.axes.clear()
1154 ax=self.axes
1155 p=ax.fill(x,y,fillcolor)
1156 self.setDrawAreaDef(drawAreaDef)
1157 self.canvas.draw()
1158 self.outputData(axes=self.axes,fig=p)"""
1159 self.setFunction(code)
1160
1162 """ This node plots on PolarAxes
1163 Input:
1164 y - sequence of values
1165 x - None; sequence of values
1166 Adjustable parameters:
1167 grid --grid on or off(default is on)
1168 gridcolor --color of the grid
1169 gridlinewidth --linewidth of the grid
1170 gridlinestyle --gridlinestyle
1171 xtickcolor -- color of xtick
1172 ytickcolor -- color of ytick
1173 xticksize --size of xtick
1174 yticksize --size of ytick
1175 """
1176 - def __init__(self, name='PolarAxes', **kw):
1177
1178 kw['name'] = name
1179 apply( MPLPlottingNode.__init__, (self,), kw )
1180 self.styles={}
1181 for ls in Line2D._lineStyles.keys():
1182 self.styles[Line2D._lineStyles[ls][6:]]=ls
1183 for ls in Line2D._markers.keys():
1184 self.styles[Line2D._markers[ls][6:]]=ls
1185
1186 del self.styles['steps']
1187 for s in self.styles.keys():
1188
1189 if s =="nothing":
1190 del self.styles['nothing']
1191 if s[:4]=='tick':
1192 del self.styles[s]
1193 self.colors=colors
1194 ip = self.inputPortsDescr
1195
1196
1197 ip.append(datatype='list', name='y',beforeDisconnect=self.codeBeforeDisconnect)
1198 ip.append(datatype='list', name='x',beforeDisconnect=self.codeBeforeDisconnect)
1199 ip.append(datatype='string', required=False, name='lineStyle')
1200 ip.append(datatype='None', required=False, name='color')
1201 ip.append(datatype='boolean', required=False, name='grid')
1202 ip.append(datatype='str', required=False, name='gridlineStyle')
1203 ip.append(datatype='str', required=False, name='gridcolor')
1204 ip.append(datatype='float', required=False, name='gridlinewidth')
1205 ip.append(datatype='str', required=False, name='axisbg')
1206 ip.append(datatype='str', required=False, name='xtickcolor')
1207 ip.append(datatype='str', required=False, name='ytickcolor')
1208 ip.append(datatype='float', required=False, name='xticksize')
1209 ip.append(datatype='float', required=False, name='yticksize')
1210 ip.append(datatype='MPLDrawArea', required=False,name='drawAreaDef',singleConnection=False)
1211 self.widgetDescr['grid'] = {
1212 'class':'NECheckButton', 'master':'ParamPanel',
1213 'initialValue':1, 'labelCfg':{'text':'grid'} ,
1214 'labelGridCfg':{'sticky':'w'},
1215 'widgetGridCfg':{'sticky':'w'},}
1216 self.widgetDescr['lineStyle'] = {
1217 'class':'NEComboBox', 'master':'node',
1218 'choices':self.styles.keys(),
1219 'fixedChoices':True,
1220 'initialValue':'solid',
1221 'entryfield_entry_width':7,
1222 'labelGridCfg':{'sticky':'w'},
1223 'widgetGridCfg':{'sticky':'w'},
1224 'labelCfg':{'text':'line style:'}}
1225 self.widgetDescr['color'] = {
1226 'class':'NEComboBox', 'master':'node',
1227 'choices':self.colors.keys(),
1228 'fixedChoices':True,
1229 'initialValue':'black',
1230 'entryfield_entry_width':7,
1231 'labelGridCfg':{'sticky':'w'},
1232 'widgetGridCfg':{'sticky':'we'},
1233 'labelCfg':{'text':'color:'}}
1234 self.widgetDescr['gridlineStyle'] = {
1235 'class':'NEComboBox', 'master':'ParamPanel',
1236 'choices':lineStyles.keys(),
1237 'fixedChoices':True,
1238 'initialValue':'--',
1239 'entryfield_entry_width':7,
1240 'labelGridCfg':{'sticky':'w'},
1241 'widgetGridCfg':{'sticky':'w'},
1242 'labelCfg':{'text':'gridlinestyle:'}}
1243 self.widgetDescr['gridcolor'] = {
1244 'class':'NEComboBox', 'master':'ParamPanel',
1245 'choices':cnames.keys(),
1246 'fixedChoices':True,
1247 'initialValue':'gray',
1248 'entryfield_entry_width':7,
1249 'labelGridCfg':{'sticky':'w'},
1250 'widgetGridCfg':{'sticky':'w'},
1251 'labelCfg':{'text':'gridcolor:'}}
1252 self.widgetDescr['gridlinewidth'] = {
1253 'class':'NEThumbWheel','master':'ParamPanel',
1254 'width':60, 'height':21, 'oneTurn':2, 'type':'float',
1255 'wheelPad':2, 'initialValue':1,
1256 'labelCfg':{'text':'gridlinewidth'},
1257 'labelGridCfg':{'sticky':'w'},
1258 'widgetGridCfg':{'sticky':'w'}}
1259 self.widgetDescr['axisbg'] = {
1260 'class':'NEComboBox', 'master':'ParamPanel',
1261 'choices':cnames.keys(),
1262 'fixedChoices':True,
1263 'initialValue':'white',
1264 'entryfield_entry_width':7,
1265 'labelGridCfg':{'sticky':'w'},
1266 'widgetGridCfg':{'sticky':'w'},
1267 'labelCfg':{'text':'axisbg:'}}
1268 self.widgetDescr['xtickcolor'] = {
1269 'class':'NEComboBox', 'master':'ParamPanel',
1270 'choices':cnames.keys(),
1271 'fixedChoices':True,
1272 'initialValue':'black',
1273 'entryfield_entry_width':7,
1274 'labelGridCfg':{'sticky':'w'},
1275 'widgetGridCfg':{'sticky':'w'},
1276 'labelCfg':{'text':'xtickcolor:'}}
1277 self.widgetDescr['ytickcolor'] = {
1278 'class':'NEComboBox', 'master':'ParamPanel',
1279 'choices':cnames.keys(),
1280 'fixedChoices':True,
1281 'initialValue':'black',
1282 'entryfield_entry_width':7,
1283 'labelGridCfg':{'sticky':'w'},
1284 'widgetGridCfg':{'sticky':'w'},
1285 'labelCfg':{'text':'ytickcolor:'}}
1286 self.widgetDescr['xticksize'] = {
1287 'class':'NEThumbWheel','master':'ParamPanel',
1288 'width':60, 'height':21, 'oneTurn':2, 'type':'float',
1289 'wheelPad':2, 'initialValue':12,
1290 'labelCfg':{'text':'xticksize'},'labelGridCfg':{'sticky':'w'},
1291 'widgetGridCfg':{'sticky':'w'} }
1292 self.widgetDescr['yticksize'] = {
1293 'class':'NEThumbWheel','master':'ParamPanel',
1294 'width':60, 'height':21, 'oneTurn':2, 'type':'float',
1295 'wheelPad':2, 'initialValue':12,
1296 'labelCfg':{'text':'yticksize'},'labelGridCfg':{'sticky':'w'},
1297 'widgetGridCfg':{'sticky':'w'} }
1298 op = self.outputPortsDescr
1299 op.append(datatype='MPLFigure', name='figure')
1300 code = """def doit(self, y,x,lineStyle='solid',color='black',grid=1,gridlineStyle="--",gridcolor="gray",gridlinewidth=1,axisbg="white",xtickcolor="black",ytickcolor="black",xticksize=12,yticksize=12,drawAreaDef=None):
1301
1302 self.figure.clear()
1303 self.setDrawAreaDef(drawAreaDef)
1304 if grid==1:
1305 matplotlib.rc('grid',color=gridcolor,linewidth=gridlinewidth,linestyle=gridlineStyle)
1306 matplotlib.rc('xtick',color=xtickcolor,labelsize=xticksize)
1307 matplotlib.rc('ytick',color=ytickcolor,labelsize=yticksize)
1308 colorChar = self.colors[color]
1309 lineStyleChar = self.styles[lineStyle]
1310 new_axes=self.figure.add_axes(self.axes.get_position(),polar=True,axisbg=axisbg)
1311 self.axes=new_axes
1312 self.axes.plot(x, y, colorChar+lineStyleChar)
1313 if grid!=1:
1314 new_axes.grid(grid)
1315 self.canvas.draw()
1316 self.outputData(figure=self.figure)"""
1317 self.setFunction(code)
1318
1319
1320
1321 -class StemNE(MPLPlottingNode):
1322 """A stem plot plots vertical lines (using linefmt) at each x location
1323 from the baseline to y, and places a marker there using markerfmt. A
1324 horizontal line at 0 is is plotted using basefmt
1325 input: list of x values
1326 Return value is (markerline, stemlines, baseline) .
1327 """
1328 - def __init__(self, name='Stem', **kw):
1329 kw['name'] = name
1330 apply( MPLPlottingNode.__init__, (self,),kw )
1331 ip = self.inputPortsDescr
1332 ip.append(datatype='list',required=True, name='x',beforeDisconnect=self.codeBeforeDisconnect)
1333 ip.append(datatype='list',required=True, name='y',beforeDisconnect=self.codeBeforeDisconnect)
1334 ip.append(datatype='string',required=False,name='stemlinestyle')
1335 ip.append(datatype='string',required=False,name='stemlinecolor')
1336 ip.append(datatype='string',required=False,name='markerstyle')
1337 ip.append(datatype='string',required=False,name='markerfacecolor')
1338 ip.append(datatype='string',required=False,name='baselinecolor')
1339 ip.append(datatype='string',required=False,name='baselinestyle')
1340 ip.append(datatype='MPLDrawArea', required=False,name='drawAreaDef',singleConnection=False)
1341 self.widgetDescr['stemlinestyle'] = {
1342 'class':'NEComboBox', 'master':'ParamPanel',
1343 'choices':['-.','--','-',':'],
1344 'fixedChoices':True,
1345 'initialValue':'--',
1346 'entryfield_entry_width':7,
1347 'labelGridCfg':{'sticky':'w'},
1348 'widgetGridCfg':{'sticky':'w'},
1349 'labelCfg':{'text':'stemlinestyle:'}}
1350 self.widgetDescr['stemlinecolor'] = {
1351 'class':'NEComboBox', 'master':'ParamPanel',
1352 'choices':colors.values(),
1353 'fixedChoices':True,
1354 'initialValue':'b',
1355 'entryfield_entry_width':7,
1356 'labelGridCfg':{'sticky':'w'},
1357 'widgetGridCfg':{'sticky':'w'},
1358 'labelCfg':{'text':'stemlinecolor:'}}
1359 self.widgetDescr['markerstyle'] = {
1360 'class':'NEComboBox', 'master':'ParamPanel',
1361 'choices':Line2D._markers.keys(),
1362 'fixedChoices':True,
1363 'initialValue':'o',
1364 'entryfield_entry_width':7,
1365 'labelGridCfg':{'sticky':'w'},
1366 'widgetGridCfg':{'sticky':'w'},
1367 'labelCfg':{'text':'markerstyle:'}}
1368 self.widgetDescr['markerfacecolor'] = {
1369 'class':'NEComboBox', 'master':'ParamPanel',
1370 'choices':colors.values(),
1371 'fixedChoices':True,
1372 'initialValue':'k',
1373 'entryfield_entry_width':7,
1374 'labelGridCfg':{'sticky':'w'},
1375 'widgetGridCfg':{'sticky':'w'},
1376 'labelCfg':{'text':'markerfacecolor:'}}
1377 self.widgetDescr['baselinestyle'] = {
1378 'class':'NEComboBox', 'master':'ParamPanel',
1379 'choices':['-.','--','-',':'],
1380 'fixedChoices':True,
1381 'initialValue':'-',
1382 'entryfield_entry_width':7,
1383 'labelGridCfg':{'sticky':'w'},
1384 'widgetGridCfg':{'sticky':'w'},
1385 'labelCfg':{'text':'baselinestyle:'}}
1386 self.widgetDescr['baselinecolor'] = {
1387 'class':'NEComboBox', 'master':'ParamPanel',
1388 'choices':colors.values(),
1389 'fixedChoices':True,
1390 'initialValue':'k',
1391 'entryfield_entry_width':7,
1392 'labelGridCfg':{'sticky':'w'},
1393 'widgetGridCfg':{'sticky':'w'},
1394 'labelCfg':{'text':'baselinecolor:'}}
1395
1396 op = self.outputPortsDescr
1397 op.append(datatype='MPLAxes', name='stem')
1398 code = """def doit(self,x,y,stemlinestyle='--',stemlinecolor="b",markerstyle='o',markerfacecolor='b',baselinecolor='b',baselinestyle="-",drawAreaDef=None):
1399 self.axes.clear()
1400 linefmt=stemlinecolor+stemlinestyle
1401 markerfmt=markerfacecolor+markerstyle
1402 basefmt= baselinecolor+baselinestyle
1403 markerline, stemlines, baseline = self.axes.stem(x, y, linefmt=linefmt, markerfmt=markerfmt, basefmt=basefmt )
1404 self.setDrawAreaDef(drawAreaDef)
1405 self.canvas.draw()
1406 self.outputData(stem=self.axes)"""
1407 self.setFunction(code)
1408
1410 """This node allows to plot multiple plots on same axes
1411 input: axes instances
1412 """
1413 - def __init__(self, name='MultiPlot', **kw):
1414 kw['name'] = name
1415 apply( MPLPlottingNode.__init__, (self,),kw )
1416 ip = self.inputPortsDescr
1417 ip.append(datatype='MPLAxes', required=True, name='multiplot', singleConnection=False,beforeDisconnect=self.codeBeforeDisconnect)
1418 ip.append(datatype='MPLDrawArea', required=False, name='drawAreaDef', singleConnection=False)
1419 op = self.outputPortsDescr
1420 op.append(datatype='MPLAxes', name='multiplot')
1421 code = """def doit(self, plots=None,drawAreaDef=None):
1422 self.axes.clear()
1423 ax=self.axes
1424 if len(plots)>0:
1425 ax.set_xlim(plots[0].get_xlim())
1426 ax.set_ylim(plots[0].get_ylim())
1427 for p in plots:
1428 if p.patches!=[]:
1429 for pt in p.patches:
1430 ax.add_patch(pt)
1431 elif p.lines!=[]:
1432 if p.lines!=[]:
1433 for pt in p.lines:
1434 ax.add_line(pt)
1435 elif p.collections!=[]:
1436 if p.collections!=[]:
1437 for pt in p.collections:
1438 ax.add_collection(pt)
1439 else:
1440 ax.add_artist(p)
1441 ax.autoscale_view()
1442 self.setDrawAreaDef(drawAreaDef)
1443 self.canvas.draw()
1444 self.outputData(multiplot=self.axes)"""
1445 self.setFunction(code)
1446
1448 """Adds a table to the current axes and plots bars.
1449 input:
1450 cellText - list of values
1451 rowLabels - list of labels
1452 rowColours - list of colors
1453 colLabels - list of labels
1454 colColours - list of colors
1455 location - location where the table to be placed.
1456 """
1457 - def __init__(self, name='TablePlot', **kw):
1458 """
1459 TABLE(cellText=None, cellColours=None,
1460 cellLoc='right', colWidths=None,
1461 rowLabels=None, rowColours=None, rowLoc='left',
1462 colLabels=None, colColours=None, colLoc='center',
1463 loc='bottom', bbox=None):
1464
1465 Adds a table to the current axes and plots bars.
1466 """
1467 kw['name'] = name
1468 locs=locations.keys()
1469 locs.append("bottom")
1470 apply( MPLPlottingNode.__init__, (self,), kw )
1471 ip = self.inputPortsDescr
1472 ip.append(datatype='list',required=True, name='values',singleConnection="auto",beforeDisconnect=self.codeBeforeDisconnect)
1473 ip.append(datatype='list',required=True, name='rowLabels',beforeDisconnect=self.codeBeforeDisconnect)
1474 ip.append(datatype='list',required=True, name='colLabels',beforeDisconnect=self.codeBeforeDisconnect)
1475 ip.append(datatype='list',required=False, name='rowColors')
1476 ip.append(datatype='list',required=False, name='colColors')
1477 ip.append(datatype='string',required=False, name='location')
1478 ip.append(datatype='MPLDrawArea',required=False,name='drawAreaDef',singleConnection=False)
1479 self.widgetDescr['location'] = {
1480 'class':'NEComboBox', 'master':'node',
1481 'choices':locs,
1482 'fixedChoices':True,
1483 'initialValue':'bottom',
1484 'entryfield_entry_width':7,
1485 'labelGridCfg':{'sticky':'w'},
1486 'widgetGridCfg':{'sticky':'w'},
1487 'labelCfg':{'text':'Location:'}}
1488 op = self.outputPortsDescr
1489 op.append(datatype='MPLAxes', name='plot')
1490
1491 code = """def doit(self,values,rowLabels,colLabels,rowColors=None,colColors=None,location='bottom',drawAreaDef=None):
1492 self.axes.clear()
1493 self.setDrawAreaDef(drawAreaDef)
1494 #self.axes.set_position([0.2, 0.2, 0.7, 0.6])
1495 data=[]
1496 nd=[]
1497 for val in values :
1498 for v in val:
1499 nd.append(float(v))
1500 data.append(nd)
1501 nd=[]
1502 #rcolours = get_colours(len(colLabels))
1503 rows = len(data)
1504 ind = arange(len(colLabels)) + 0.3 # the x locations for the groups
1505 cellText = []
1506 width = 0.4 # the width of the bars
1507 yoff = array([0.0] * len(colLabels)) # the bottom values for stacked bar chart
1508 for row in xrange(rows):
1509 self.axes.bar(ind, data[row], width, bottom=yoff, color=rowColors[row])
1510 yoff = yoff + data[row]
1511 cellText.append(['%1.1f' % x for x in yoff])
1512 the_table = self.axes.table(cellText=cellText,
1513 rowLabels=rowLabels,
1514 rowColours=rowColors,
1515 colColours=colColors,
1516 colLabels=colLabels,
1517 loc=location)
1518 if location=="bottom":
1519 self.axes.set_xticks([])
1520 self.axes.set_xticklabels([])
1521 self.canvas.draw()
1522 self.outputData(plot=self.axes)"""
1523 self.setFunction(code)
1524
1526 """This nodes takes a list of values and builds a histogram using matplotlib
1527 http://matplotlib.sourceforge.net/matplotlib.pylab.html#-hist
1528
1529 Compute the histogram of x. bins is either an integer number of
1530 bins or a sequence giving the bins. x are the data to be binned.
1531
1532 The return values is (n, bins, patches)
1533
1534 If normed is true, the first element of the return tuple will be the
1535 counts normalized to form a probability distribtion, ie,
1536 n/(len(x)*dbin)
1537
1538 Addition kwargs: hold = [True|False] overrides default hold state
1539
1540 Input:
1541 values: sequence of values
1542 bins=10: number of dequence giving the gins
1543 normed=0 normalize
1544
1545 Output:
1546 plot Matplotlib Axes object
1547 """
1548 - def __init__(self, name='Histogram', **kw):
1549 kw['name'] = name
1550
1551 apply( MPLPlottingNode.__init__, (self,), kw )
1552 self.colors=cnames
1553 ip = self.inputPortsDescr
1554 ip.append(datatype='None', name='values',beforeDisconnect=self.codeBeforeDisconnect)
1555 ip.append(datatype='None', required=False, name='bins')
1556 ip.append(datatype='boolean', required=False, name='normed')
1557 ip.append(datatype='float', required=False, name='patch_antialiased')
1558 ip.append(datatype='float', required=False, name='patch_linewidth')
1559 ip.append(datatype='string', required=False, name='patch_edgecolor')
1560 ip.append(datatype='string', required=False, name='patch_facecolor')
1561 ip.append(datatype='MPLDrawArea',required=False,name='drawAreaDef',singleConnection=False)
1562 self.widgetDescr['bins'] = {
1563 'class':'NEThumbWheel','master':'node',
1564 'width':75, 'height':21, 'oneTurn':10, 'type':'int', 'wheelPad':2,
1565 'initialValue':10,
1566 'labelCfg':{'text':'# of bins'} }
1567
1568 self.widgetDescr['normed'] = {
1569 'class':'NECheckButton', 'master':'node',
1570 'initialValue':1, 'labelCfg':{'text':'normalize'},
1571 }
1572 self.widgetDescr['patch_linewidth'] = {
1573 'class':'NEThumbWheel','master':'ParamPanel',
1574 'width':60, 'height':21, 'oneTurn':2, 'type':'int',
1575 'wheelPad':2, 'initialValue':1,
1576 'labelCfg':{'text':'linewidth'} }
1577 self.widgetDescr['patch_antialiased'] = {
1578 'class':'NECheckButton', 'master':'ParamPanel',
1579 'labelCfg':{'text':'antialiased:'},
1580 'initialValue':1,}
1581 self.widgetDescr['patch_edgecolor'] = {
1582 'class':'NEComboBox', 'master':'ParamPanel',
1583 'choices':self.colors.keys(),
1584 'fixedChoices':True,
1585 'initialValue':'black',
1586 'entryfield_entry_width':7,
1587 'labelGridCfg':{'sticky':'w'},
1588 'widgetGridCfg':{'sticky':'w'},
1589 'labelCfg':{'text':'edgecolor:'}}
1590 self.widgetDescr['patch_facecolor'] = {
1591 'class':'NEComboBox', 'master':'ParamPanel',
1592 'choices':self.colors.keys(),
1593 'fixedChoices':True,
1594 'initialValue':'blue',
1595 'entryfield_entry_width':7,
1596 'labelGridCfg':{'sticky':'w'},
1597 'widgetGridCfg':{'sticky':'w'},
1598 'labelCfg':{'text':'facecolor:'}}
1599 op = self.outputPortsDescr
1600 op.append(datatype='MPLAxes', name='plot')
1601
1602 code = """def doit(self, values, bins=10, normed=False,patch_antialiased=1,patch_linewidth=1,patch_edgecolor='black',patch_facecolor='blue',drawAreaDef=None):
1603 self.axes.clear()
1604 self.setDrawAreaDef(drawAreaDef)
1605 n, bins, patches = self.axes.hist(values, bins, normed)
1606 if self.axes.patches:
1607 for p in self.axes.patches:
1608 p.set_linewidth(patch_linewidth)
1609 p.set_edgecolor(patch_edgecolor)
1610 p.set_facecolor(patch_facecolor)
1611 p.set_antialiased(patch_antialiased)
1612 self.canvas.draw()
1613 self.outputData(plot=self.axes)
1614 """
1615 self.setFunction(code)
1616
1617
1618
1619 -class PlotNE(MPLPlottingNode):
1620 """This nodes takes two lists of values and plots the the second against the first.
1621
1622 Input:
1623 y - sequence of values
1624 x - None; sequence of values
1625 figure - None; MPLFigure object object into which to place the drawing
1626
1627 Output:
1628 plot Matplotlib Axes object
1629 line: - line
1630 """
1631
1632 - def __init__(self, name='Plot', **kw):
1633 kw['name'] = name
1634 apply( MPLPlottingNode.__init__, (self,), kw )
1635 self.styles=get_styles()
1636 self.colors=colors
1637 self.joinstyles = Line2D.validJoin
1638 self.capstyles = Line2D.validCap
1639 ip = self.inputPortsDescr
1640 ip.append(datatype='list', name='y',beforeDisconnect=self.codeBeforeDisconnect)
1641 ip.append(datatype='list', required=False, name='x')
1642 ip.append(datatype='string', required=False, name='lineStyle')
1643 ip.append(datatype='None', required=False, name='color')
1644 ip.append(datatype='boolean', required=False, name='line_antialiased')
1645 ip.append(datatype='float', required=False, name='line_linewidth')
1646 ip.append(datatype='string', required=False, name='solid_joinstyle')
1647 ip.append(datatype='string', required=False, name='solid_capstyle')
1648 ip.append(datatype='string', required=False, name='dash_capstyle')
1649 ip.append(datatype='string', required=False, name='dash_joinstyle')
1650 ip.append(datatype='MPLDrawArea', required=False,name='drawAreaDef',singleConnection=False)
1651
1652 self.widgetDescr['lineStyle'] = {
1653 'class':'NEComboBox', 'master':'node',
1654 'choices':self.styles.keys(),
1655 'fixedChoices':True,
1656 'initialValue':'solid',
1657 'entryfield_entry_width':7,
1658 'labelGridCfg':{'sticky':'w'},
1659 'widgetGridCfg':{'sticky':'w'},
1660 'labelCfg':{'text':'line style:'}}
1661
1662 self.widgetDescr['color'] = {
1663 'class':'NEComboBox', 'master':'node',
1664 'choices':self.colors.keys(),
1665 'fixedChoices':True,
1666 'initialValue':'black',
1667 'entryfield_entry_width':7,
1668 'labelGridCfg':{'sticky':'w'},
1669 'widgetGridCfg':{'sticky':'we'},
1670 'labelCfg':{'text':'color:'}}
1671
1672 self.widgetDescr['dash_capstyle'] = {
1673 'class':'NEComboBox', 'master':'ParamPanel',
1674 'choices':self.capstyles,
1675 'fixedChoices':True,
1676 'initialValue':'butt',
1677 'entryfield_entry_width':7,
1678 'labelGridCfg':{'sticky':'w'},
1679 'widgetGridCfg':{'sticky':'w'},
1680 'labelCfg':{'text':'dash_capstyle:'}}
1681 self.widgetDescr['dash_joinstyle'] = {
1682 'class':'NEComboBox', 'master':'ParamPanel',
1683 'choices':self.joinstyles,
1684 'fixedChoices':True,
1685 'initialValue':'miter',
1686 'entryfield_entry_width':7,
1687 'labelGridCfg':{'sticky':'w'},
1688 'widgetGridCfg':{'sticky':'w'},
1689 'labelCfg':{'text':'dash _joinstyle:'}}
1690 self.widgetDescr['solid_capstyle'] = {
1691 'class':'NEComboBox', 'master':'ParamPanel',
1692 'choices':self.capstyles,
1693 'fixedChoices':True,
1694 'initialValue':'projecting',
1695 'entryfield_entry_width':7,
1696 'labelGridCfg':{'sticky':'w'},
1697 'widgetGridCfg':{'sticky':'w'},
1698 'labelCfg':{'text':'solid_capstyle:'}}
1699 self.widgetDescr['solid_joinstyle'] = {
1700 'class':'NEComboBox', 'master':'ParamPanel',
1701 'choices':self.joinstyles,
1702 'fixedChoices':True,
1703 'initialValue':'miter',
1704 'entryfield_entry_width':7,
1705 'labelGridCfg':{'sticky':'w'},
1706 'widgetGridCfg':{'sticky':'w'},
1707 'labelCfg':{'text':'solid_joinstyle:'}}
1708 self.widgetDescr['line_linewidth'] = {
1709 'class':'NEThumbWheel','master':'ParamPanel',
1710 'width':60, 'height':21, 'oneTurn':2, 'type':'int',
1711 'wheelPad':2, 'initialValue':1,
1712 'labelCfg':{'text':'linewidth'} }
1713
1714 self.widgetDescr['line_antialiased'] = {
1715 'class':'NECheckButton', 'master':'ParamPanel',
1716 'labelCfg':{'text':'antialiased:'},
1717 'initialValue':1,}
1718 op = self.outputPortsDescr
1719 op.append(datatype='MPLAxes', name='plot')
1720
1721 code = """def doit(self, y, x=None, lineStyle='solid',color='black',line_antialiased=1,line_linewidth=1,solid_joinstyle='miter',solid_capstyle='projecting',dash_capstyle='butt',dash_joinstyle='miter',drawAreaDef=None):
1722 self.axes.clear()
1723 self.setDrawAreaDef(drawAreaDef)
1724 colorChar = self.colors[color]
1725 lineStyleChar = self.styles[lineStyle]
1726 if x is None:
1727 l = self.axes.plot(y, colorChar+lineStyleChar)
1728 else:
1729 l = self.axes.plot(x, y, colorChar+lineStyleChar)
1730 #line properties
1731 if self.axes.lines:
1732 for l in self.axes.lines:
1733 l.set_linewidth(line_linewidth)
1734 l.set_antialiased(line_antialiased)
1735 l.set_solid_joinstyle(solid_joinstyle)
1736 l.set_solid_capstyle(solid_capstyle)
1737 l.set_dash_capstyle(dash_capstyle)
1738 l.set_dash_joinstyle(dash_joinstyle)
1739
1740 self.canvas.draw()
1741 self.outputData(plot=self.axes)
1742 """
1743 self.setFunction(code)
1744
1746 """This nodes takes two lists of values and plots the the second against the first.
1747
1748 Input:
1749 y - sequence of dates
1750 x - sequence of dates
1751 optional arguements:
1752 lineStyle - line style
1753 color - color of the line
1754 (lineStyle+colorchar --fmt)
1755 tz - timezone
1756 xdate - is True, the x-axis will be labeled with dates
1757 ydate - is True, the y-axis will be labeled with dates
1758 Output:
1759 plot Matplotlib Axes object
1760 line: - line
1761 pytz is required.
1762 checks for pytz module and returns if not
1763 """
1764 - def __init__(self, name='PlotDate', **kw):
1765 kw['name'] = name
1766 apply( MPLPlottingNode.__init__, (self,), kw )
1767 self.styles=get_styles()
1768 self.colors=colors
1769 self.joinstyles = Line2D.validJoin
1770 timezones=common_timezones
1771 self.capstyles = Line2D.validCap
1772 ip = self.inputPortsDescr
1773 ip.append(datatype='list', name='y',beforeDisconnect=self.codeBeforeDisconnect)
1774 ip.append(datatype='list', name='x',beforeDisconnect=self.codeBeforeDisconnect)
1775 ip.append(datatype='string', required=False, name='lineStyle')
1776 ip.append(datatype='None', required=False, name='color')
1777 ip.append(datatype='string', required=False, name='tz')
1778 ip.append(datatype='boolean', required=False, name='xdate')
1779 ip.append(datatype='boolean', required=False, name='ydate')
1780 ip.append(datatype='boolean', required=False, name='line_antialiased')
1781 ip.append(datatype='float', required=False, name='line_linewidth')
1782 ip.append(datatype='string', required=False, name='solid_joinstyle')
1783 ip.append(datatype='string', required=False, name='solid_capstyle')
1784 ip.append(datatype='string', required=False, name='dash_capstyle')
1785 ip.append(datatype='string', required=False, name='dash_joinstyle')
1786 ip.append(datatype='MPLDrawArea', required=False,name='drawAreaDef',singleConnection=False)
1787
1788 self.widgetDescr['lineStyle'] = {
1789 'class':'NEComboBox', 'master':'node',
1790 'choices':self.styles.keys(),
1791 'fixedChoices':True,
1792 'initialValue':'circle',
1793 'entryfield_entry_width':7,
1794 'labelGridCfg':{'sticky':'w'},
1795 'widgetGridCfg':{'sticky':'w'},
1796 'labelCfg':{'text':'line style:'}}
1797
1798 self.widgetDescr['color'] = {
1799 'class':'NEComboBox', 'master':'node',
1800 'choices':self.colors.keys(),
1801 'fixedChoices':True,
1802 'initialValue':'blue',
1803 'entryfield_entry_width':7,
1804 'labelGridCfg':{'sticky':'w'},
1805 'widgetGridCfg':{'sticky':'we'},
1806 'labelCfg':{'text':'color:'}}
1807
1808 self.widgetDescr['tz'] = {
1809 'class':'NEComboBox', 'master':'node',
1810 'choices':timezones,
1811 'fixedChoices':True,
1812 'initialValue':'US/PACIFIC',
1813 'entryfield_entry_width':7,
1814 'labelGridCfg':{'sticky':'w'},
1815 'widgetGridCfg':{'sticky':'w'},
1816 'labelCfg':{'text':'timezone:'}}
1817
1818 self.widgetDescr['xdate'] = {
1819 'class':'NECheckButton', 'master':'ParamPanel',
1820 'labelCfg':{'text':'xdate:'},
1821 'initialValue':1,}
1822
1823 self.widgetDescr['ydate'] = {
1824 'class':'NECheckButton', 'master':'ParamPanel',
1825 'labelCfg':{'text':'ydate:'},
1826 'initialValue':0,}
1827
1828 self.widgetDescr['dash_capstyle'] = {
1829 'class':'NEComboBox', 'master':'ParamPanel',
1830 'choices':self.capstyles,
1831 'fixedChoices':True,
1832 'initialValue':'butt',
1833 'entryfield_entry_width':7,
1834 'labelGridCfg':{'sticky':'w'},
1835 'widgetGridCfg':{'sticky':'w'},
1836 'labelCfg':{'text':'dash_capstyle:'}}
1837 self.widgetDescr['dash_joinstyle'] = {
1838 'class':'NEComboBox', 'master':'ParamPanel',
1839 'choices':self.joinstyles,
1840 'fixedChoices':True,
1841 'initialValue':'miter',
1842 'entryfield_entry_width':7,
1843 'labelGridCfg':{'sticky':'w'},
1844 'widgetGridCfg':{'sticky':'w'},
1845 'labelCfg':{'text':'dash _joinstyle:'}}
1846 self.widgetDescr['solid_capstyle'] = {
1847 'class':'NEComboBox', 'master':'ParamPanel',
1848 'choices':self.capstyles,
1849 'fixedChoices':True,
1850 'initialValue':'projecting',
1851 'entryfield_entry_width':7,
1852 'labelGridCfg':{'sticky':'w'},
1853 'widgetGridCfg':{'sticky':'w'},
1854 'labelCfg':{'text':'solid_capstyle:'}}
1855 self.widgetDescr['solid_joinstyle'] = {
1856 'class':'NEComboBox', 'master':'ParamPanel',
1857 'choices':self.joinstyles,
1858 'fixedChoices':True,
1859 'initialValue':'miter',
1860 'entryfield_entry_width':7,
1861 'labelGridCfg':{'sticky':'w'},
1862 'widgetGridCfg':{'sticky':'w'},
1863 'labelCfg':{'text':'solid_joinstyle:'}}
1864 self.widgetDescr['line_linewidth'] = {
1865 'class':'NEThumbWheel','master':'ParamPanel',
1866 'width':60, 'height':21, 'oneTurn':2, 'type':'int',
1867 'wheelPad':2, 'initialValue':1,
1868 'labelCfg':{'text':'linewidth'} }
1869
1870 self.widgetDescr['line_antialiased'] = {
1871 'class':'NECheckButton', 'master':'ParamPanel',
1872 'labelCfg':{'text':'antialiased:'},
1873 'initialValue':1,}
1874 op = self.outputPortsDescr
1875 op.append(datatype='MPLAxes', name='plot')
1876
1877 code = """def doit(self, y, x=None, lineStyle='solid',color='black',tz='US/PACIFIC',xdate=True,ydate=False,line_antialiased=1,line_linewidth=1,solid_joinstyle='miter',solid_capstyle='projecting',dash_capstyle='butt',dash_joinstyle='miter',drawAreaDef=None):
1878 try:
1879 from pytz import common_timezones
1880 except:
1881 print "Could not import pytz "
1882 return
1883 self.axes.clear()
1884 self.setDrawAreaDef(drawAreaDef)
1885 colorChar = self.colors[color]
1886 lineStyleChar = self.styles[lineStyle]
1887 rcParams['timezone'] = tz
1888 tz=timezone(tz)
1889 fmt= colorChar+lineStyleChar
1890 l = self.axes.plot_date(x, y, fmt=colorChar+lineStyleChar, tz=tz, xdate= xdate,ydate= ydate)
1891 #line properties
1892 if self.axes.lines:
1893 for l in self.axes.lines:
1894 l.set_linewidth(line_linewidth)
1895 l.set_antialiased(line_antialiased)
1896 l.set_solid_joinstyle(solid_joinstyle)
1897 l.set_solid_capstyle(solid_capstyle)
1898 l.set_dash_capstyle(dash_capstyle)
1899 l.set_dash_joinstyle(dash_joinstyle)
1900
1901 self.canvas.draw()
1902 self.outputData(plot=self.axes)
1903 """
1904 self.setFunction(code)
1905
1906 -class PieNE(MPLPlottingNode):
1907 """plots a pie diagram for a list of numbers. The size of each wedge
1908 will be the fraction x/sumnumbers).
1909
1910 Input:
1911 fractions - sequence of values
1912 labels - None; sequence of labels (has to match length of factions
1913 explode - None; float or sequence of values which specifies the
1914 fraction of the radius to offset that wedge.
1915 if a single float is given the list is generated automatically
1916 shadow - True; if True, will draw a shadow beneath the pie.
1917 format - None; fromat string used to label the wedges with their
1918 numeric value
1919 Output:
1920 plot - Matplotlib Axes object
1921 patches - sequence of matplotlib.patches.Wedge
1922 texts - list of the label Text instances
1923 autotextsline - list of text instances for the numeric labels (only if
1924 format is not None
1925 """
1926