class CanvasFrame(wx.Frame): """create a main plotting canvas title : optional window title as_one : plot as one overlapping graph (else a list of scaled graphs) verb : verbose level (default 1) """ counter = 0 def __init__(self, title='', as_one=0, verb=1): wx.Frame.__init__(self, None, -1, title, size=(400, 300)) self.counter += 1 self.verb = verb self.figure = Figure() self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.SetSizer(self.sizer) self.Fit() self.canvas.mpl_connect('key_press_event', self.cb_keypress) self.as_one = as_one self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.toolbar.update() def cb_keypress(self, event): if event.key == 'q': self.Close() def plot_scaled_mat(self, amat, verb=1): """plot data scaled and shifted to fit on one graph data - AfniMatrix, list of float lists, or 1D file title - optional window title verb - optional verbose level """ # allow matlist, list of float lists, # if type(matlist) == type([]): # e0 = matlist[0] # if type if not matlist: return nmats = len(matlist) if nmats < 1: return yformat = FormatStrFormatter('%5.1f') def plot_matlist(self, matlist, title='', ylabels=[], ftcolors=0, verb=1): """plot AfniMatrix list, one graph per AfniMatrix matlist - list of AfniMatrix elements title - optional window title ylabels - optional list of ylabel per mat ftcolors - flag: use fit/timeseries colors (black blue) verb - optional verbose level """ if not matlist: return nmats = len(matlist) if nmats < 1: return yformat = FormatStrFormatter('%5.1f') matplotlib.rcParams['lines.linewidth'] = 2 # make a label list, and get max length (among any label[0]) if ylabels: labels = ylabels else: labels = [] rlen = 0 nruns = 0 maxlen = 0 for ind in range(nmats): if ylabels: lab = ylabels[ind] else: if matlist[ind].labels: lab = matlist[ind].labels[0] else: lab = '' labels.append(lab) if len(lab) > maxlen: maxlen = len(lab) # note run info if nruns == 0 and matlist[ind].nruns > 1: nruns = matlist[ind].nruns rlen = matlist[ind].run_len for ind in range(nmats): amat = matlist[ind] if ind == 0: tstr = title else: tstr = '' ax = self.figure.add_subplot(nmats, 1, ind + 1, title=tstr) #if ftcolors and amat.ncols == 2: # use blue over black? # ax.plot(amat.mat[:,0], 'k') # ax.plot(amat.mat[:,1], 'b') ax.plot(amat.mat) # apply y tickmarks ymin, ymax = ax.get_ylim() width = ymax - ymin if ymin * ymax < 0.0: ymean = 0.0 else: ymean = round((ymin + ymax) / 2.0, 2) ax.grid(True) ax.yaxis.set_major_formatter(yformat) # if there are many graphs, reduce the number of yticks if nmats > 10: ax.set_yticks(N.array([ymin, ymax])) elif nmats > 2: ax.set_yticks(N.array([ymin, ymean, ymax])) if rlen > 0: ax.set_xticks(N.array([r * rlen for r in range(nruns + 1)])) if ind < nmats - 1: ax.set_xticklabels([]) else: ax.set_xlabel('TRs') if labels: if nmats > 1: ax.set_ylabel('%-*s ' % (maxlen, labels[ind]), rotation='horizontal') rv, plist = self.axis_posn(ax) if rv == 0: ax.set_position((0.15, plist[1], 0.7, 0.7 / nmats)) else: ax.set_ylabel('%s' % labels[ind]) ax.set_position((0.15, 0.2, 0.7, 0.7)) self.canvas.draw() matplotlib.rcParams['lines.linewidth'] = 1 # reset def axis_posn(self, ax): """return error code, posn array""" # first attempt is to look for simple array return try: posn = ax.get_position() except: if self.verb > 1: print '** failed ax.get_position()' return 1, None # have list, ready for some return if type(posn) == type([]): if len(posn) < 4: if self.verb > 1: print '** get_position returns len %d list' % len(posn) return 1, None if self.verb > 2: print '-- get_position returns list %s' % \ UTIL.float_list_string(posn) return 0, posn # no list, assume Bbox and expect get_points() to return 2x2 numpy array try: plist = posn.get_points() except: if self.verb > 1: print '** failed posn.get_points()' return 1, None if type(plist) != type(N.array([])): if self.verb > 1: print '** posn.get_points() does not return N.array?' return 1, None try: pnlist = [plist[0][0], plist[0][1], plist[1][0], plist[1][1]] except: if self.verb > 1: print '** bad plist shape %s' % plist.shape return 1, None if self.verb > 2: print '-- get_position returns Bbox list: %s' % \ UTIL.float_list_string(pnlist) return 0, pnlist def plot_mat_by_cols(self, amat, cols=[]): """plot the given columns from a single AfniMatrix""" if not isinstance(amat, AM.AfniXmat): print '** plot_MBC: instance is not AfniXmat' return if not cols: if amat.verb > 1: print '-- plotting default of %d cols' % amat.ncols cols = [i for i in range(amat.ncols)] ncols = len(cols) if ncols < 1: return # create reduced matrix and column labels mat = amat.mat[:, cols] yformat = FormatStrFormatter('%5.1f') if amat.labels: labels = N.array(amat.labels) labels = labels[cols] labels = labels.tolist() # create axis formatter string striplabs = 1 for label in labels: # strip trailing '#' if indices are all 0 ind = regress_index(label) if ind > 0: striplabs = 0 maxlen = 0 for l in range(len(labels)): label = labels[l] if striplabs: labels[l] = labels[l][0:labels[l].rfind('#')] if len(labels[l]) > maxlen: maxlen = len(labels[l]) for i in range(ncols): if i == 0: title = '%s [%s]' % (os.path.basename( amat.fname), UTIL.encode_1D_ints(cols)) else: title = '' if self.as_one: # then only create one axis if i == 0: ax = self.figure.add_subplot(1, 1, 1, title=title) else: ax = self.figure.add_subplot(ncols, 1, i + 1, title=title) data = mat[:, i] ax.plot(data) # apply y tickmarks ymin, ymax = ax.get_ylim() width = ymax - ymin if ymin * ymax < 0.0: ymean = 0.0 else: ymean = round((ymin + ymax) / 2.0, 2) ax.grid(True) ax.yaxis.set_major_formatter(yformat) amax = round(data.max(), 1) if self.as_one: pass # use default yticks elif amax == 1.0 and ymin == 0.0: ax.set_yticks(N.array([ymin, amax])) elif ncols > 10: ax.set_yticks(N.array([ymin, ymax])) else: ax.set_yticks(N.array([ymin, ymean, ymax])) # now that yticks are set, prevent tight limits if not self.as_one: if ymin == data.min(): ymin -= 0.15 * width ax.set_ylim((ymin, ymax)) if ymax == data.max(): ymax += 0.15 * width ax.set_ylim((ymin, ymax)) if amat.run_len > 10 and amat.nruns > 1: ax.set_xticks( N.array( [r * amat.run_len for r in range(amat.nruns + 1)])) if i < ncols - 1: ax.set_xticklabels([]) else: ax.set_xlabel('TRs') if self.as_one: ax.set_ylabel('') elif amat.labels: ax.set_ylabel('%-*s ' % (maxlen, labels[i]), rotation='horizontal') rv, plist = self.axis_posn(ax) # rcr - fix #if rv == 0: ax.set_position((0.2, plist[1], plist[2], plist[3])) if rv == 0: ax.set_position((0.15, plist[1], 0.7, 0.7 / ncols)) self.Fit() self.canvas.draw()
class icPlotPanel(wx.Panel): """ """ def __init__(self, parent, id=-1, pos=(-1, -1), size=(-1, -1), style=0, bWxAgg=False): wx.Panel.__init__(self, parent, id, pos, size, style=style) self.fig = Figure((5, 4), 75) if bWxAgg: self.canvas = FigureCanvasWxAgg(self, -1, self.fig) else: self.canvas = FigureCanvasWx(self, -1, self.fig) self.canvas.mpl_connect('motion_notify_event', self.OnMouseMove) self.canvas.mpl_connect('button_press_event', self.OnMouseLeftDown) self.toolbar = icPloterToolbar(self.canvas) self.toolbar.Realize() self.parent = parent self.legendLst = [] # --- Атрибуты курсора # Положение курсора self._cursor = None # Значение курсора self._cursorVal = None # Статический курсор - значение обновляется только при нажантии # левой кнопки мыши self._statCursor = None # On Windows, default frame size behaviour is incorrect # you don't need this under Linux tw, th = self.toolbar.GetSizeTuple() fw, fh = self.canvas.GetSizeTuple() self.toolbar.SetSize(wx.Size(fw, th)) # Create a figure manager to manage things self.figmgr = FigureManager(self.canvas, 1, self) # Now put all into a sizer sizer = wx.BoxSizer(wx.VERTICAL) # This way of adding to sizer allows resizing sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) # Best to allow the toolbar to resize! sizer.Add(self.toolbar, 0, wx.GROW) self.SetSizer(sizer) self.Fit() # --- Описание обработчиков self.Bind(wx.EVT_PAINT, self.OnPaint) # --- Инициализация графика self.init_graph() def draw_cursor(self, event): """ event is a MplEvent. Draw a cursor over the axes """ if event.inaxes is None: self.erase_cursor() try: del self.lastInfo except AttributeError: pass return canvas = self.canvas figheight = canvas.figure.bbox.height() ax = event.inaxes left, bottom, width, height = ax.bbox.get_bounds() bottom = figheight - bottom top = bottom - height right = left + width x, y = event.x, event.y y = figheight - y dc = wx.ClientDC(canvas) dc.SetLogicalFunction(wx.XOR) wbrush = wx.Brush(wx.Colour(255, 255, 255), wx.TRANSPARENT) wpen = wx.Pen(wx.Colour(200, 200, 200), 1, wx.SOLID) dc.SetBrush(wbrush) dc.SetPen(wpen) dc.ResetBoundingBox() dc.BeginDrawing() x, y, left, right, bottom, top = [ int(val) for val in x, y, left, right, bottom, top ] self.erase_cursor() line1 = (x, bottom, x, top) line2 = (left, y, right, y) self.lastInfo = line1, line2, ax, dc dc.DrawLine(*line1) # draw new dc.DrawLine(*line2) # draw new dc.EndDrawing() time, price = event.xdata, event.ydata try: tm = str(num2date(time))[:16] except: tm = time self._cursor = (time, price) self._cursorVal = (tm, price) def erase_cursor(self): try: lastline1, lastline2, lastax, lastdc = self.lastInfo except AttributeError: pass else: lastdc.DrawLine(*lastline1) # erase old lastdc.DrawLine(*lastline2) # erase old def GetToolBar(self): """ You will need to override GetToolBar if you are using an unmanaged toolbar in your frame. """ return self.toolbar def GetCursorPos(self): """ Возвращает положение курсора. """ return self._cursor def GetCursorVal(self): """ Возвращает значение курсора - временная координата приведена в читаемый вид - YYYY-MM-DD HH:MM:SS. """ return self._cursorVal def GetStaticCursor(self): """ Возвращает значение статического курсора - значение которого обновляется только при нажантии левой кнопки мыши. """ return self._statCursor def init_graph(self): """ Инициализация графика. """ self.canvas.figure.set_facecolor('#f5f5f5') self.subplot = a = self.fig.add_subplot(111) a.grid(True) self.toolbar.update() def OnMouseMove(self, evt): """ """ self.draw_cursor(evt) def OnMouseLeftDown(self, evt): """ """ self._statCursor = self.GetCursorPos() def OnPaint(self, evt): """ """ self.erase_cursor() try: del self.lastInfo except AttributeError: pass self.canvas.draw() evt.Skip() def plot_data(self): a = self.subplot t = numpy.arange(0.0, 3.0, 0.01) s = numpy.sin(2 * numpy.pi * t) c = numpy.cos(2 * numpy.pi * t) a.plot(t, c, 'r:o') def add_plot_date(self, dates, values, format=None, xlabel=None, ylabel=None, bClear=True, titlePlot='Title', legend='Legend'): """ Наполняет график точками. @type dates: C{list | tuple} @param dates: Список дат в формате datetime. @type values: C{list | tuple} @param values: Список значений. @type dates: C{list | tuple} @param dates: Список дат в формате datetime. @type xlabel: C{string} @param xlabel: Подпись оси X. @type ylabel: C{string} @param ylabel: Подпись оси Y. @type bClear: C{bool} @param bClear: Признак того, что необходимо все предыдущие точки удалить из графика. @type titlePlot: C{string} @param titlePlot: Заголовок. @type legend: C{string} @param legend: Легенда. """ if bClear: self.subplot.lines = [] self.legendLst = [] matplotlib.rcParams['timezone'] = 'US/Pacific' tz = timezone('US/Pacific') majorTick = HourLocator(range(0, 25, 3), tz=tz) line = self.subplot.plot_date(dates, values, format, tz=tz) self.subplot.xaxis.set_major_locator(majorTick) # Устанавливаем легенду self.legendLst.append(legend) self.subplot.legend(self.subplot.lines, self.legendLst, 'upper right', shadow=True) def set_date_plot2(self, date1=None, date2=None): """ """ # --- Plot2 matplotlib.rcParams['timezone'] = 'US/Pacific' tz = timezone('US/Pacific') if not date1: date1 = datetime.datetime(2000, 3, 2, 0, tzinfo=tz) else: date1 = datetime.datetime(date1[0], date1[1], date1[2], date1[3], tzinfo=tz) if not date2: date2 = datetime.datetime(2000, 3, 2, 23, tzinfo=tz) else: date2 = datetime.datetime(date2[0], date2[1], date2[2], date2[3], tzinfo=tz) delta = datetime.timedelta(minutes=20) dates = drange(date1, date2, delta) dd = 10 yy = pylab.arrayrange(len(dates) * 1.0) ysq = [y * y / dd for y in yy] self.add_plot_date(dates, ysq, 'bo', 'Время', 'Цена', legend='Скорость') self.add_plot_date(dates, yy, 'r-d', bClear=False) labels = self.subplot.get_xticklabels() pylab.set(labels, 'rotation', 45, size=10)
class CanvasFrame(wx.Frame): """create a main plotting canvas title : optional window title as_one : plot as one overlapping graph (else a list of scaled graphs) verb : verbose level (default 1) """ counter = 0 def __init__(self, title="", as_one=0, verb=1): wx.Frame.__init__(self, None, -1, title, size=(400, 300)) self.counter += 1 self.verb = verb self.figure = Figure() self.canvas = FigureCanvas(self, -1, self.figure) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) self.SetSizer(self.sizer) self.Fit() self.canvas.mpl_connect("key_press_event", self.cb_keypress) self.as_one = as_one self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) self.toolbar.update() def cb_keypress(self, event): if event.key == "q": self.Close() def plot_scaled_mat(self, amat, verb=1): """plot data scaled and shifted to fit on one graph data - AfniMatrix, list of float lists, or 1D file title - optional window title verb - optional verbose level """ # allow matlist, list of float lists, # if type(matlist) == type([]): # e0 = matlist[0] # if type if not matlist: return nmats = len(matlist) if nmats < 1: return yformat = FormatStrFormatter("%5.1f") def plot_matlist(self, matlist, title="", ylabels=[], ftcolors=0, verb=1): """plot AfniMatrix list, one graph per AfniMatrix matlist - list of AfniMatrix elements title - optional window title ylabels - optional list of ylabel per mat ftcolors - flag: use fit/timeseries colors (black blue) verb - optional verbose level """ if not matlist: return nmats = len(matlist) if nmats < 1: return yformat = FormatStrFormatter("%5.1f") matplotlib.rcParams["lines.linewidth"] = 2 # make a label list, and get max length (among any label[0]) if ylabels: labels = ylabels else: labels = [] rlen = 0 nruns = 0 maxlen = 0 for ind in range(nmats): if ylabels: lab = ylabels[ind] else: if matlist[ind].labels: lab = matlist[ind].labels[0] else: lab = "" labels.append(lab) if len(lab) > maxlen: maxlen = len(lab) # note run info if nruns == 0 and matlist[ind].nruns > 1: nruns = matlist[ind].nruns rlen = matlist[ind].run_len for ind in range(nmats): amat = matlist[ind] if ind == 0: tstr = title else: tstr = "" ax = self.figure.add_subplot(nmats, 1, ind + 1, title=tstr) # if ftcolors and amat.ncols == 2: # use blue over black? # ax.plot(amat.mat[:,0], 'k') # ax.plot(amat.mat[:,1], 'b') ax.plot(amat.mat) # apply y tickmarks ymin, ymax = ax.get_ylim() width = ymax - ymin if ymin * ymax < 0.0: ymean = 0.0 else: ymean = round((ymin + ymax) / 2.0, 2) ax.grid(True) ax.yaxis.set_major_formatter(yformat) # if there are many graphs, reduce the number of yticks if nmats > 10: ax.set_yticks(N.array([ymin, ymax])) elif nmats > 2: ax.set_yticks(N.array([ymin, ymean, ymax])) if rlen > 0: ax.set_xticks(N.array([r * rlen for r in range(nruns + 1)])) if ind < nmats - 1: ax.set_xticklabels([]) else: ax.set_xlabel("TRs") if labels: if nmats > 1: ax.set_ylabel("%-*s " % (maxlen, labels[ind]), rotation="horizontal") rv, plist = self.axis_posn(ax) if rv == 0: ax.set_position((0.15, plist[1], 0.7, 0.7 / nmats)) else: ax.set_ylabel("%s" % labels[ind]) ax.set_position((0.15, 0.2, 0.7, 0.7)) self.canvas.draw() matplotlib.rcParams["lines.linewidth"] = 1 # reset def axis_posn(self, ax): """return error code, posn array""" # first attempt is to look for simple array return try: posn = ax.get_position() except: if self.verb > 1: print "** failed ax.get_position()" return 1, None # have list, ready for some return if type(posn) == type([]): if len(posn) < 4: if self.verb > 1: print "** get_position returns len %d list" % len(posn) return 1, None if self.verb > 2: print "-- get_position returns list %s" % UTIL.float_list_string(posn) return 0, posn # no list, assume Bbox and expect get_points() to return 2x2 numpy array try: plist = posn.get_points() except: if self.verb > 1: print "** failed posn.get_points()" return 1, None if type(plist) != type(N.array([])): if self.verb > 1: print "** posn.get_points() does not return N.array?" return 1, None try: pnlist = [plist[0][0], plist[0][1], plist[1][0], plist[1][1]] except: if self.verb > 1: print "** bad plist shape %s" % plist.shape return 1, None if self.verb > 2: print "-- get_position returns Bbox list: %s" % UTIL.float_list_string(pnlist) return 0, pnlist def plot_mat_by_cols(self, amat, cols=[]): """plot the given columns from a single AfniMatrix""" if not isinstance(amat, AM.AfniXmat): print "** plot_MBC: instance is not AfniXmat" return if not cols: if amat.verb > 1: print "-- plotting default of %d cols" % amat.ncols cols = [i for i in range(amat.ncols)] ncols = len(cols) if ncols < 1: return # create reduced matrix and column labels mat = amat.mat[:, cols] yformat = FormatStrFormatter("%5.1f") if amat.labels: labels = N.array(amat.labels) labels = labels[cols] labels = labels.tolist() # create axis formatter string striplabs = 1 for label in labels: # strip trailing '#' if indices are all 0 ind = regress_index(label) if ind > 0: striplabs = 0 maxlen = 0 for l in range(len(labels)): label = labels[l] if striplabs: labels[l] = labels[l][0 : labels[l].rfind("#")] if len(labels[l]) > maxlen: maxlen = len(labels[l]) for i in range(ncols): if i == 0: title = "%s [%s]" % (os.path.basename(amat.fname), UTIL.encode_1D_ints(cols)) else: title = "" if self.as_one: # then only create one axis if i == 0: ax = self.figure.add_subplot(1, 1, 1, title=title) else: ax = self.figure.add_subplot(ncols, 1, i + 1, title=title) data = mat[:, i] ax.plot(data) # apply y tickmarks ymin, ymax = ax.get_ylim() width = ymax - ymin if ymin * ymax < 0.0: ymean = 0.0 else: ymean = round((ymin + ymax) / 2.0, 2) ax.grid(True) ax.yaxis.set_major_formatter(yformat) amax = round(data.max(), 1) if self.as_one: pass # use default yticks elif amax == 1.0 and ymin == 0.0: ax.set_yticks(N.array([ymin, amax])) elif ncols > 10: ax.set_yticks(N.array([ymin, ymax])) else: ax.set_yticks(N.array([ymin, ymean, ymax])) # now that yticks are set, prevent tight limits if not self.as_one: if ymin == data.min(): ymin -= 0.15 * width ax.set_ylim((ymin, ymax)) if ymax == data.max(): ymax += 0.15 * width ax.set_ylim((ymin, ymax)) if amat.run_len > 10 and amat.nruns > 1: ax.set_xticks(N.array([r * amat.run_len for r in range(amat.nruns + 1)])) if i < ncols - 1: ax.set_xticklabels([]) else: ax.set_xlabel("TRs") if self.as_one: ax.set_ylabel("") elif amat.labels: ax.set_ylabel("%-*s " % (maxlen, labels[i]), rotation="horizontal") rv, plist = self.axis_posn(ax) # rcr - fix # if rv == 0: ax.set_position((0.2, plist[1], plist[2], plist[3])) if rv == 0: ax.set_position((0.15, plist[1], 0.7, 0.7 / ncols)) self.Fit() self.canvas.draw()