def __init__(self, parent, messenger=None, size=(6.00,3.70), dpi=96, **kwds): BasePanel.__init__(self, parent, messenger=messenger) matplotlib.rc('axes', axisbelow=True) matplotlib.rc('lines', linewidth=2) matplotlib.rc('xtick', labelsize=11, color='k') matplotlib.rc('ytick', labelsize=11, color='k') matplotlib.rc('grid', linewidth=0.5, linestyle='-') self.conf = PlotConfig() self.win_config = None self.cursor_callback = None self.parent = parent self.figsize = size self.dpi = dpi
class StripChartPanel(BasePanel): """ MatPlotlib 2D plot as a wx.Panel, suitable for embedding in any wx.Frame. This does provide a right-click popup menu for configuration, zooming, saving an image of the figure, and Ctrl-C for copy-image-to-clipboard. For more features, see PlotFrame, which embeds a PlotPanel and also provides, a Menu, StatusBar, and Printing support. """ def __init__(self, parent, messenger=None, size=(6.00,3.70), dpi=96, **kwds): BasePanel.__init__(self, parent, messenger=messenger) matplotlib.rc('axes', axisbelow=True) matplotlib.rc('lines', linewidth=2) matplotlib.rc('xtick', labelsize=11, color='k') matplotlib.rc('ytick', labelsize=11, color='k') matplotlib.rc('grid', linewidth=0.5, linestyle='-') self.conf = PlotConfig() self.win_config = None self.parent = parent self.figsize = size self.dpi = dpi def plot(self,xdata,ydata, label=None, dy=None, color=None, style =None, linewidth=None, marker=None, markersize=None, use_dates=False, ylog_scale=False, grid=None, title=None, xlabel=None, ylabel=None, **kw): """ plot (that is, create a newplot: clear, then oplot) """ self.axes.cla() self.conf.ntrace = 0 self.data_range = [min(xdata),max(xdata), min(ydata),max(ydata)] if xlabel is not None: self.set_xlabel(xlabel) if ylabel is not None: self.set_ylabel(ylabel) if title is not None: self.set_title(title) if use_dates !=None: self.use_dates = use_dates if ylog_scale !=None: self.ylog_scale = ylog_scale if grid: self.conf.show_grid = grid return self.oplot(xdata,ydata,label=label, color=color,style=style, linewidth=linewidth,dy=dy, marker=marker, markersize=markersize, **kw) def oplot(self,xdata,ydata, label=None,color=None,style=None, linewidth=None,marker=None,markersize=None,dy=None, autoscale=True, refresh=True, yaxis='left', **kw): """ basic plot method, overplotting any existing plot """ # set y scale to log/linear yscale = 'linear' if (self.ylog_scale and min(ydata) > 0): yscale = 'log' self.axes.set_yscale(yscale, basey=10) if dy is None: _lines = self.axes.plot(xdata,ydata) else: l1,l2 = self.axes.errorbar(xdata,ydata,yerr=dy) _lines = [l1] for i in l2: _lines.append(i) self.data_range = [min((self.data_range[0],min(xdata))), max((self.data_range[1],max(xdata))), min((self.data_range[2],min(ydata))), max((self.data_range[3],max(ydata)))] cnf = self.conf n = cnf.ntrace if label == None: label = 'trace %i' % (n+1) cnf.set_trace_label(label) cnf.lines[n] = _lines if color: cnf.set_trace_color(color) if style: cnf.set_trace_style(style) if marker: cnf.set_trace_marker(marker) if linewidth!=None: cnf.set_trace_linewidth(linewidth) if markersize!=None: cnf.set_trace_markersize(markersize) self.axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter)) self.axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter)) xa = self.axes.xaxis if refresh: cnf.refresh_trace(n) cnf.relabel() if autoscale: self.axes.autoscale_view() self.zoom_lims = [None] if self.conf.show_grid: # I'm sure there's a better way... for i in self.axes.get_xgridlines()+self.axes.get_ygridlines(): i.set_color(self.conf.grid_color) self.axes.grid(True) self.canvas.draw() cnf.ntrace = cnf.ntrace + 1 return _lines def set_xylims(self, xyrange,autoscale=True): """ update xy limits of a plot, as used with .update_line() """ xmin,xmax,ymin,ymax = xyrange if autoscale: xmin,xmax,ymin,ymax = self.data_range self.axes.set_xlim((xmin,xmax),emit=True) self.axes.set_ylim((ymin,ymax),emit=True) self.axes.update_datalim(((xmin,ymin),(xmax,ymax))) if autoscale: self.axes.set_xbound(self.axes.xaxis.get_major_locator().view_limits(xmin,xmax)) self.axes.set_ybound(self.axes.yaxis.get_major_locator().view_limits(ymin,ymax)) def clear(self): """ clear plot """ self.axes.cla() self.conf.ntrace = 0 self.conf.xlabel = '' self.conf.ylabel = '' self.conf.title = '' def unzoom_all(self,event=None): """ zoom out full data range """ self.zoom_lims = [None] self.unzoom(event) def unzoom(self,event=None): """ zoom out 1 level, or to full data range """ lims = None if len(self.zoom_lims) > 1: self.zoom_lims.pop() lims = self.zoom_lims[-1] if lims is None: # auto scale self.zoom_lims = [None] xmin,xmax,ymin,ymax = self.data_range self.axes.set_xlim((xmin,xmax),emit=True) self.axes.set_ylim((ymin,ymax),emit=True) self.axes.update_datalim(((xmin,ymin),(xmax,ymax))) self.axes.set_xbound(self.axes.xaxis.get_major_locator().view_limits(xmin,xmax)) self.axes.set_ybound(self.axes.yaxis.get_major_locator().view_limits(ymin,ymax)) else: self.axes.set_xlim(lims[:2]) self.axes.set_ylim(lims[2:]) self.old_zoomdc = (None,(0,0),(0,0)) txt = '' if len(self.zoom_lims)>1: txt = 'zoom level %i' % (len(self.zoom_lims)) self.write_message(txt) self.canvas.draw() def set_ylabel(self,s): "set plot ylabel" self.conf.ylabel = s self.conf.relabel() def configure(self,event=None): try: self.win_config.Raise() except: self.win_config = PlotConfigFrame(self.conf) #### ## create GUI #### def BuildPanel(self, **kwds): """ builds basic GUI panel and popup menu""" wx.Panel.__init__(self, self.parent, -1, **kwds) self.fig = Figure(self.figsize,dpi=self.dpi) self.axes = self.fig.add_axes([0.12,0.12,0.80,0.80], axisbg='#FFFFFA') self.canvas = FigureCanvas(self, -1, self.fig) self.printer.canvas = self.canvas self.set_bg() self.conf.axes = self.axes self.conf.fig = self.fig self.conf.canvas= self.canvas self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS)) # overwrite ScalarFormatter from ticker.py here: self.axes.yaxis.set_major_formatter(FuncFormatter(self.yformatter)) self.axes.xaxis.set_major_formatter(FuncFormatter(self.xformatter)) # This way of adding to sizer allows resizing sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 2, wx.LEFT|wx.TOP|wx.BOTTOM|wx.EXPAND,0) self.SetAutoLayout(True) self.SetSizer(sizer) self.Fit() # define zoom box properties self.conf.zoombrush = wx.Brush('#080830', wx.SOLID) self.conf.zoompen = wx.Pen('#707070', 2, wx.SOLID) # SOLID) self.addCanvasEvents() def update_line(self,trace,xdata,ydata): """ update a single trace, for faster redraw """ x = self.conf.get_mpl_line(trace) x.set_data(xdata,ydata) self.data_range = [min(self.data_range[0],xdata.min()), max(self.data_range[1],xdata.max()), min(self.data_range[2],ydata.min()), max(self.data_range[3],ydata.max())] # this defeats zooming, which gets ugly in this fast-mode anyway. self.cursor_mode = 'cursor' self.canvas.draw() #### ## GUI events #### def reportLeftDown(self,event=None): if event == None: return fmt = "X,Y= %s, %s" % (self._xfmt, self._yfmt) self.write_message(fmt % (event.xdata,event.ydata), panel=0)