def matplotCanvas(self): f = Figure(figsize=(5, 5), dpi=100) a = f.add_subplot(111) a.plot([1, 2, 3, 4, 5, 6, 7, 8], [5, 6, 1, 3, 8, 9, 3, 5]) canvas = FigureCanvasAgg(f, self) canvas.show() canvas.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=True)
class PlotWrap(object): __debug = False __keyArgDict = { 'title' : None, 'winTitle' : None, 'xlabel' : None, 'xticks' : None, 'ylabel' : None, 'yticks' : None, 'ylog' : False, 'xlog' : False, 'ybound' : (None,None), 'xbound' : (None,None), 'legend' : None, 'style' : None, 'aging' : None, 'alphaMin' : 0.02, 'agingCull' : True, 'bball' : None, 'accum' : False, 'showByDefault' : True, 'makeWinByDefault': True, 'axes' : None, 'axesRect' : None, 'axprops' : {}, 'figsize' : (5,4), 'dpi' : 100, 'window' : None, 'as3D' : False, } def __init__(self, **keyArgs ): # defaults for parm, val in self.__keyArgDict.iteritems(): self.__setattr__(parm, val) # # parse keyword args for keyArg in self.getKeyArgList(): if keyArgs.has_key(keyArg): self.__setattr__(keyArg, keyArgs.pop(keyArg)) if len(keyArgs) > 0: raise RuntimeError, 'unparsed keyword args : '+str(keyArgs) # window = self.window del self.window # self.x_accum = self.accum del self.accum # axes = self.axes del self.axes self.x_prev = None self.x_store = [[],[]] self.win = None self.a = None self.canvas = None self.ownCanvas = True if window is None: self.ownCanvas = True 'checking self.showByDefault here causes trouble because it is hard to attach a figure to a window later for a general backend ***' if self.showByDefault or self.makeWinByDefault: # 'go ahead and make a window, using PlotWinP to increase backend flexibility' # self.win = ...PlotWinP(as3D=self.as3D, figsize=self.figsize, dpi=self.dpi) # self.a = self.win.getAxes(0) # self.f = self.win.getFigure() # self.canvas = self.win.getCanvas() # self.a.set_autoscale_on(True) self.__checkWin() self.f = self.win.f else: from matplotlib.figure import Figure self.f = Figure(figsize=self.figsize, dpi=self.dpi) if self.as3D: import mpl_toolkits.mplot3d.axes3d as p3 self.a = p3.Axes3D(self.f) else: if self.axesRect is None: self.a = self.f.add_subplot(1, 1, 1, **self.axprops) else: self.a = self.f.add_axes(self.axesRect, **self.axprops) if axes is not None: raise RuntimeError, 'do not specify axes when have not passed a window' else: self.ownCanvas = False self.win = window self.canvas = self.win.getCanvas() self.f = self.win.getFigure() if axes is None: if self.__debug: print 'using axprops: '+str(self.axprops) self.a = self.win.getNextAxes(rect=self.axesRect, attachPW=self, **self.axprops) elif isinstance(axes, int): self.a = self.win.getAxes(axes, **self.axprops) else: self.a = axes # self.clear() # sets labels and so forth # self.style = style # can be None # self.bball = bball # can be None # #self.aging = aging #self.agingCull = agingCull #self.alphaMin = alphaMin self.agingNumAge = -1 if self.aging is not None: from math import log self.agingNumAge = max(int(log(self.alphaMin)/log(self.aging)),1) self.plotProps = {} # self.lineListList = [] # not needed, can, and should, use a.lines self.asImIJ = False # self.transform = None self.axIm = None self.__colorbar = None return def add_axes(self, arect, kwAddAxes={}, **kwarg): aNew = self.f.add_axes(arect, **kwAddAxes) # self.a.set_position((0.05, 0.05, 0.45, 0.9)) new = self.__class__(window=self.win, axes=aNew, **kwarg) return new @classmethod def popKeyArgs(cls, kwargs): retval = {} for key in cls.getKeyArgList(): if kwargs.has_key(key): retval[key] = kwargs.pop(key) return retval @classmethod def getKeyArgList(cls): return cls.__keyArgDict.keys() def __checkCanvas(self): 'leave dead True, not checking for window, just for canvas' #from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg if self.win is not None: return if self.canvas is not None: return from matplotlib.backends.backend_tkagg import FigureCanvasAgg self.canvas = FigureCanvasAgg(self.f) if hasattr(self.a,'mouse_init'): self.a.mouse_init() return def __checkWin(self): if self.win is not None: return winTitle = self.winTitle if winTitle is None : winTitle = self.title if winTitle is None : winTitle = 'plotWin' if hasattr(self,'f'): self.win = PlotWin(1,1,title=winTitle, relfigsize=self.figsize, figure=self.f, axesList=[self.a]) else: self.win = PlotWin(1,1,title=winTitle, relfigsize=self.figsize, axesList=[self.a]) #self.win = PlotWinP(title=winTitle, figure=self.f, axes=self.a) self.canvas = self.win.getCanvas() return def removeLines(self): lines = self.a.get_lines() for line in lines: line.remove() if self.showByDefault: self.show() # self.canvas.show() return def show(self): self.__checkWin() if self.legend is not None: pass # do not yet have this right # if isinstance(self.legend, str) or isinstance(self.legend, int): # or hasattr(self.legend,'__len__') # self.a.legend(loc=self.legend) # elif isinstance(self.legend, bool): # self.a.legend() # elif isinstance(self.legend, list): # self.a.legend(*self.legend) # elif isinstance(self.legend, dict): # self.a.legend(**self.legend) # else: # raise RuntimeError, 'do not know what to do with legend specification: '+str(self.legend) if hasattr(self.a,'mouse_init'): self.a.mouse_init() if hasattr(self.f, 'show'): self.f.show() elif hasattr(self.canvas, 'show'): self.canvas.show() else: raise RuntimeError, 'do not know how to do show' return def clear(self): self.asImIJ = False self.axIm = None # self.transform = None self.x_prev = None self.__colorbar = None self.x_store = [[],[]] if self.showByDefault: self.__checkWin() if self.a is not None: if hasattr(self.a,'mouse_init'): 'doing a.clear() seems like it causes trouble with plotting collections?' self.a.clear() # self.a.cla() self.a.set_autoscale_on(True) else: self.a.clear() # self.a.cla() self.a.set_autoscale_on(True) if self.xticks is not None: self.a.set_xticks(self.xticks) if self.title is not None: self.a.set_title(self.title) if self.xlabel is not None: self.a.set_xlabel(self.xlabel) # r'X axis label $\mu\mbox{lentz}$' if self.win is not None: 'make some room for the label' self.win.haveXLabels() if self.yticks is not None: self.a.set_yticks(self.yticks) if self.xlog: self.a.set_xscale('log') if self.ylog: self.a.set_yscale('log') #self.a.set_ybound(self.ybound) self.a.set_ylim(ymin=self.ybound[0], ymax=self.ybound[1]) self.a.set_xlim(xmin=self.xbound[0], xmax=self.xbound[1]) if self.ylabel is not None: self.a.set_ylabel(self.ylabel) if self.win is not None: 'make some room for the label' self.win.haveYLabels() if self.legend is not None: pass # do not yet have this right # if isinstance(self.legend, str) or isinstance(self.legend, int): # or hasattr(self.legend,'__len__') # self.a.legend(loc=self.legend) # elif isinstance(self.legend, bool): # self.a.legend() # elif isinstance(self.legend, list): # self.a.legend(*self.legend) # elif isinstance(self.legend, dict): # self.a.legend(**self.legend) # else: # raise RuntimeError, 'do not know what to do with legend specification: '+str(self.legend) if self.a is not None: self.a.set_autoscale_on(True) if self.showByDefault: self.show() # self.canvas.show() return def setLegend(self, val=True): # if self.legend is None: # self.legend = True # if val is not None: # self.legend = val self.legend = val return def save(self, **keyArgs): '''make hardcopy of the current figure; specify filename or prefix keyword argument ''' import numpy as num filename = None prefix = None if keyArgs.has_key('filename'): filename = keyArgs.pop('filename') if keyArgs.has_key('prefix'): prefix = keyArgs.pop('prefix') filename = prefix+'.pdf' # .eps if prefix is not None: 'export data' if len(self.x_store[0]) > 0: dataFilename = prefix+'.data' from hexrd import arrayUtil try: arrayUtil.writeArray(dataFilename, num.array(self.x_store)) except: import sys print 'problem writing to '+dataFilename+' : '+str(self.x_store) sys.exit(1) if not self.ownCanvas: if self.__debug: print 'skipping print_figure because this plot does not own its canvas' else: self.__checkCanvas() if filename is None: raise RuntimeError, 'need filename or prefix entry in keyArgs' #self.canvas.print_figure(filename, **keyArgs) self.f.savefig(filename, **keyArgs) return def destroy(self): 'does not clean up self.a, just kills the window if this plot owns the window' if self.ownCanvas and self.win is not None: self.win.destroy() return def drawBBox(self, bbox, **kwargs): import numpy as num bbox_x = bbox[0] bbox_y = bbox[1] xBBox = num.array([ bbox_x[0], bbox_x[1], bbox_x[1], bbox_x[0], bbox_x[0] ]) yBBox = num.array([ bbox_y[0], bbox_y[0], bbox_y[1], bbox_y[1], bbox_y[0] ]) 'go through call, instead of callXY, in case of asImIJ' self.__call__(xBBox, yBBox, **kwargs) return def __call__(self, *args, **keyArgs): import numpy as num noShow = False retVal = None # if keyArgs.has_key('transform'): # 'pop transform so that can keep it for other (overlaid) plots' # self.transform = keyArgs.pop('transform') if keyArgs.has_key('noShow'): noShow = keyArgs.pop('noShow') if len(args) == 2: alphas = None if self.asImIJ: x = args[1] y = args[0] else: x = args[0] y = args[1] if keyArgs.has_key('alphas'): alphas = keyArgs.pop('alphas') assert len(args) == 2, 'len(args) != 2' assert len(alphas) == len(y), 'len(alphas) != len(y)' self.x_prev = None for iX in range(len(x)): self.callXY([x[iX]],[y[iX]],alpha=alphas[iX],**keyArgs) else: self.callXY(x, y, **keyArgs) elif len(args) == 3: X = args[0]; Y = args[1]; data = args[2]; cont = self.callContour(X, Y, data, **keyArgs) retVal = cont elif len(args) == 1 and isinstance(args[0],str): 'interpret string as name of a file to plot in axes' filename = args[0] im = self.callImage(filename, **keyArgs) retVal = im elif len(args) == 1 and isinstance(args[0],num.ndarray): im = self.callIm(args[0], **keyArgs) retVal = im else: raise RuntimeError, 'do not know what to do with args' self.a.set_ylim(ymin=self.ybound[0], ymax=self.ybound[1]) self.a.set_xlim(xmin=self.xbound[0], xmax=self.xbound[1]) if not noShow: if self.showByDefault: self.show() return retVal def callImage(self, filename, **keyArgs): import Image im = Image.open(filename) s = im.tostring() # convert PIL image -> string import numpy as num rgb = num.fromstring(s, dtype=num.uint8).astype(num.float)/255.0 # convert string -> array of floats rgb = num.resize(rgb, (im.size[1], im.size[0], 3)) # resize to RGB array retval = self.callIm(rgb, **keyArgs) return retval def callIm(self, im, interpolation='nearest', aspect='equal', ijAsXY=False, clear=True, **keyArgs): if clear: self.clear() self.a.axis('off') self.a.set_autoscale_on(True) if ijAsXY: self.asImIJ = False 'imshow does not yet really support transform' if len(im.shape) == 3: imT = im.transpose(1,0,2) else: imT = im.T axIm = self.a.imshow(imT, interpolation=interpolation, aspect=aspect, origin='lower', # transform=self.transform, **keyArgs) self.a.format_coord = lambda x,y: 'i=%d; j=%d; val=%s' % \ (round(x), round(y), str(im[round(x),round(y)])) else: self.asImIJ = True 'imshow does not yet really support transform' axIm = self.a.imshow(im, interpolation=interpolation, aspect=aspect, # transform=self.transform, **keyArgs) self.a.format_coord = lambda x,y: 'i=%d; j=%d; val=%s' % \ (round(y), round(x), str(im[round(y),round(x)])) 'turn off autoscale so that axis limits do not get reset on replots' self.axIm = axIm self.mappable = axIm self.a.set_autoscale_on(False) return axIm def callContour(self, X, Y, data, interpolation=None, aspect=None, **keyArgs): pp = {} pp.update(self.plotProps) pp.update(keyArgs) # plotProps #cont = self.a.contourf(X, Y, data, 200, **keyArgs) 'imshow does not yet really support transform' self.a.set_autoscale_on(True) cont = self.a.imshow(data, origin='lower', extent=(X[0,0],X[0,-1],Y[0,0],Y[-1,0]), interpolation=interpolation, aspect=aspect, # transform=self.transform, **keyArgs) self.a.set_autoscale_on(False) self.mappable = cont return cont def discontXY(self): self.x_prev = None return def callXY(self, x, y, style=None, **keyArgs): assert len(x) == len(y), \ 'x and y must be same length' xUse = x yUse = y if len(x) == 1: if self.x_prev is not None: xUse = []; xUse.append(self.x_prev[0]); xUse.append(x) yUse = []; yUse.append(self.x_prev[1]); yUse.append(y) pp = {} pp.update(self.plotProps) pp.update(keyArgs) # plotProps if self.bball is not None: 'first, get rid of last bball' lenCur = len(self.a.lines) if lenCur>0: self.a.lines = self.a.lines[0:lenCur-1] if self.aging is not None: #for lineList in self.lineListList[:-1]: # for line in lineList: lenCur = len(self.a.lines) for line in self.a.lines[max(0,lenCur-self.agingNumAge):lenCur]: alphaCur = line.get_alpha() line.set_alpha(alphaCur*self.aging) if self.agingCull: if lenCur > self.agingNumAge: self.a.lines = self.a.lines[lenCur-self.agingNumAge:lenCur] if style is not None: 'passing transform of None can cause trouble' lines = self.a.plot(xUse, yUse, style, # transform=self.transform, **pp) elif self.style is not None: #self.lineListList.append(self.a.plot(x,y,self.style,**pp)) lines = self.a.plot(xUse, yUse, self.style, # transform=self.transform, **pp) else: #self.lineListList.append(self.a.plot(x,y,**pp)) lines = self.a.plot(xUse, yUse, # transform=self.transform, **pp) if self.bball is not None: 'add bball at end' self.a.plot([x[-1]],[y[-1]], self.bball) # transform=self.transform if len(x) == 1: if self.x_accum: self.x_prev = [x, y] self.x_store[0] = self.x_store[0] + list(x) self.x_store[1] = self.x_store[1] + list(y) else: self.x_prev = None if len(x) == len(self.x_store[0]): 'assume called with the same x values' self.x_store.append(list(y)) else: self.x_store[0] = list(x) self.x_store[1] = list(y) return def setVMM(self, vMM): if type(vMM) == int: iCol = vMM vMM = self.a.collections[iCol].get_clim() for col in self.a.collections: col.set_clim(vmin=vMM[0],vmax=vMM[1]) return def colorbar(self, rect=(0.80,0.1,0.05,0.8), adjustPos=True, thing=None, **kwargs): ''' if set rect to None, then colorbar steals self.a ''' self.__checkWin() w = self.win f = self.f if len(self.a.collections) > 0: self.setVMM(0) if thing is None: if len(self.a.collections) > 0: thing = self.a.collections[0] elif hasattr(self, 'mappable'): thing = self.mappable else: raise RuntimeError, 'do not know what to colobar, pass in a thing' if rect is None: self.__colorbar = f.colorbar(thing, ax=self.a) else: cax = w.getNextAxes(rect=rect) self.__colorbar = f.colorbar(thing, cax=cax) if adjustPos: 'adjust existing position to make room for colorbar' bbox = self.a.get_position().get_points() arect = (bbox[0,0], # left bbox[0,1], # bottom rect[0]-bbox[0,0]-0.02, # width bbox[1,1]-bbox[0,1], # height ) self.a.set_position(arect) self.show() return
class PlotWrap(object): __debug = False __keyArgDict = { 'title' : None, 'winTitle' : None, 'xlabel' : None, 'xticks' : None, 'ylabel' : None, 'yticks' : None, 'ylog' : False, 'xlog' : False, 'ybound' : (None,None), 'xbound' : (None,None), 'legend' : None, 'style' : None, 'aging' : None, 'alphaMin' : 0.02, 'agingCull' : True, 'bball' : None, 'accum' : False, 'showByDefault' : True, 'makeWinByDefault': True, 'axes' : None, 'axesRect' : None, 'axprops' : {}, 'figsize' : (5,4), 'dpi' : 100, 'window' : None, 'as3D' : False, } def __init__(self, **keyArgs ): # defaults for parm, val in self.__keyArgDict.iteritems(): self.__setattr__(parm, val) # # parse keyword args for keyArg in self.getKeyArgList(): if keyArgs.has_key(keyArg): self.__setattr__(keyArg, keyArgs.pop(keyArg)) if len(keyArgs) > 0: raise RuntimeError, 'unparsed keyword args : '+str(keyArgs) # window = self.window del self.window # self.x_accum = self.accum del self.accum # axes = self.axes del self.axes self.x_prev = None self.x_store = [[],[]] self.win = None self.a = None self.canvas = None self.ownCanvas = True if window is None: self.ownCanvas = True 'checking self.showByDefault here causes trouble because it is hard to attach a figure to a window later for a general backend ***' if self.showByDefault or self.makeWinByDefault: # 'go ahead and make a window, using PlotWinP to increase backend flexibility' # self.win = ...PlotWinP(as3D=self.as3D, figsize=self.figsize, dpi=self.dpi) # self.a = self.win.getAxes(0) # self.f = self.win.getFigure() # self.canvas = self.win.getCanvas() # self.a.set_autoscale_on(True) self.__checkWin() self.f = self.win.f else: from matplotlib.figure import Figure self.f = Figure(figsize=self.figsize, dpi=self.dpi) if self.as3D: import mpl_toolkits.mplot3d.axes3d as p3 self.a = p3.Axes3D(self.f) else: if self.axesRect is None: self.a = self.f.add_subplot(1, 1, 1, **self.axprops) else: self.a = self.f.add_axes(self.axesRect, **self.axprops) if axes is not None: raise RuntimeError, 'do not specify axes when have not passed a window' else: self.ownCanvas = False self.win = window self.canvas = self.win.getCanvas() self.f = self.win.getFigure() if axes is None: if self.__debug: print 'using axprops: '+str(self.axprops) self.a = self.win.getNextAxes(rect=self.axesRect, attachPW=self, **self.axprops) elif isinstance(axes, int): self.a = self.win.getAxes(axes, **self.axprops) else: self.a = axes # self.clear() # sets labels and so forth # self.style = style # can be None # self.bball = bball # can be None # #self.aging = aging #self.agingCull = agingCull #self.alphaMin = alphaMin self.agingNumAge = -1 if self.aging is not None: from math import log self.agingNumAge = max(int(log(self.alphaMin)/log(self.aging)),1) self.plotProps = {} # self.lineListList = [] # not needed, can, and should, use a.lines self.asImIJ = False # self.transform = None self.axIm = None self.__colorbar = None return def add_axes(self, arect, kwAddAxes={}, **kwarg): aNew = self.f.add_axes(arect, **kwAddAxes) # self.a.set_position((0.05, 0.05, 0.45, 0.9)) new = self.__class__(window=self.win, axes=aNew, **kwarg) return new @classmethod def popKeyArgs(cls, kwargs): retval = {} for key in cls.getKeyArgList(): if kwargs.has_key(key): retval[key] = kwargs.pop(key) return retval @classmethod def getKeyArgList(cls): return cls.__keyArgDict.keys() def __checkCanvas(self): 'leave dead True, not checking for window, just for canvas' #from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg if self.win is not None: return if self.canvas is not None: return from matplotlib.backends.backend_tkagg import FigureCanvasAgg self.canvas = FigureCanvasAgg(self.f) if hasattr(self.a,'mouse_init'): self.a.mouse_init() return def __checkWin(self): if self.win is not None: return winTitle = self.winTitle if winTitle is None : winTitle = self.title if winTitle is None : winTitle = 'plotWin' if hasattr(self,'f'): self.win = PlotWin(1,1,title=winTitle, relfigsize=self.figsize, figure=self.f, axesList=[self.a]) else: self.win = PlotWin(1,1,title=winTitle, relfigsize=self.figsize, axesList=[self.a]) #self.win = PlotWinP(title=winTitle, figure=self.f, axes=self.a) self.canvas = self.win.getCanvas() return def removeLines(self): lines = self.a.get_lines() for line in lines: line.remove() if self.showByDefault: self.show() # self.canvas.show() return def show(self): self.__checkWin() if self.legend is not None: pass # do not yet have this right # if isinstance(self.legend, str) or isinstance(self.legend, int): # or hasattr(self.legend,'__len__') # self.a.legend(loc=self.legend) # elif isinstance(self.legend, bool): # self.a.legend() # elif isinstance(self.legend, list): # self.a.legend(*self.legend) # elif isinstance(self.legend, dict): # self.a.legend(**self.legend) # else: # raise RuntimeError, 'do not know what to do with legend specification: '+str(self.legend) if hasattr(self.a,'mouse_init'): self.a.mouse_init() if hasattr(self.f, 'show'): self.f.show() elif hasattr(self.canvas, 'show'): self.canvas.show() else: raise RuntimeError, 'do not know how to do show' return def clear(self): self.asImIJ = False self.axIm = None # self.transform = None self.x_prev = None self.__colorbar = None self.x_store = [[],[]] if self.showByDefault: self.__checkWin() if self.a is not None: if hasattr(self.a,'mouse_init'): 'doing a.clear() seems like it causes trouble with plotting collections?' self.a.clear() # self.a.cla() self.a.set_autoscale_on(True) else: self.a.clear() # self.a.cla() self.a.set_autoscale_on(True) if self.xticks is not None: self.a.set_xticks(self.xticks) if self.title is not None: self.a.set_title(self.title) if self.xlabel is not None: self.a.set_xlabel(self.xlabel) # r'X axis label $\mu\mbox{lentz}$' if self.win is not None: 'make some room for the label' self.win.haveXLabels() if self.yticks is not None: self.a.set_yticks(self.yticks) if self.xlog: self.a.set_xscale('log') if self.ylog: self.a.set_yscale('log') #self.a.set_ybound(self.ybound) self.a.set_ylim(ymin=self.ybound[0], ymax=self.ybound[1]) self.a.set_xlim(xmin=self.xbound[0], xmax=self.xbound[1]) if self.ylabel is not None: self.a.set_ylabel(self.ylabel) if self.win is not None: 'make some room for the label' self.win.haveYLabels() if self.legend is not None: pass # do not yet have this right # if isinstance(self.legend, str) or isinstance(self.legend, int): # or hasattr(self.legend,'__len__') # self.a.legend(loc=self.legend) # elif isinstance(self.legend, bool): # self.a.legend() # elif isinstance(self.legend, list): # self.a.legend(*self.legend) # elif isinstance(self.legend, dict): # self.a.legend(**self.legend) # else: # raise RuntimeError, 'do not know what to do with legend specification: '+str(self.legend) if self.a is not None: self.a.set_autoscale_on(True) if self.showByDefault: self.show() # self.canvas.show() return def setLegend(self, val=True): # if self.legend is None: # self.legend = True # if val is not None: # self.legend = val self.legend = val return def save(self, **keyArgs): '''make hardcopy of the current figure; specify filename or prefix keyword argument ''' import numpy as num filename = None prefix = None if keyArgs.has_key('filename'): filename = keyArgs.pop('filename') if keyArgs.has_key('prefix'): prefix = keyArgs.pop('prefix') filename = prefix+'.pdf' # .eps if prefix is not None: 'export data' if len(self.x_store[0]) > 0: dataFilename = prefix+'.data' from hexrd import arrayutil try: arrayutil.writeArray(dataFilename, num.array(self.x_store)) except: import sys print 'problem writing to '+dataFilename+' : '+str(self.x_store) sys.exit(1) if not self.ownCanvas: if self.__debug: print 'skipping print_figure because this plot does not own its canvas' else: self.__checkCanvas() if filename is None: raise RuntimeError, 'need filename or prefix entry in keyArgs' #dpi = self.f.get_dpi() #self.canvas.print_figure(filename, dpi=dpi, **keyArgs) self.f.savefig(filename, **keyArgs) return def destroy(self): 'does not clean up self.a, just kills the window if this plot owns the window' if self.ownCanvas and self.win is not None: self.win.destroy() return def drawBBox(self, bbox, **kwargs): import numpy as num bbox_x = bbox[0] bbox_y = bbox[1] xBBox = num.array([ bbox_x[0], bbox_x[1], bbox_x[1], bbox_x[0], bbox_x[0] ]) yBBox = num.array([ bbox_y[0], bbox_y[0], bbox_y[1], bbox_y[1], bbox_y[0] ]) 'go through call, instead of callXY, in case of asImIJ' self.__call__(xBBox, yBBox, **kwargs) return def __call__(self, *args, **keyArgs): import numpy as num noShow = False retVal = None # if keyArgs.has_key('transform'): # 'pop transform so that can keep it for other (overlaid) plots' # self.transform = keyArgs.pop('transform') if keyArgs.has_key('noShow'): noShow = keyArgs.pop('noShow') if len(args) == 2: alphas = None if self.asImIJ: x = args[1] y = args[0] else: x = args[0] y = args[1] if keyArgs.has_key('alphas'): alphas = keyArgs.pop('alphas') assert len(args) == 2, 'len(args) != 2' assert len(alphas) == len(y), 'len(alphas) != len(y)' self.x_prev = None for iX in range(len(x)): self.callXY([x[iX]],[y[iX]],alpha=alphas[iX],**keyArgs) else: self.callXY(x, y, **keyArgs) elif len(args) == 3: X = args[0]; Y = args[1]; data = args[2]; cont = self.callContour(X, Y, data, **keyArgs) retVal = cont elif len(args) == 1 and isinstance(args[0],str): 'interpret string as name of a file to plot in axes' filename = args[0] im = self.callImage(filename, **keyArgs) retVal = im elif len(args) == 1 and isinstance(args[0],num.ndarray): im = self.callIm(args[0], **keyArgs) retVal = im else: raise RuntimeError, 'do not know what to do with args' self.a.set_ylim(ymin=self.ybound[0], ymax=self.ybound[1]) self.a.set_xlim(xmin=self.xbound[0], xmax=self.xbound[1]) if not noShow: if self.showByDefault: self.show() return retVal def callImage(self, filename, **keyArgs): import Image im = Image.open(filename) s = im.tostring() # convert PIL image -> string import numpy as num rgb = num.fromstring(s, dtype=num.uint8).astype(num.float)/255.0 # convert string -> array of floats rgb = num.resize(rgb, (im.size[1], im.size[0], 3)) # resize to RGB array retval = self.callIm(rgb, **keyArgs) return retval def callIm(self, im, interpolation='nearest', aspect='equal', ijAsXY=False, clear=True, **keyArgs): if clear: self.clear() self.a.axis('off') # self.a.set_autoscale_on(True) if ijAsXY: self.asImIJ = False 'imshow does not yet really support transform' if len(im.shape) == 3: imT = im.transpose(1,0,2) else: imT = im.T axIm = self.a.imshow(imT, interpolation=interpolation, aspect=aspect, origin='lower', # transform=self.transform, **keyArgs) self.a.format_coord = lambda x,y: 'i=%d; j=%d; val=%s' % \ (round(x), round(y), str(im[round(x),round(y)])) else: self.asImIJ = True 'imshow does not yet really support transform' axIm = self.a.imshow(im, interpolation=interpolation, aspect=aspect, # transform=self.transform, **keyArgs) self.a.format_coord = lambda x,y: 'i=%d; j=%d; val=%s' % \ (round(y), round(x), str(im[round(y),round(x)])) 'turn off autoscale so that axis limits do not get reset on replots' self.axIm = axIm self.mappable = axIm self.a.set_autoscale_on(False) return axIm def callContour(self, X, Y, data, interpolation=None, aspect=None, **keyArgs): pp = {} pp.update(self.plotProps) pp.update(keyArgs) # plotProps #cont = self.a.contourf(X, Y, data, 200, **keyArgs) 'imshow does not yet really support transform' # self.a.set_autoscale_on(True) cont = self.a.imshow(data, origin='lower', extent=(X[0,0],X[0,-1],Y[0,0],Y[-1,0]), interpolation=interpolation, aspect=aspect, # transform=self.transform, **keyArgs) self.a.set_autoscale_on(False) self.mappable = cont return cont def discontXY(self): self.x_prev = None return def callXY(self, x, y, style=None, **keyArgs): assert len(x) == len(y), \ 'x and y must be same length' xUse = x yUse = y if len(x) == 1: if self.x_prev is not None: xUse = []; xUse.append(self.x_prev[0]); xUse.append(x) yUse = []; yUse.append(self.x_prev[1]); yUse.append(y) pp = {} pp.update(self.plotProps) pp.update(keyArgs) # plotProps if self.bball is not None: 'first, get rid of last bball' lenCur = len(self.a.lines) if lenCur>0: self.a.lines = self.a.lines[0:lenCur-1] if self.aging is not None: #for lineList in self.lineListList[:-1]: # for line in lineList: lenCur = len(self.a.lines) for line in self.a.lines[max(0,lenCur-self.agingNumAge):lenCur]: alphaCur = line.get_alpha() line.set_alpha(alphaCur*self.aging) if self.agingCull: if lenCur > self.agingNumAge: self.a.lines = self.a.lines[lenCur-self.agingNumAge:lenCur] if style is not None: 'passing transform of None can cause trouble' lines = self.a.plot(xUse, yUse, style, # transform=self.transform, **pp) elif self.style is not None: #self.lineListList.append(self.a.plot(x,y,self.style,**pp)) lines = self.a.plot(xUse, yUse, self.style, # transform=self.transform, **pp) else: #self.lineListList.append(self.a.plot(x,y,**pp)) lines = self.a.plot(xUse, yUse, # transform=self.transform, **pp) if self.bball is not None: 'add bball at end' self.a.plot([x[-1]],[y[-1]], self.bball) # transform=self.transform if len(x) == 1: if self.x_accum: self.x_prev = [x, y] self.x_store[0] = self.x_store[0] + list(x) self.x_store[1] = self.x_store[1] + list(y) else: self.x_prev = None if len(x) == len(self.x_store[0]): 'assume called with the same x values' self.x_store.append(list(y)) else: self.x_store[0] = list(x) self.x_store[1] = list(y) return def setVMM(self, vMM): if type(vMM) == int: iCol = vMM vMM = self.a.collections[iCol].get_clim() for col in self.a.collections: col.set_clim(vmin=vMM[0],vmax=vMM[1]) return def colorbar(self, rect=(0.80,0.1,0.05,0.8), adjustPos=True, thing=None, **kwargs): ''' if set rect to None, then colorbar steals self.a ''' self.__checkWin() w = self.win f = self.f if len(self.a.collections) > 0: self.setVMM(0) if thing is None: if len(self.a.collections) > 0: thing = self.a.collections[0] elif hasattr(self, 'mappable'): thing = self.mappable else: raise RuntimeError, 'do not know what to colobar, pass in a thing' if rect is None: self.__colorbar = f.colorbar(thing, cax=self.a, **kwargs) else: cax = w.getNextAxes(rect=rect) self.__colorbar = f.colorbar(thing, cax=cax, **kwargs) if adjustPos: 'adjust existing position to make room for colorbar' bbox = self.a.get_position().get_points() arect = (bbox[0,0], # left bbox[0,1], # bottom rect[0]-bbox[0,0]-0.02, # width bbox[1,1]-bbox[0,1], # height ) self.a.set_position(arect) self.show() return
class PlotWindow(plt.Figure): """ Tk window containing a matplotlib plot. In addition to the functions described below, also supports all functions contained in matplotlib's Axes_ and Figure_ objects. .. _Axes: http://matplotlib.sourceforge.net/api/axes_api.html .. _Figure: http://matplotlib.sourceforge.net/api/figure_api.html Args: title (str): The title to be used for the initial window. visible (bool): Whether to actually display a Tk window (set to `False` to create and save plots without displaying a window). standalone (bool, optional): If `True`, plot windows will be kept open by keeping the Tk event loop alive. """ _tk_started = False # If this is True, uses Toplevel to create the window, otherwise creates a main window def __init__(self, title="Plotting Window", visible=True): plt.Figure.__init__(self) self.add_subplot(111) self.visible = visible self._destroyed = False if self.visible: # If visible, use Tk's frontend # Use the correct method to create a window, then set the tk_started flag to True self.canvas = FigureCanvasTkAgg( self, Toplevel() if self.__class__._tk_started else Tk()) self.__class__._tk_started = True self.title(title) self.make_window() self.show() else: self.canvas = FigureCanvasAgg(self) def make_window(self): """ Pack the plot and matplotlib toolbar into the containing Tk window. This method is called during initialization and it is unlikely you will need to call it elsewhere. """ self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) self.toolbar = NavigationToolbar2Tk(self.canvas, self.canvas._master) self.toolbar.update() self.canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1) def destroy(self): """ Destroy the Tk window. Note that after calling this method (or manually closing the Tk window), this :py:class:`PlotWindow` cannot be used. """ try: # Try and destroy the window self.canvas._master.destroy() except: pass # It was probably already destroyed self._destroyed = True def clear(self): """ Clear the plot, keeping the Tk window active. """ self.clf() self.add_subplot(111) if self.visible: self.show() def show(self): """ Update the canvas image (automatically called for most functions). """ try: self.canvas.draw() except Exception: self.canvas.show() def __getattr__(self, name): show = True if name.startswith('_'): name = name[1:] show = False if hasattr(self.axes[0], name): attr = getattr(self.axes[0], name) if hasattr(attr, '__call__'): if show: def tmp(*args, **kwargs): out = attr(*args, **kwargs) if self.visible: self.show() return out return tmp else: return attr else: return attr else: raise AttributeError("PlotWindow object has no attribute %s" % name) def title(self, title): """ Change the title of the Tk window """ self.canvas._master.title(title) def legend(self, *args): """ Create a legend for the figure (requires plots to have been made with labels) """ handles, labels = self.axes[0].get_legend_handles_labels() self.axes[0].legend(handles, labels) if self.visible: self.show() def save(self, fname, **kwargs): """ Save this plot as an image. File type determined by extension of filename passed in. See documentation for savefig_. .. _savefig: http://matplotlib.sourceforge.net/api/figure_api.html Args: fname: The file to create, which may be a path or a file-like object. """ self.savefig(fname, **kwargs) def stay(self): """ Start the Tkinter window's main loop (e.g., to keep the plot open at the end of the execution of a script) """ self.canvas._master.mainloop() def plot(self, *args, **kwargs): """ Plot lines and/or markers to the Axes. See pyplot_ for more information. .. _pyplot: https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot """ self.__getattr__('plot')(*args, **kwargs)