class AmountGraph(wx.Panel): def __init__(self, parent, all_data): wx.Panel.__init__(self, parent=parent) plt.style.use('bmh') # matplotlib figure self.figure = Figure() self.ax = self.figure.subplots() money_list = [money[2] for money in all_data] if money_list == []: max_money = 1000 else: max_money = max(money_list) hist_bins = round(max_money / 1000) self.ax.hist(money_list, histtype='barstacked', bins=hist_bins, range=(0, hist_bins * 1000), rwidth=1) # canvas self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.figure) self.canvas.SetBackgroundColour(wx.Colour(100, 255, 255)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, flag=wx.EXPAND) self.SetSizer(sizer) self.Fit()
class PlotPanel(wx.Panel): """ The PlotPanel has a Figure and a Canvas. OnSize events simply set a flag, and the actual resizing of the figure is triggered by an Idle event. """ def __init__(self, parent, obj_id): # initialize Panel wx.Panel.__init__(self, parent, obj_id) # initialize matplotlib stuff self.figure = Figure(None, None) self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.figure) rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) self.Bind(wx.EVT_SIZE, self._on_size) def _on_size(self, event): self._set_size() def _set_size(self): pixels = tuple(self.GetClientSize()) self.SetSize(pixels) self.canvas.SetSize(pixels) self.figure.set_size_inches( float(pixels[0]) / self.figure.get_dpi(), float(pixels[1]) / self.figure.get_dpi()) def draw(self): pass # abstract, to be overridden by child classes
class Plot(wx.Panel): def __init__(self, parent, id=-1, dpi=None): ps = parent.GetSize() wx.Panel.__init__(self, parent, id=id, size=ps) self.SetBackgroundColour('WHITE') self.figure = mpl.figure.Figure(dpi=dpi, facecolor='w', figsize=(ps[0] * .09, ps[1] * .09)) #self.figure.SetBackgroundColour('WHITE') self.canvas = Canvas(self, -1, self.figure) self.canvas.SetBackgroundColour('WHITE') self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.doSave) def doSave(self, event): dlg = wx.FileDialog(self, message="Save file as ...", defaultDir=os.curdir, defaultFile="", wildcard="*.png", style=wx.FD_SAVE) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() dlg.Destroy() self.figure.savefig(path, dpi=None, facecolor='w', edgecolor='w', orientation='portrait', papertype=None, format='png', transparent=False, bbox_inches=None, pad_inches=0.1, frameon=None)
class PeriodGraph(wx.Panel): def __init__(self, parent, test): wx.Panel.__init__(self, parent=parent) plt.style.use('bmh') # matplotlib figure year_list = [item[2] for item in test] year_list = list(set(year_list)) year_list.sort() month_list = [num for num in range(1, 13)] use_list = [item[0] for item in test] use_list = list(set(use_list)) use_list.sort() data_list = { use: [[0 for month in month_list] for year in year_list] for use in use_list } for item in test: for y_index, year in enumerate(year_list): if item[2] == year: for month in month_list: if item[3] == month: for use in use_list: if item[0] == use: data_list[use][y_index][month - 1] = item[1] data_print_list = [ f"{year}/{month}" for year in year_list for month in month_list ] plt.style.use('bmh') self.figure = Figure() self.ax1 = self.figure.subplots() all_list = np.array([0 for month in month_list for year in year_list]) for use in use_list: use_data = [] for data in data_list[use]: use_data.extend(data) use_data = np.array(use_data) all_list += use_data self.ax1.plot(data_print_list, use_data, marker='o') self.ax1.set_xticklabels(data_print_list, rotation=270, fontsize='small') self.ax2 = self.ax1.twinx() res = np.cumsum(all_list) self.ax2.plot(data_print_list, res, color="red") # canvas self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.figure) self.canvas.SetBackgroundColour(wx.Colour(100, 255, 255)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, flag=wx.EXPAND) self.SetSizer(sizer) self.Fit()
class PlotPanel(wx.Panel): """The PlotPanel has a Figure and a Canvas. OnSize events simply set a flag, and the actual resizing of the figure is triggered by an Idle event.""" def __init__(self, parent, color=None, dpi=None, **kwargs): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure # initialize Panel if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__(self, parent, **kwargs) # initialize matplotlib stuff self.figure = Figure(None, dpi) self.axes = self.figure.gca() self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.SetColor(color) self._SetSize() self.draw() self.axes.set_xlabel('T (s)') self.axes.set_ylabel('Alfa_max (g)') self.axes.set_title("wave curve") self.axes.grid(True) self._resizeflag = False self.Bind(wx.EVT_IDLE, self._onIdle) self.Bind(wx.EVT_SIZE, self._onSize) def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def _onSize(self, event): self._resizeflag = True def _onIdle(self, evt): if self._resizeflag: self._resizeflag = False self._SetSize() def _SetSize(self): pixels = tuple(self.parent.GetClientSize()) self.SetSize(pixels) self.canvas.SetSize(pixels) self.figure.set_size_inches( float(pixels[0]) / self.figure.get_dpi(), float(pixels[1]) / self.figure.get_dpi()) def draw(self): pass # abstract, to be overridden by child classes
class myWxPlot(wx.Panel): def __init__(self, parent): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure self.parent = parent wx.Panel.__init__(self, parent) #matplotlib figure self.figure = Figure(None) self.figure.set_facecolor((0.7, 0.7, 1.)) self.subplot = self.figure.add_subplot(111) #canvas self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.canvas.SetBackgroundColour(wx.Colour(100, 255, 255)) self._SetSize() self.draw2() def _SetSize(self): size = tuple(self.parent.GetClientSize()) self.SetSize(size) self.canvas.SetSize(size) self.figure.set_size_inches( float(size[0]) / self.figure.get_dpi(), float(size[1]) / self.figure.get_dpi()) def draw(self): from mpl_toolkits.mplot3d import Axes3D import numpy as np x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X) + np.cos(Y) ax = Axes3D(self.figure) ax.plot_wireframe(X, Y, Z) def draw2(self): import numpy as np theta = np.arange(0, 200, 0.1) x = 2 * np.cos(theta / 7) y = 3 * np.sin(theta / 3) self.subplot.plot(x, y, '-r') self.subplot.set_title("Sample", fontsize=12) self.subplot.set_xlabel("x") self.subplot.set_ylabel("y") self.subplot.set_xlim([-4, 4]) self.subplot.set_ylim([-4, 4])
class WXMatPlotLibPanel(wx.Panel): def __init__(self, parent, color=None, dpi=None, **kwargs): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure # initialize Panel if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__(self, parent, **kwargs) # initialize matplotlib stuff self.figure = Figure(None, dpi) self.canvas = FigureCanvasWxAgg(self, -1, self.figure) #self.SetColor( color ) self._SetSize() self.draw() self._resizeflag = False self.Bind(wx.EVT_IDLE, self._onIdle) self.Bind(wx.EVT_SIZE, self._onSize) def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def _onSize(self, event): self._resizeflag = True def _onIdle(self, evt): if self._resizeflag: self._resizeflag = False self._SetSize() def _SetSize(self): pixels = tuple(self.parent.GetClientSize()) self.SetSize(pixels) self.canvas.SetSize(pixels) self.figure.set_size_inches( float(pixels[0]) / self.figure.get_dpi(), float(pixels[1]) / self.figure.get_dpi()) def draw(self): pass # abstract, to be overridden by child classes
class plottingWindow(wx.Window): def __init__(self, *args, **kwargs): if "figsize" in kwargs: self.figure = Figure(figsize=kwargs["figsize"]) self._axes = [0.1, 0.1, 0.8, 0.8] del kwargs["figsize"] else: self.figure = Figure(figsize=[8, 2.5]) self.figure.set_facecolor('white') wx.Window.__init__(self, *args, **kwargs) self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.figure.set_facecolor('white') self.figure.set_edgecolor('white') self.canvas.SetBackgroundColour('white') # Create a resizer self.Bind(wx.EVT_SIZE, self.sizeHandler) self.resize = 1 # self.canvas.mpl_connect('motion_notify_event', self.onMotion) # Prepare for zoom self.zoom = None self.zoomtype = "box" def setupGetXAxies(self, plots): self.getxaxis = GetXValues(plots) def repaint(self): """ Redraw and refresh the plot. :return: None """ self.canvas.draw() def clearPlot(self, *args): """ Clear the plot and rest some of the parameters. :param args: Arguments :return: """ self.figure.clear() self.repaint() def sizeHandler(self, *args, **kwargs): if self.resize == 1: self.canvas.SetSize(self.GetSize())
class PiePanel (wx.Panel): def __init__( self, parent, color=None, dpi=None, explode=(0, 0.05, 0, 0), fracs=[15,30,45, 10], **kwargs ): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__( self, parent, **kwargs ) self.parent=parent self.figure = Figure( None, dpi ) self.canvas = FigureCanvasWxAgg( self, -1, self.figure ) labels = 'Frogs', 'Hogs', 'Dogs', 'Logs' self.SetColor( color ) self._SetSize() ax = self.figure.add_axes([0.1, 0.1, 0.8, 0.8]) pies=ax.pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True) self.draw() self._resizeflag = False self.Bind(wx.EVT_IDLE, self._onIdle) self.Bind(wx.EVT_SIZE, self._onSize) def SetColor( self, rgbtuple=None ): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get() clr = [c/255. for c in rgbtuple] self.figure.set_facecolor( clr ) self.figure.set_edgecolor( clr ) self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) ) def _onSize( self, event ): self._resizeflag = True def _onIdle( self, evt ): if self._resizeflag: self._resizeflag = False self._SetSize() def _SetSize( self ): pixels = tuple( self.parent.GetClientSize() ) self.SetSize( pixels ) self.canvas.SetSize( pixels ) self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(), float( pixels[1] )/self.figure.get_dpi() ) def draw( self ): print "Drawing" self.canvas.draw()
class UseGraph(wx.Panel): def __init__(self, parent, use_accounting_list): wx.Panel.__init__(self, parent=parent) plt.style.use('bmh') use = [use_accounting[0] for use_accounting in use_accounting_list] money = [use_accounting[1] for use_accounting in use_accounting_list] use_money_df = pd.DataFrame({ "use": use, "money": money }, columns=["use", "money"]) use_money_df["accum"] = np.cumsum(use_money_df["money"]) use_money_df["accum_pa"] = use_money_df["accum"] / sum(money) * 100 # matplotlib figure self.figure = Figure() self.ax1 = self.figure.subplots() self.ax1.bar(use, money, label=u'累計', width=-1, edgecolor='k') self.ax1.tick_params(axis="x", which="major", direction="in") self.ax1.set_xticklabels(use, rotation=270, fontsize='small') self.ax2 = self.ax1.twinx() self.ax2.plot(use, use_money_df["accum_pa"], c='k', marker='o', label=u'累積和') self.ax2.set_ylim([0, 100]) self.ax2.set_yticks(np.arange(0, 101, 10)) percent_labels = [f"{i}%" for i in np.arange(0, 101, 10)] self.ax2.set_yticklabels(percent_labels) try: self.figure.legend(bbox_to_anchor=(1, 0.05), loc='upper right', ncol=2) except: pass # canvas self.canvas = FigureCanvasWxAgg(self, wx.ID_ANY, self.figure) self.canvas.SetBackgroundColour(wx.Colour(100, 255, 255)) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, flag=wx.EXPAND) self.SetSizer(sizer) self.Fit()
class WxMatplotlibPanel(wx.Panel): def __init__(self, parent): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure self.parent = parent wx.Panel.__init__(self, parent) self.figure = Figure(None) self.figure.set_facecolor((0.7, 0.7, 1.)) self.subplot = self.figure.add_subplot(111) self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.canvas.SetBackgroundColour(wx.Colour(100, 255, 255)) self._SetSize() self.draw() def _SetSize(self): size = tuple(self.parent.GetClientSize()) self.SetSize(size) self.canvas.SetSize(size) self.figure.set_size_inches( float(size[0]) / self.figure.get_dpi(), float(size[1]) / self.figure.get_dpi()) def draw(self): from mpl_toolkits.mplot3d import Axes3D import numpy as np x = np.arange(-3, 3, 0.25) y = np.arange(-3, 3, 0.25) X, Y = np.meshgrid(x, y) Z = np.sin(X) + np.cos(Y) ax = Axes3D(self.figure) #ax.plot_wireframe(X, Y, Z) ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
class plotTimeSeries(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def _init_ctrls(self, parent): #matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, parent, -1) self.parent = parent # self.figure = Figure()#matplotlib.figure.Figure() #init Plot # self.timeSeries=self.figure.add_subplot(111) self.timeSeries = host_subplot(111, axes_class=AA.Axes) # self.timeSeries.axis([0, 1, 0, 1])# self.timeSeries.plot([],[]) self.timeSeries.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, plt.gcf()) # self.canvas = FigCanvas(self, -1, self.figure) self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) # self.canvas.mpl_connect('pick_event', self.on_pick) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, allowselect=True) self.toolbar.Realize() self.seriesPlotInfo= None self.fontP = FontProperties() self.fontP.set_size('small') self.format = '-o' self.SetColor("WHITE") #self.canvas.gca().xaxis.set_major_locator() #init lists self.lines=[] self.axislist={} self.curveindex = -1 self.editseriesID = -1 self.editCurve =None self.cid=None self.canvas.draw() self._init_sizers() # def changeSelectionDT(self, sellist): # #list of DateTimes # print sellist # self.parent.record_service.select_points(datetime_list= sellist) # sellist = self.selFormat(sellist) # self.changeSelection(sellist) # print sellist # def selFormat(self, pairs): # #convert selectionlist from datetimes to true false # print len(pairs) # if len(pairs) ==0: # return [False] * len(self.editData.DataValues) # verts =[ (matplotlib.dates.date2num(x), y) for x,y in pairs] # p = path.Path(verts) # ind = p.contains_points(self.xys) # return ind def changeSelection(self, sellist ): #list of True False self.editPoint.set_color(['k' if x==0 else 'r' for x in sellist]) self.parent.record_service.select_points_tf(sellist) Publisher.sendMessage(("changeTableSelection"), sellist=sellist) self.canvas.draw() def onDateChanged(self, date, time): # print date # self.timeSeries.clear() date = datetime.datetime(date.Year, date.Month+1, date.Day, 0, 0, 0) ## print date if time == "start": self.startDate = date else: self.endDate = date self.timeSeries.axis.axes.set_xbound(self.startDate, self.endDate) self.canvas.draw() def set_date_bound(self, start, end): if start < self.overallStart: self.overallStart = start if end > self.currEnd: self.currEnd = end def OnShowLegend(self, isVisible): # print self.timeSeries.show_legend if isVisible: plt.subplots_adjust(bottom=.1+.1) self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), ncol=2, prop = self.fontP) else: plt.subplots_adjust(bottom=.1) self.timeSeries.legend_=None # self.timeSeries.plot(legend= not isVisible) self.canvas.draw() def OnPlotType(self, ptype): # self.timeSeries.clear() if ptype == "line": ls = '-' m='None' elif ptype == "point": ls='None' m='o' else: ls = '-' m='o' # print plt.setp(self.lines) # print(len(self.lines)) format = ls+m for line, i in zip(self.lines, range(len(self.lines))): if not (i == self.curveindex): plt.setp(line, linestyle = ls, marker = m) self.canvas.draw() def Clear(self): lines = [] for key, ax in self.axislist.items(): ax.clear() # self.stopEdit() def stopEdit(self): self.Clear() self.selectedlist = None self.editPoint =None self.lman= None self.canvas.mpl_disconnect(self.cid) self.cid=None self.xys = None self.curveindex = -1 self.editCurve =None # self.RefreshPlot() if self.seriesPlotInfo and self.seriesPlotInfo.IsPlotted(self.editseriesID): self.updatePlot() self.editseriesID = -1 def updateValues(self): # self.addEdit(self.editCursor, self.editSeries, self.editDataFilter) #clear current edit points and curve curraxis= self.axislist[self.editCurve.axisTitle] for l in curraxis.lines: if l.get_label() == self.editCurve.plotTitle: curraxis.lines.remove(l) self.editPoint.remove() #redraw editpoints and curve self.seriesPlotInfo.UpdateEditSeries() self.editCurve= self.seriesPlotInfo.GetEditSeriesInfo() self.drawEditPlot(self.editCurve) Publisher.sendMessage(("refreshTable"), e=None) # self.parent.parent.dataTable.Refresh() self.canvas.draw() def drawEditPlot(self, oneSeries): curraxis= self.axislist[oneSeries.axisTitle] self.lines[self.curveindex]=curraxis.plot_date([x[1] for x in oneSeries.dataTable], [x[0] for x in oneSeries.dataTable], "-", color=oneSeries.color, xdate = True, tz = None, label = oneSeries.plotTitle ) self.selectedlist = self.parent.record_service.get_filter_list() self.editPoint = curraxis.scatter([x[1] for x in oneSeries.dataTable], [x[0] for x in oneSeries.dataTable], s= 20, c=['k' if x==0 else 'r' for x in self.selectedlist]) self.xys = [(matplotlib.dates.date2num(x[1]), x[0]) for x in oneSeries.dataTable ] self.cid = self.canvas.mpl_connect('button_press_event', self.onpress) def SetColor( self, color): """Set figure and canvas colours to be the same.""" plt.gcf().set_facecolor( color ) plt.gcf().set_edgecolor( color ) self.canvas.SetBackgroundColour( color ) def Close(self): plt.close() def Plot(self, seriesPlotInfo): self.seriesPlotInfo= seriesPlotInfo self.updatePlot() def updatePlot(self): self.Clear() count = self.seriesPlotInfo.count() self.lines=[] # self.timeSeries=self.canvas.add_subplot(111) self.setUpYAxis() for oneSeries in self.seriesPlotInfo.GetSeriesInfo(): if oneSeries.seriesID == self.seriesPlotInfo.GetEditSeriesID(): self.curveindex = len(self.lines) self.lines.append("") self.editCurve= oneSeries self.drawEditPlot(oneSeries) else: curraxis= self.axislist[oneSeries.axisTitle] self.lines.append(curraxis.plot_date([x[1] for x in oneSeries.dataTable], [x[0] for x in oneSeries.dataTable], self.format, color=oneSeries.color, xdate = True, tz = None, label = oneSeries.plotTitle )) if count >1: # self.timeSeries.set_title("Multiple Series plotted") self.timeSeries.set_title("") plt.subplots_adjust(bottom=.1+.1) # self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), # ncol=2, prop = self.fontP) self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -0.15), ncol=2, prop = self.fontP) elif count == 0: self.timeSeries.set_title("") self.timeSeries.legend_=None else: self.timeSeries.set_title(oneSeries.plotTitle) plt.subplots_adjust(bottom=.1) self.timeSeries.legend_=None # self.timeSeries.set_xlim([0,1000]) self.timeSeries.set_xlabel("Date Time") self.canvas.draw() def setEdit(self, id): self.editseriesID = id if self.seriesPlotInfo and self.seriesPlotInfo.IsPlotted(self.editseriesID): self.editCurve = self.seriesPlotInfo.GetSeries(self.editseriesID) self.updatePlot() # print self.editCurve def setUpYAxis(self): self.axislist={} left = 0 right = 0 adj = .05 #loop through the list of curves and add an axis for each for oneSeries in self.seriesPlotInfo.GetSeriesInfo(): #test to see if the axis already exists if not oneSeries.axisTitle in self.axislist: self.axislist[oneSeries.axisTitle]=None for i, axis in zip(range(len(self.axislist)), self.axislist): if i %2==0: left = left+1 #add to the left(yaxis) if i==0: #if first plot use the orig axis newAxis =self.timeSeries else: newAxis= self.timeSeries.twinx() new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis newAxis.axis['left']= new_fixed_axis(loc = 'left', axes= newAxis, offset= (-30*left ,0)) newAxis.axis["left"].toggle(all = True) newAxis.axis["right"].toggle(all = False) plt.subplots_adjust(left=.10+(adj*(left-1))) else: right= right+1 #add to the right(y2axis) newAxis= self.timeSeries.twinx() new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis newAxis.axis['right']= new_fixed_axis(loc = 'right', axes= newAxis, offset= (60*(right-1) ,0)) newAxis.axis['right'].toggle(all=True) plt.subplots_adjust(right=.9-(adj*right)) newAxis.set_ylabel(axis) self.axislist[axis]=newAxis def callback(self, verts): seldatetimes= [matplotlib.dates.num2date(x[0]) for x in verts] #print seldatetimes # self.parent.record_service.select_points(datetime_list=seldatetimes) p = path.Path(verts) ind = p.contains_points(self.xys) self.changeSelection(ind) self.canvas.draw_idle() self.canvas.widgetlock.release(self.lasso) del self.lasso def onpress(self, event): if self.canvas.widgetlock.locked(): return if event.inaxes is None: return self.lasso = Lasso(event.inaxes, (event.xdata, event.ydata), self.callback) # acquire a lock on the widget drawing self.canvas.widgetlock(self.lasso) def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class CTRL_Graphique(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1, style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER) self.dictParametres = None self.afficher_valeurs = False # Init canvas self.figure = matplotlib.pyplot.figure() self.canvas = Canvas(self, -1, self.figure) self.canvas.SetMinSize((20, 20)) self.SetColor((255, 255, 255)) # Layout sizer_canvas = wx.BoxSizer(wx.VERTICAL) sizer_canvas.Add(self.canvas, 1, wx.EXPAND, 0) self.SetSizer(sizer_canvas) self.Layout() def OnBoutonZoom(self, event): import DLG_Zoom_graphe dlg = DLG_Zoom_graphe.Dialog(self, figure=self.figure) dlg.ShowModal() dlg.Destroy() def OnBoutonOptions(self, event): # Création du menu contextuel menuPop = UTILS_Adaptations.Menu() item = wx.MenuItem(menuPop, 10, _(u"Afficher les valeurs"), _(u"Afficher les valeurs"), wx.ITEM_CHECK) menuPop.AppendItem(item) self.Bind(wx.EVT_MENU, self.On_afficher_valeurs, id=10) if self.afficher_valeurs == True: item.Check(True) self.PopupMenu(menuPop) menuPop.Destroy() def On_afficher_valeurs(self, event): self.afficher_valeurs = not self.afficher_valeurs self.MAJ() def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def ConvertCouleur(self, couleur=None): return [c / 255. for c in couleur] def SetParametres(self, dictParametres=None): self.dictParametres = dictParametres def MAJ(self): self.figure.clear() if self.dictParametres == None: wx.CallAfter(self.SendSizeEvent) return if self.dictParametres[ "IDmodele"] == "repartition_categories_debit_tresorerie": self.Graphe_repartition_categories(typeCategorie="debit", typeDonnees="tresorerie") if self.dictParametres[ "IDmodele"] == "repartition_categories_credit_tresorerie": self.Graphe_repartition_categories(typeCategorie="credit", typeDonnees="tresorerie") if self.dictParametres[ "IDmodele"] == "repartition_categories_debit_budgetaires": self.Graphe_repartition_categories(typeCategorie="debit", typeDonnees="budgetaires") if self.dictParametres[ "IDmodele"] == "repartition_categories_credit_budgetaires": self.Graphe_repartition_categories(typeCategorie="credit", typeDonnees="budgetaires") if self.dictParametres[ "IDmodele"] == "repartition_categories_debit_tresorerie_budgetaires": self.Graphe_repartition_categories( typeCategorie="debit", typeDonnees="tresorerie+budgetaires") if self.dictParametres[ "IDmodele"] == "repartition_categories_credit_tresorerie_budgetaires": self.Graphe_repartition_categories( typeCategorie="credit", typeDonnees="tresorerie+budgetaires") if self.dictParametres["IDmodele"] == "tiers_debit": self.Graphe_tiers(typeCategorie="debit") if self.dictParametres["IDmodele"] == "tiers_credit": self.Graphe_tiers(typeCategorie="credit") self.Layout() def Graphe_repartition_categories(self, typeCategorie="", typeDonnees="tresorerie+budgetaires"): # Récupération des données conditions = [] if self.dictParametres["date_debut"] != None: conditions.append("date_budget>='%s'" % self.dictParametres["date_debut"]) conditions.append("date_budget<='%s'" % self.dictParametres["date_fin"]) if self.dictParametres["IDanalytique"] != None: conditions.append("IDanalytique=%d" % self.dictParametres["IDanalytique"]) if len(conditions) > 0: ConditionsStr = "AND " + " AND ".join(conditions) else: ConditionsStr = "" DB = GestionDB.DB() dictDonnees = {} if "budgetaires" in typeDonnees: req = """SELECT compta_operations_budgetaires.IDcategorie, compta_categories.nom, SUM(compta_operations_budgetaires.montant) FROM compta_operations_budgetaires LEFT JOIN compta_categories ON compta_categories.IDcategorie = compta_operations_budgetaires.IDcategorie WHERE compta_operations_budgetaires.type='%s' %s GROUP BY compta_operations_budgetaires.IDcategorie ;""" % (typeCategorie, ConditionsStr) DB.ExecuterReq(req) listeDonnees = DB.ResultatReq() for IDcategorie, nom, montant in listeDonnees: if dictDonnees.has_key(IDcategorie) == False: dictDonnees[IDcategorie] = {"nom": nom, "montant": 0.0} dictDonnees[IDcategorie]["montant"] += montant if "tresorerie" in typeDonnees: req = """SELECT compta_ventilation.IDcategorie, compta_categories.nom, SUM(compta_ventilation.montant) FROM compta_ventilation LEFT JOIN compta_categories ON compta_categories.IDcategorie = compta_ventilation.IDcategorie WHERE type='%s' %s GROUP BY compta_ventilation.IDcategorie ;""" % (typeCategorie, ConditionsStr) DB.ExecuterReq(req) listeDonnees = DB.ResultatReq() for IDcategorie, nom, montant in listeDonnees: if dictDonnees.has_key(IDcategorie) == False: dictDonnees[IDcategorie] = {"nom": nom, "montant": 0.0} dictDonnees[IDcategorie]["montant"] += montant DB.Close() if len(dictDonnees) == 0: return listeValeurs = [] listeLabels = [] listeCouleurs = [] montantTotal = 0.0 for IDcategorie, dictTemp in dictDonnees.iteritems(): montantTotal += dictTemp["montant"] index = 1 for IDcategorie, dictTemp in dictDonnees.iteritems(): listeValeurs.append(dictTemp["montant"]) label = dictTemp["nom"] if self.afficher_valeurs == True: label += u"\n%.2f %s" % (float(montant), SYMBOLE) listeLabels.append(label) couleur = 1.0 * montant / montantTotal couleur = matplotlib.cm.hsv(index * 0.1) listeCouleurs.append(couleur) index += 1 # Création du graphique ax = self.figure.add_subplot(111) cam = ax.pie(listeValeurs, labels=listeLabels, colors=listeCouleurs, autopct='%1.1f%%', shadow=False) title = ax.set_title( self.dictParametres["nom"], weight="bold", horizontalalignment='center') #, position=(0.5, 0.97)) matplotlib.pyplot.setp(title, rotation=0, fontsize=11) ax.set_aspect(1) labels, labelsPourcent = cam[1], cam[2] matplotlib.pyplot.setp(labels, rotation=0, fontsize=11) matplotlib.pyplot.setp(labelsPourcent, rotation=0, fontsize=9) # Finalisation ax.autoscale_view('tight') ax.figure.canvas.draw() wx.CallAfter(self.SendSizeEvent) def Graphe_tiers(self, typeCategorie=""): # Récupération des données conditions = [] if self.dictParametres["date_debut"] != None: conditions.append("date_budget>='%s'" % self.dictParametres["date_debut"]) conditions.append("date_budget<='%s'" % self.dictParametres["date_fin"]) if self.dictParametres["IDanalytique"] != None: conditions.append("IDanalytique=%d" % self.dictParametres["IDanalytique"]) if len(conditions) > 0: ConditionsStr = "AND " + " AND ".join(conditions) else: ConditionsStr = "" DB = GestionDB.DB() req = """SELECT compta_tiers.IDtiers, compta_tiers.nom, SUM(compta_ventilation.montant) FROM compta_tiers LEFT JOIN compta_operations ON compta_operations.IDtiers = compta_tiers.IDtiers LEFT JOIN compta_ventilation ON compta_ventilation.IDoperation = compta_operations.IDoperation WHERE type='%s' %s GROUP BY compta_tiers.IDtiers ;""" % (typeCategorie, ConditionsStr) DB.ExecuterReq(req) listeDonnees = DB.ResultatReq() DB.Close() if len(listeDonnees) == 0: return listeValeurs = [] listeLabels = [] listeCouleurs = [] for IDtiers, nom, montant in listeDonnees: listeValeurs.append(montant) listeLabels.append(nom) listeIndex = np.arange(len(listeLabels)) bar_height = 0.2 opacity = 0.4 ax = self.figure.add_subplot(111) barres = ax.barh(listeIndex, listeValeurs, height=bar_height, align='center', alpha=opacity) # Formatage des montants sur x majorFormatter = FormatStrFormatter(u"%d " + SYMBOLE) ax.xaxis.set_major_formatter(majorFormatter) # Affichage des labels x ax.set_yticks(listeIndex) ax.set_yticklabels(listeLabels) def autolabel(rects): # attach some text labels for rect in rects: width = rect.get_width() ax.text(width + 10, rect.get_y() + rect.get_height() / 2., u"%.2f %s" % (int(width), SYMBOLE), ha='left', va='center', fontsize=8, color="grey") if self.afficher_valeurs == True: autolabel(barres) # Recherche la largeur de texte max largeurMax = 0 for label in listeLabels: if len(label) > largeurMax: largeurMax = len(label) # Espaces autour du graph margeGauche = 0.1 + largeurMax * 0.008 self.figure.subplots_adjust(left=margeGauche, right=None, wspace=None, hspace=None) # Finalisation ax.autoscale_view('tight') ## ax.grid(True) ax.figure.canvas.draw() wx.CallAfter(self.SendSizeEvent) return # Récupération des données from Ol import OL_Suivi_budget analyse = OL_Suivi_budget.Analyse(self.dictBudget) listeCategories = analyse.GetValeurs() listeRealise = [] listeBudgete = [] listeLabels = [] for dictCategorie in listeCategories: listeRealise.append(dictCategorie["realise"]) listeBudgete.append(dictCategorie["plafond"]) listeLabels.append(dictCategorie["nomCategorie"]) ## if dictCategorie["typeCategorie"] == "debit" : ## solde = plafond - realise ## else : ## solde = realise - plafond ## # TEST ## listeIndex = np.arange(len(listeLabels)) ## bar_width = 0.2 ## opacity = 0.4 ## ## ax = self.figure.add_subplot(111) ## barres = ax.bar(listeIndex, listeRealise, width=bar_width, alpha=opacity, color="g", label=_(u"Réel")) ## barres = ax.bar(listeIndex + bar_width, listeBudgete, width=bar_width, alpha=opacity, color="b", label=_(u"Budgété")) ## ## # Formatage des montants sur y ## majorFormatter = FormatStrFormatter(SYMBOLE + u" %d") ## ax.yaxis.set_major_formatter(majorFormatter) ## ## # Affichage des labels x ## ax.set_xticks(listeIndex + bar_width) ## ax.set_xticklabels(listeLabels) ## ## labels = ax.get_xticklabels() ## setp(labels, rotation=45) ## ## # Légende ## props = matplotlib.font_manager.FontProperties(size=10) ## leg = ax.legend(loc='best', shadow=False, fancybox=True, prop=props) ## leg.get_frame().set_alpha(0.5) ## ## # Espaces autour du graph ## self.figure.subplots_adjust(left=0.12, bottom=0.40, right=None, wspace=None, hspace=None) # TEST listeIndex = np.arange(len(listeLabels)) bar_height = 0.2 opacity = 0.4 ax = self.figure.add_subplot(111) barresRealise = ax.barh(listeIndex, listeRealise, height=bar_height, alpha=opacity, color="g", label=_(u"Réel")) barresBudgete = ax.barh(listeIndex + bar_height, listeBudgete, height=bar_height, alpha=opacity, color="b", label=_(u"Budgété")) # Formatage des montants sur x majorFormatter = FormatStrFormatter(u"%d " + SYMBOLE) ax.xaxis.set_major_formatter(majorFormatter) # Affichage des labels x ax.set_yticks(listeIndex + bar_height) ax.set_yticklabels(listeLabels) def autolabel(rects): # attach some text labels for rect in rects: width = rect.get_width() ax.text(width + 20, rect.get_y() + rect.get_height() / 2., u"%.2f %s" % (int(width), SYMBOLE), ha='left', va='center', fontsize=8, color="grey") if self.afficher_valeurs == True: autolabel(barresRealise) autolabel(barresBudgete) # Recherche la largeur de texte max largeurMax = 0 for label in listeLabels: if len(label) > largeurMax: largeurMax = len(label) # Espaces autour du graph margeGauche = 0.1 + largeurMax * 0.008 self.figure.subplots_adjust(left=margeGauche, right=None, wspace=None, hspace=None) # Légende props = matplotlib.font_manager.FontProperties(size=10) leg = ax.legend(loc='best', shadow=False, fancybox=True, prop=props) leg.get_frame().set_alpha(0.5) # Finalisation ax.autoscale_view('tight') ax.grid(True) ax.figure.canvas.draw() wx.CallAfter(self.SendSizeEvent) return
class plotProb(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def Clear(self): self.plot.clear() def _init_ctrls(self, prnt): #matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, prnt, -1) self.figure = matplotlib.figure.Figure() self.plot = self.figure.add_subplot(111) self.plot.axis([0, 1, 0, 1]) # self.plot.plot([], []) self.plot.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, self.figure) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas) self.toolbar.Realize() #self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS)) #self.canvas.SetScrollbar(wx.HORIZONTAL, 0,5, 1000) self.SetColor("WHITE") self.canvas.SetFont( wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.fontP = FontProperties() self.fontP.set_size('small') self.canvas.draw() self._init_sizers() def OnPlotType(self, ptype): # self.timeSeries.clear() if ptype == "line": ls = '-' m = 'None' elif ptype == "point": ls = 'None' m = 's' else: ls = '-' m = 's' # print plt.setp(self.lines) # print(len(self.lines)) format = ls + m for line in self.lines: plt.setp(line, linestyle=ls, marker=m) self.canvas.draw() def OnShowLegend(self, isVisible): # print self.timeSeries.show_legend if isVisible: plt.subplots_adjust(bottom=.1 + .1) self.plot.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), ncol=2, prop=self.fontP) else: plt.subplots_adjust(bottom=.1) self.plot.legend_ = None # self.timeSeries.plot(legend= not isVisible) self.canvas.draw() def Plot(self, seriesPlotInfo): self.seriesPlotInfo = seriesPlotInfo self.updatePlot() def updatePlot(self): self.Clear() count = self.seriesPlotInfo.count() self.lines = [] self.plot = self.figure.add_subplot(111) for oneSeries in self.seriesPlotInfo.GetSeriesInfo(): self.plot.set_xlabel("Cumulative Frequency < Stated Value %") if count > 1: self.plot.set_ylabel("\n".join( textwrap.wrap(oneSeries.axisTitle, 50))) self.plot.set_title("") else: self.plot.set_ylabel("\n".join( textwrap.wrap(oneSeries.axisTitle, 50))) self.plot.set_title("\n".join( textwrap.wrap(oneSeries.plotTitle, 55))) self.lines.append( self.plot.plot(oneSeries.Probability.Xaxis, oneSeries.Probability.Yaxis, 'bs', color=oneSeries.color, label=oneSeries.plotTitle)) self.setXaxis() if count > 1: plt.subplots_adjust(bottom=.1 + .1) self.plot.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), ncol=2, prop=self.fontP) else: plt.subplots_adjust(bottom=.1) self.plot.legend_ = None self.canvas.draw() def addPlot(self, cursor, series, Filter): # self.cursor = Values[0] self.cursor = cursor self.cursor.execute("SELECT DataValue FROM DataValues" + Filter) self.dataValues = [x[0] for x in self.cursor.fetchall()] # self.Series= Values[1] self.Series = series self.plot.clear() length = len(self.dataValues) self.Yaxis = sorted(self.dataValues) self.Xaxis = [] for it in range(0, length): #curValue = datavalues[it] curFreq = self.CalcualteProbabilityFreq(it + 1, length) curX = self.CalculateProbabilityXPosition(curFreq) #self.Yaxis.append(curValue) self.Xaxis.append(curX) #print self.Xaxis # print self.Yaxis self.plot.clear() x = range(len(self.Xaxis)) self.plot.set_xlabel("Cumulative Frequency < Stated Value %") self.plot.set_ylabel("\n".join( textwrap.wrap( self.Series.variable_name + "(" + self.Series.variable_units_name + ")", 50))) self.plot.set_title("\n".join( textwrap.wrap( self.Series.site_name + " " + self.Series.variable_name, 55))) self.plot = self.figure.add_subplot(111) self.lines = self.plot.plot(self.Xaxis, self.Yaxis, 'bs') self.setXaxis() self.canvas.draw() def setXaxis(self): self.plot.set_xticklabels([ "0.01", "0.02", "0.02", "1", "2", "5", "10", "20", "30", "40", "50", "60", "70", "80", "90", "95", "98", "99", "99.9", "99.98", "99.99" ]) self.plot.set_xticks([ -3.892, -3.5, -3.095, -2.323, -2.055, -1.645, -1.282, -0.842, -0.542, -0.254, 0, 0.254, 0.542, 0.842, 1.282, 1.645, 2.055, 2.323, 3.095, 3.5, 3.892 ]) self.plot.set_xbound(-4, 4) def SetColor(self, color): """Set figure and canvas colours to be the same.""" self.figure.set_facecolor(color) self.figure.set_edgecolor(color) self.canvas.SetBackgroundColour(color) def CalculateProbabilityXPosition(self, freq): try: return round(4.91 * ((freq**.14) - (1.00 - freq)**.14), 3) except: print "An error occurred while calculating the X-Position for a point in the prob plot" pass def CalcualteProbabilityFreq(self, rank, numRows): try: return round((rank - .0375) / (numRows + 1 - (2 * 0.375)), 3) except: print "An error occured while calculating the frequency for a point in the prob plot" pass def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class PlotBox(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def _init_ctrls(self, prnt): # matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, prnt, -1) Publisher.subscribe(self.monthly, ("box.Monthly")) Publisher.subscribe(self.yearly, ("box.Yearly")) Publisher.subscribe(self.seasonaly, ("box.Seasonal")) Publisher.subscribe(self.overall, ("box.Overall")) self.figure = Figure() # self.figure = plt.figure() plot = self.figure.add_subplot(111) #self.plot.axis([0, 1, 0, 1]) # plot.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, self.figure) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, True) self.toolbar.Realize() self.figure.tight_layout() self.setColor("WHITE") self.canvas.SetFont( wx.Font(15, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.canvas.draw() self._init_sizers() def clear(self): self.figure.clear() def close(self): self.figure.clf() # plt.close('all') def gridSize(self, cells): rows = 1 cols = 1 while rows * cols < cells: if rows == cols: cols = cols + 1 else: rows = rows + 1 return rows, cols def textSize(self, cells): wrap = 40 wrap = wrap - (cells * 3) text = 20 - cells return wrap, text def Plot(self, seriesPlotInfo): self.seriesPlotInfo = seriesPlotInfo self.updatePlot() def updatePlot(self): self.clear() rows, cols = self.gridSize(self.seriesPlotInfo.count()) # self.figure, self.axes = plt.subplots(nrows=rows, ncols=cols) i = 1 for oneSeries in self.seriesPlotInfo.getAllSeries(): if len(oneSeries.dataTable) > 0: self._createPlot(oneSeries, rows, cols, i) i += 1 # self.figure.tight_layout() self.canvas.draw() def _createPlot(self, oneSeries, rows, cols, index): ax = self.figure.add_subplot(repr(rows) + repr(cols) + repr(index)) med = oneSeries.BoxWhisker.currinterval.medians ci = oneSeries.BoxWhisker.currinterval.confint mean = oneSeries.BoxWhisker.currinterval.means cl = oneSeries.BoxWhisker.currinterval.conflimit # Plot Means confidence level for x in range(len(mean)): ax.vlines(x + 1, cl[x][0], cl[x][1], color='r', linestyle="solid") # Plot Mean ax.scatter([range(1, len(mean) + 1)], mean, marker='o', c='r', s=10) # Plot Median ax.scatter([range(1, len(med) + 1)], med, marker='s', c="k", s=10) # bp = onSeries.dataTable.boxplot( bp = oneSeries.dataTable[ oneSeries.dataTable["DataValue"] != oneSeries.noDataValue].boxplot( column="DataValue", ax=ax, by=oneSeries.BoxWhisker.currinterval.groupby, rot=35, notch=True, sym="-s", conf_intervals=ci, return_type='dict', grid=False) # Set Colors of the Box Whisker plot try: plt.setp(bp['DataValue']['whiskers'], color='k', linestyle='-') plt.setp(bp['DataValue']['medians'], color='k', linestyle='-') plt.setp(bp['DataValue']['boxes'], color='GREY', linestyle='-') plt.setp(bp['DataValue']['caps'], color='k') plt.setp(bp['DataValue']['fliers'], markersize=3.5, color=oneSeries.color) except: plt.setp(bp['whiskers'], color='k', linestyle='-') plt.setp(bp['medians'], color='k', linestyle='-') plt.setp(bp['boxes'], color='GREY', linestyle='-') plt.setp(bp['caps'], color='k') plt.setp(bp['fliers'], markersize=3.5, color=oneSeries.color) #Labels ax.set_xticklabels( [x for x in oneSeries.BoxWhisker.currinterval.xlabels]) # set the text of the first few minor ticks created by pandas.plot # remove the minor xtick labels set by pandas.plot ax.set_xticklabels([], minor=True) # turn the minor ticks created by pandas.plot off # plt.minorticks_off() wrap, text = self.textSize(self.seriesPlotInfo.count()) self.canvas.SetFont( wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) ax.set_xlabel("\n".join( textwrap.wrap(oneSeries.BoxWhisker.currinterval.title, wrap))) ax.set_ylabel("\n".join( textwrap.wrap( oneSeries.variableName + "\n (" + oneSeries.variableUnits + ")", wrap))) self.figure.suptitle("") ax.set_title("\n".join(textwrap.wrap(oneSeries.siteName, wrap))) def setColor(self, color): # """Set figure and canvas colours to be the same.""" self.figure.set_facecolor(color) self.figure.set_edgecolor(color) self.canvas.SetBackgroundColour(color) def monthly(self, str): # print "monthly" self.seriesPlotInfo.setBoxInterval("Month") self.updatePlot() def seasonaly(self, str): # print"seasonal" self.seriesPlotInfo.setBoxInterval("Season") self.updatePlot() def yearly(self, str): # print "yearly" self.seriesPlotInfo.setBoxInterval("Year") self.updatePlot() def overall(self, str): # print "overall" self.seriesPlotInfo.setBoxInterval("Overall") self.updatePlot() def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class plotHist(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def _init_ctrls(self, prnt): # matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, prnt, -1) self.figure = Figure() plot = self.figure.add_subplot(111) plot.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, self.figure) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, True) self.toolbar.Realize() self.figure.tight_layout() self.setColor("WHITE") self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.canvas.draw() self._init_sizers() self.bins = 50 def changeNumOfBins(self, bins): self.bins = bins self.updatePlot() def clear(self): self.figure.clear() # plt.clear() def gridSize(self, cells): rows = 1 cols = 1 while rows * cols < cells: if rows == cols: cols = cols + 1 else: rows = rows + 1 return rows, cols def textSize(self, cells): wrap = 50 wrap = wrap - (cells * 3) text = 20 - cells return wrap, text def Plot(self, seriesPlotInfo): self.seriesPlotInfo = seriesPlotInfo self.updatePlot() def updatePlot(self): self.clear() rows, cols = self.gridSize(self.seriesPlotInfo.count()) logger.debug("Rows: %s, cols: %s" % (rows,cols)) i = 1 for oneSeries in self.seriesPlotInfo.getAllSeries(): if len(oneSeries.dataTable) > 0: self._createPlot(oneSeries, rows, cols, i) i += 1 #self.figure.tight_layout() self.canvas.draw() def _createPlot(self, oneSeries, rows, cols, index): ax = self.figure.add_subplot(repr(rows) + repr(cols) + repr(index)) logger.debug("HISTOGRAM: %s"% ax) # oneSeries.filteredData.hist(ax= ax, color='k', alpha=0.5, bins=50) his = oneSeries.dataTable.hist(column="DataValue", ax=ax, bins=self.bins, facecolor=oneSeries.color, label=oneSeries.siteName + " " + oneSeries.variableName, grid=False) wrap, text = self.textSize(self.seriesPlotInfo.count()) ax.set_xlabel("\n".join(textwrap.wrap(oneSeries.variableName, wrap))) ax.set_ylabel("Number of Observations") self.canvas.SetFont(wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) ax.set_title("\n".join(textwrap.wrap(oneSeries.siteName, wrap))) def setColor(self, color): """Set figure and canvas colours to be the same.""" self.figure.set_facecolor(color) self.figure.set_edgecolor(color) self.canvas.SetBackgroundColour(color) def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class PlotPanel(wx.Panel): ''' Principal Component Analysis (PCA) plot (PCA1 against PCA2) GUI ''' def __init__(self, parent, id=-1, dpi=None, **kwargs): wx.Panel.__init__(self, parent, id=id, **kwargs) self.figure = Figure(dpi=dpi, figsize=(2, 2)) self.canvas = Canvas(self, -1, self.figure) self.figure.set_facecolor((1, 1, 1)) self.figure.set_edgecolor((1, 1, 1)) self.canvas.SetBackgroundColour('white') self.subplot = self.figure.add_subplot(111) self.plot_scores = None self.class_masks = None self.class_names = None self.Loadings = None self.object_opacity = None self.object_accuracies = None self.leg = None self.maskedPCA1 = None self.maskedPCA2 = None self.axes = None # If the script is loaded from ClassifierGUI, load the classification weaklearners try: self.classifier = classifier self.classifier_rules = classifier.algorithm.weak_learners except: self.classifier_rules = [('None', 0, np.array([0, 0]))] self.chMap = p.image_channel_colors self.toolbar = NavigationToolbar2Wx(self.canvas) self.toolbar.Realize() POSITION_OF_CONFIGURE_SUBPLOTS_BTN = 6 self.toolbar.DeleteToolByPos(POSITION_OF_CONFIGURE_SUBPLOTS_BTN) self.statusBar = wx.StatusBar(self, -1) self.statusBar.SetFieldsCount(1) self.motion_event_active = False self.canvas.mpl_connect('motion_notify_event', self.update_status_bar) self.canvas.mpl_connect('button_press_event', self.on_open_image) self.hide_legend_btn = wx.Button(self, -1, " Hide legend ") wx.EVT_BUTTON(self.hide_legend_btn, -1, self.hide_show_legend) self.hide_legend = True tools_sizer = wx.BoxSizer(wx.HORIZONTAL) tools_sizer.Add(self.toolbar, 0, wx.RIGHT | wx.EXPAND) tools_sizer.AddSpacer(5) tools_sizer.Add(self.hide_legend_btn, 0, wx.LEFT | wx.EXPAND) tools_sizer.AddSpacer(5) tools_sizer.Add(self.statusBar, 0, wx.LEFT | wx.EXPAND) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.EXPAND) sizer.Add(tools_sizer, 0, wx.EXPAND) self.SetSizer(sizer) def set_plot_type(self, plot_scores): ''' Set the plot type (Scores. Loadings) for each notebook page ''' self.plot_scores = plot_scores def set_colormap(self, class_array): ''' Set the colormap based on the number of different classes to plot ''' self.colormap = cm.get_cmap('hsv') num_colors = len(class_array) class_value = np.array(list(range(1, (num_colors + 2))), dtype='float') / num_colors color_set = np.array(self.colormap(class_value)) return color_set def on_open_image(self, event): if event.button == 2 and self.plot_scores == "Scores" and event.inaxes: self.open_image() def open_image(self): ''' Open the image of the selected cell in the Scores plot ''' imViewer = ShowImage(self.actual_key[:-1], self.chMap[:], parent=self.classifier, brightness=1.0, contrast=None) imViewer.imagePanel.SelectPoint(db.GetObjectCoords(self.actual_key)) def hide_show_legend(self, event): ''' Hide or show the legend on the canvas by pressing the button ''' if self.leg is not None: if self.hide_legend: self.leg.set_visible(False) self.figure.canvas.draw() self.hide_legend = False self.hide_legend_btn.SetLabel(label='Show legend') else: self.leg.set_visible(True) self.figure.canvas.draw() self.hide_legend = True self.hide_legend_btn.SetLabel(label=' Hide legend ') def update_status_bar(self, event): ''' Show the key for the nearest object (measured as the Euclidean distance) to the mouse pointer in the plot (scores pdimensredux.PlotPanel.__init__dimensredux.PlotPanel.__init__lot) or the nearest feature (loadings plot) ''' if event.inaxes and self.motion_event_active: x, y = event.xdata, event.ydata if self.plot_scores == "Scores": dist = np.hypot((x - self.Scores[:, 0]), (y - self.Scores[:, 1])) object_dict_key = np.where(dist == np.amin(dist)) xy_key = int(object_dict_key[0][0]) if self.object_accuracies: errorData = ', CA = %0.1f%%' % ( (1 - self.object_opacity[xy_key]) * 100.0) else: errorData = '' self.statusBar.SetStatusText( ("Object key = " + str(self.data_dic[xy_key]) + errorData), 0) self.actual_key = self.data_dic[xy_key] elif self.plot_scores == "Loadings": dist = np.hypot((x - self.Loadings[0]), (y - self.Loadings[1])) feature_dict_key = np.where(dist == np.amin(dist)) xy_key = int(feature_dict_key[0]) feat_text = self.features_dic[xy_key].split('_') self.statusBar.SetStatusText(('_'.join(feat_text[1:])), 0) def plot_pca(self): ''' Plot the Principal Component Analysis scores (cells) and loadings (features) along with the percentage of data variance the scores represent ''' self.subplot.clear() # Only obtain class data from the database if no data is available yet if self.class_masks is None or self.class_names is None: self.class_masks, self.class_names = self.create_class_masks() self.data = np.nan_to_num(self.data) # Eliminate NaNs # Calculate PCA-SVD and mask data with class information centered = self.mean_center(self.data) U, S, self.Loadings, explained_variance = self.pca_svd( centered, 100, True) self.Scores = np.array(U[:, 0:2]) self.maskedPCA1, self.maskedPCA2 = self.mask_data( len(self.class_names), self.class_masks, self.Scores) self.axes = explained_variance[0:2] self.color_set = self.set_colormap(self.class_names) # Plot the first two PCAs' Scores in the Scores canvas if self.plot_scores == "Scores": handles = [] labels = [] # Determine the different opacities for the objects. This is set to 1 if no opacities have been specified. if self.object_opacity is None: self.object_opacity = np.ones([self.maskedPCA1.shape[0], 1]) self.object_accuracies = False elif self.object_accuracies is None: self.object_accuracies = True opacities = np.unique(self.object_opacity) nOpacity = len(opacities) # For each class and opacity combination plot the corresponding objects for i in range(len(self.class_names)): cell_count = np.shape(np.nonzero(self.maskedPCA1[:, i])) for j in range(nOpacity): showObjects = np.where(self.object_opacity == opacities[j]) subHandle = self.subplot.scatter( self.maskedPCA1[showObjects[0], i], self.maskedPCA2[showObjects[0], i], 8, c=self.color_set[i, :], linewidth="0.25", alpha=0.25 + 0.75 * opacities[j]) # The highest opacity objects are added to the legend if opacities[j] == np.max(opacities): handles.append(subHandle) labels.append(self.class_names[i] + ': ' + str(cell_count[1])) # Construct the legend and make up the rest of the plot self.leg = self.subplot.legend(handles, labels, loc=4, fancybox=True, handlelength=1) self.leg.get_frame().set_alpha(0.25) x_var = round(((1 - self.axes[0]) * 100), 2) y_var = round(((self.axes[0] - self.axes[1]) * 100), 2) x_axe_var = 'Explained variance: ' + str(x_var) + '%' y_axe_var = 'Explained variance: ' + str(y_var) + '%' self.subplot.set_xlabel(x_axe_var, fontsize=12) self.subplot.set_ylabel(y_axe_var, fontsize=12) self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1) self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1) self.figure.canvas.draw() elif self.plot_scores == "Loadings": # Plot the first two PCAs' Loadings in the Loading canvas weaklearners_mask = np.zeros((np.shape(self.Loadings[0]))) for key in list(self.features_dic.keys()): for value in self.classifier_rules: if value[0] == self.features_dic[key]: weaklearners_mask[key] += 1 scatter_mask = weaklearners_mask + 1 colors_mask = [] size_mask = [] for i in range(len(scatter_mask)): colors_mask.append(COLORS[int(scatter_mask[i])]) size_mask.append((int(scatter_mask[i])**2) * 5) self.subplot.scatter(self.Loadings[0], self.Loadings[1], c=colors_mask, s=size_mask, linewidth="0.5", marker='o') self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1) self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1) self.figure.canvas.draw() self.motion_event_active = True def plot_tsne(self): ''' Plot the t-Distributed Stochastic Neighbor Embedding (t-SNE) distribution of the data ''' self.subplot.clear() self.data = np.nan_to_num(self.data) # Eliminate NaNs centered = self.mean_center(self.data) standardized = self.standardization(centered) # Calculate t-SNE of the data and mask it (python t-SNE version if Intel IPP is not installed) try: from calc_tsne import calc_tsne U = calc_tsne(standardized, 2, 50, 20.0) except: logging.warning( '''Could not use fast t-SNE. You may need to install the Intel Integrated Performance Libraries. Will use normal t-SNE instead.''' ) try: from .tsne import tsne U = tsne(standardized, 2, 50, 20.0) except: logging.error( '''Both t-SNE versions failed. Your dataset may be too large for t-SNE to handle. Will not plot t-SNE results.''' ) return self.Scores = U[:, 0:2] if self.class_masks is None or self.class_names is None: self.class_masks, self.class_names = self.create_class_masks() self.masked_X, self.masked_Y = self.mask_data(len(self.class_names), self.class_masks, self.Scores) # Plot the masked t-SNE results in the Scores canvas self.color_set = self.set_colormap(self.class_names) handles = [] labels = [] # Determine the different opacities for the objects. This is set to 1 if no opacities have been specified. if self.object_opacity is None: self.object_opacity = np.ones([self.masked_X.shape[0], 1]) self.object_accuracies = False elif self.object_accuracies is None: self.object_accuracies = True opacities = np.unique(self.object_opacity) nOpacity = len(opacities) # For each class and opacity combination plot the corresponding objects for i in range(len(self.class_names)): cell_count = np.shape(np.nonzero(self.masked_X[:, i])) for j in range(nOpacity): showObjects = np.where(self.object_opacity == opacities[j]) subHandle = self.subplot.scatter(self.masked_X[showObjects, i], self.masked_Y[showObjects, i], 8, c=self.color_set[i, :], linewidth="0.25", alpha=0.25 + 0.75 * opacities[j]) # The highest opacity objects are added to the legend if opacities[j] == np.max(opacities): handles.append(subHandle) labels.append(self.class_names[i] + ': ' + str(cell_count[1])) self.leg = self.subplot.legend(handles, labels, loc=4, fancybox=True, handlelength=1) self.leg.get_frame().set_alpha(0.25) self.subplot.axhline(0, -100000, 100000, c='k', lw=0.1) self.subplot.axvline(0, -100000, 100000, c='k', lw=0.1) self.figure.canvas.draw() self.motion_event_active = True def clean_canvas(self): self.subplot.clear() def standardization(self, centered_data): ''' Standardize data prior to calculation in order to improve the performance over measurements with large differences in their value ranges ''' standards = np.std(centered_data, 0) for value in standards: if value == 0: logging.error( 'Division by zero, cannot proceed (an object measurements in your dataset has 0 standard deviation, please check your database)' ) standardized_data = centered_data / standards return standardized_data def mean_center(self, raw_data): ''' Centering the measurements data around the mean is necessary prior to calculation ''' row, col = np.shape(raw_data) centered_data = raw_data mean_data = raw_data.mean(axis=0) for i in range(row): centered_data[i] -= mean_data centered_data = centered_data[:, np.var(centered_data, axis=0) != 0] return centered_data def pca_svd(self, data, PCs=100, standardize=True): ''' Calculate the eigenvectors of the data array using SVD (Singular Value Decomposition) method ''' row, col = np.shape(data) if PCs > col: PCs = col if standardize: data = self.standardization(data) import time U, S, V = np.linalg.svd(data, full_matrices=False) # Calculate the percentage of data measurements variance each PCA explains E = data.copy() row, col = np.shape(E) explained_variance = np.zeros((PCs)) total_explained_variance = 0 init_total_error = np.sum(np.square(E)) for k in range(PCs): T = (U[:, k].reshape(row, 1)) * S[k] V_t = np.transpose(V) P = V_t[:, k].reshape(col, 1) E = E - T * (np.transpose(P)) total_error = np.sum(np.square(E)) total_object_residual_variance = (total_error / init_total_error) explained_variance[ k] = 1 - total_object_residual_variance - total_explained_variance total_explained_variance += explained_variance[k] return U, S, V, explained_variance def create_class_masks(self): ''' Create class masks for the data based on the classification data from CPAnalyst. This is done in order to print Scoring plots with points in different colors for each class ''' class_data = db.execute('SELECT class, class_number FROM %s ' \ 'ORDER BY %s ASC, %s ASC' % (p.class_table, \ p.image_id, p.object_id)) class_name_number = set([result for result in class_data]) class_name_number = sorted(class_name_number, key=itemgetter(1)) class_names = [item[0] for item in class_name_number] class_number = np.array([result[1] for result in class_data]) num_classes = len(class_names) # In case class numbers are missing in the range (for instance some classes # that were available to train objects in have no objects classified in them) # the class numbers should be remapped class_ids = [item[1] for item in class_name_number] max_id = np.max(class_ids) if len(class_ids) != max_id: logging.info( 'Found non-consecutive class IDs. Remapping class IDs.') missing_ids = np.flipud( np.setdiff1d(np.arange(max_id) + 1, class_ids)) while missing_ids.shape != (0, ): indices = class_number >= missing_ids[0] class_number[indices] -= 1 missing_ids = np.delete(missing_ids, 0) class_masks = np.zeros((len(class_number), num_classes)) for i in range(len(class_number)): class_col = class_number[i] - 1 class_masks[i, class_col] = 1 return class_masks, class_names def mask_data(self, num_classes, class_masks, Scores): ''' Mask the Score matrixes using the masks from create_class_mask ''' row = np.size(Scores[:, 0]) col = num_classes masked_data_X = np.zeros((row, col)) masked_data_Y = np.zeros((row, col)) for i in range(num_classes): masked_data_X[:, i] = Scores[:, 0] * class_masks[:, i] masked_data_Y[:, i] = Scores[:, 1] * class_masks[:, i] return masked_data_X, masked_data_Y
class PlotPanel(wx.Panel): """ The PlotPanel """ def __init__(self, parent, color=None, dpi=None, **kwargs): # initialize Panel if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__(self, parent, **kwargs) self.SetMinSize((100, 40)) # initialize matplotlib stuff self.figure = Figure(None, dpi=dpi, facecolor='white') self.canvas = FigureCanvas(self, -1, self.figure) self.canvas.SetMinSize((30, 10)) self.SetBackgroundColour('white') # Add the canvas to the sizer. self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.canvas, 1, wx.EXPAND) self.SetSizer(self.sizer) #self.canvas.mpl_connect('button_press_event', self.onClick) self.canvas.Bind(wx.EVT_SET_FOCUS, self.onSetFocus) self.Bind(wx.EVT_SET_FOCUS, self.onSetFocus2) self.canvas.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) self.Bind(wx.EVT_KEY_DOWN, self.onKeyDown) self.canvas.Bind(wx.EVT_KEY_UP, self.onKeyUp) self.Bind(wx.EVT_KEY_UP, self.onKeyUp) self.Bind(wx.EVT_LEFT_DOWN, self.onLeftDown) self.canvas.Bind(wx.EVT_LEFT_DOWN, self.onLeftDown) def onClick(self, event): print "Clicked in View. event: %s" % event.guiEvent event.guiEvent.ResumePropagation(1) event.guiEvent.Skip() def onWxClick(self, event): print "Got the WX event." def onSetFocus(self, event): print "Canvas got Focus" event.Skip() def onSetFocus2(self, event): print "PlotPanel got Focus" def onKeyDown(self, event): print "Propagating keyDown in plotPanel" event.ResumePropagation(1) event.Skip() def onKeyUp(self, event): print "Propagating keyUp in plotPanel" event.ResumePropagation(1) event.Skip() def onLeftDown(self, event): print "PlotPanel LEFT DOWN" event.ResumePropagation(30) event.Skip() def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) self.canvas.Refresh()
class MyPlotPanel(wx.Panel): def __init__(self, parent, figsize=None, dpi=None, bgcolor=None, type=None, toolbar=None, aspect='auto', **kwargs): """ construction method of MyPlotPanel class :param parent: parent object :param figsize: plot figure size, (w, h) :param dpi: figure dpi, :parma bgcolor: background color of figure and canvas :param type: type of initial figure, 'image' or 'line' :param toolbar: show toolbar if not set None :param aspect: axes aspect, float number or 'auto' by default """ wx.Panel.__init__(self, parent, **kwargs) self.parent = parent self.figsize = figsize self.dpi = dpi self.bgcolor = bgcolor self.type = type self.toolbar = toolbar self.aspect = aspect self.figure = Figure(self.figsize, self.dpi) self.canvas = FigureCanvas(self, -1, self.figure) # figure background color self.set_color(self.bgcolor) # initialize plot self._init_plot() # set layout self.set_layout() # post-initialization self._post_init() # binding events self.canvas.mpl_connect('button_press_event', self.on_press) self.canvas.mpl_connect('button_release_event', self.on_release) self.canvas.mpl_connect('motion_notify_event', self.on_motion) self.canvas.mpl_connect('pick_event', self.on_pick) self.Bind(wx.EVT_SIZE, self.on_size) self.xylim_choice.Bind(wx.EVT_CHOICE, self.xylim_choiceOnChoice) self.minlim_tc.Bind(wx.EVT_TEXT_ENTER, self.minlim_tcOnTextEnter) self.maxlim_tc.Bind(wx.EVT_TEXT_ENTER, self.maxlim_tcOnTextEnter) def set_layout(self): """ set panel layout """ sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.EXPAND) hbox = wx.BoxSizer(wx.HORIZONTAL) # set toolbar if defined if self.toolbar is not None: self.toobar = MyToolbar(self.canvas) self.toobar.Realize() hbox.Add(self.toobar, 0, wx.EXPAND | wx.RIGHT, 5) # add x[y]lim control xylim_hbox = wx.BoxSizer(wx.HORIZONTAL) xy_vbox = wx.BoxSizer(wx.VERTICAL) xylim_choiceChoices = [u"X-Limit", u"Y-Limit", u"Auto"] self.xylim_choice = wx.Choice(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, xylim_choiceChoices, 0) self.xylim_choice.SetSelection(0) xy_vbox.Add(self.xylim_choice, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3) xylim_hbox.Add(xy_vbox, 0, wx.ALIGN_CENTER_VERTICAL, 1) lim_vbox = wx.BoxSizer(wx.VERTICAL) min_hbox = wx.BoxSizer(wx.HORIZONTAL) self.minlim_st = wx.StaticText(self, wx.ID_ANY, u"Min", wx.DefaultPosition, wx.DefaultSize, 0) self.minlim_st.Wrap(-1) self.minlim_st.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace")) min_hbox.Add(self.minlim_st, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.TOP, 1) self.minlim_tc = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_PROCESS_ENTER) self.minlim_tc.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace")) self.minlim_tc.SetToolTip(u"Min of Limit") min_hbox.Add(self.minlim_tc, 0, wx.ALIGN_CENTER_VERTICAL | wx.TOP, 1) lim_vbox.Add(min_hbox, 1, wx.EXPAND, 1) max_hbox = wx.BoxSizer(wx.HORIZONTAL) self.maxlim_st = wx.StaticText(self, wx.ID_ANY, u"Max", wx.DefaultPosition, wx.DefaultSize, 0) self.maxlim_st.Wrap(-1) self.maxlim_st.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace")) max_hbox.Add(self.maxlim_st, 0, wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.RIGHT | wx.TOP, 1) self.maxlim_tc = wx.TextCtrl(self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, wx.TE_PROCESS_ENTER) self.maxlim_tc.SetFont(wx.Font(6, 70, 90, 90, False, "Monospace")) self.maxlim_tc.SetToolTip(u"Max of Limit") max_hbox.Add(self.maxlim_tc, 0, wx.ALIGN_CENTER_VERTICAL | wx.BOTTOM | wx.TOP, 1) lim_vbox.Add(max_hbox, 1, wx.EXPAND, 1) xylim_hbox.Add(lim_vbox, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 1) hbox.Add(xylim_hbox, 0, wx.EXPAND | wx.RIGHT, 5) # (x, y) pos label self.pos_st = wx.StaticText(self, label='') hbox.Add(self.pos_st, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(hbox, 0, wx.EXPAND | wx.BOTTOM, 0) self.SetSizerAndFit(sizer) def _init_plot(self): if not hasattr(self, 'axes'): self.axes = self.figure.add_subplot(111, aspect=self.aspect) if self.type == 'image': # draw image x = y = np.linspace(-np.pi, np.pi, 100) self.x, self.y = np.meshgrid(x, y) self.z = self._func_peaks(self.x, self.y) self.image = self.axes.imshow(self.z) else: # draw line self.x = np.linspace(-10, 10, 200) self.y = np.sin(self.x) self.line, = self.axes.plot(self.x, self.y) def _post_init(self): self._set_xylim_flag(self.xylim_choice.GetStringSelection()) def set_color(self, rgb_tuple): """ set figure and canvas with the same color. :param rgb_tuple: rgb color tuple, e.g. (255, 255, 255) for white color """ if rgb_tuple is None: #rgb_tuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() rgb_tuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_DESKTOP).Get() clr = [c / 255.0 for c in rgb_tuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgb_tuple)) def on_size(self, event): self.fit_canvas() self.canvas.draw_idle() event.Skip() def on_press(self, event): pass def on_release(self, event): pass def on_pick(self, event): pass def on_motion(self, event): if event.inaxes is not None: self.pos_st.SetLabel("({x:<.4f}, {y:<.4f})".format(x=event.xdata, y=event.ydata)) def fit_canvas(self): """ tight fit canvas layout """ #self.canvas.SetSize(self.GetSize()) self.figure.set_tight_layout(True) def _func_peaks(self, x, y): return 3.0 * (1.0 - x)**2.0 * np.exp(-(x**2) - (y+1)**2) \ - 10*(x/5 - x**3 - y**5) * np.exp(-x**2-y**2) \ - 1.0/3.0*np.exp(-(x+1)**2 - y**2) def refresh(self): self.canvas.draw_idle() def xylim_choiceOnChoice(self, event): sel_str = self.xylim_choice.GetStringSelection() self._set_xylim_flag(sel_str) if sel_str == 'Auto': self.minlim_tc.Disable() self.maxlim_tc.Disable() self.minlim_st.Disable() self.maxlim_st.Disable() # auto set xy limit min_list = [ np.vstack(line.get_data()).min(axis=1).tolist() for line in self.axes.get_lines() ] max_list = [ np.vstack(line.get_data()).max(axis=1).tolist() for line in self.axes.get_lines() ] xmin, ymin = np.array(min_list).min(axis=0) xmax, ymax = np.array(max_list).max(axis=0) x0, xhw = (xmin + xmax) * 0.5, (xmax - xmin) * 0.5 y0, yhw = (ymin + ymax) * 0.5, (ymax - ymin) * 0.5 _xmin, _xmax = x0 - xhw * 1.1, x0 + xhw * 1.1 _ymin, _ymax = y0 - yhw * 1.1, y0 + yhw * 1.1 self.axes.set_xlim([_xmin, _xmax]) self.axes.set_ylim([_ymin, _ymax]) self.refresh() else: self.minlim_tc.Enable() self.maxlim_tc.Enable() self.minlim_st.Enable() self.maxlim_st.Enable() try: _xlim = self.axes.get_xlim() _ylim = self.axes.get_ylim() except: _xlim = [0, 100] _ylim = [0, 100] self._set_default_minlim(_xlim, _ylim) self._set_default_maxlim(_xlim, _ylim) def _set_default_minlim(self, xlim_array, ylim_array): if self._xylim == 'X-Limit': self.minlim_tc.SetValue("{xmin:.3g}".format(xmin=xlim_array[0])) elif self._xylim == 'Y-Limit': self.minlim_tc.SetValue("{ymin:.3g}".format(ymin=ylim_array[0])) def _set_default_maxlim(self, xlim_array, ylim_array): if self._xylim == 'X-Limit': self.maxlim_tc.SetValue("{xmax:.3g}".format(xmax=xlim_array[1])) elif self._xylim == 'Y-Limit': self.maxlim_tc.SetValue("{ymax:.3g}".format(ymax=ylim_array[1])) def minlim_tcOnTextEnter(self, event): xymin = float(self.minlim_tc.GetValue()) xymax = float(self.maxlim_tc.GetValue()) self._set_xylim_range(xymin, xymax) def maxlim_tcOnTextEnter(self, event): xymin = float(self.minlim_tc.GetValue()) xymax = float(self.maxlim_tc.GetValue()) self._set_xylim_range(xymin, xymax) def _set_xylim_flag(self, flag='X-Limit'): """ control x/y limit to be set :param flag: 'X-Limit' or 'Y-Limit' """ self._xylim = flag def _set_xylim_range(self, vmin, vmax): """ set x/y limit according to _xylim value :param vmin: min of limit :param vmax: max of limit """ if self._xylim == 'X-Limit': self.axes.set_xlim([vmin, vmax]) elif self._xylim == 'Y-Limit': self.axes.set_ylim([vmin, vmax]) self.refresh()
class GraphCanvasPanel(wx.Panel): def __init__(self, graphFrame, parent): super().__init__(parent) self.graphFrame = graphFrame # Remove matplotlib font cache, see #234 try: cache_dir = mpl._get_cachedir() except: cache_dir = os.path.expanduser(os.path.join('~', '.matplotlib')) cache_file = os.path.join(cache_dir, 'fontList.cache') if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file): os.remove(cache_file) mainSizer = wx.BoxSizer(wx.VERTICAL) self.figure = Figure(figsize=(5, 3), tight_layout={'pad': 1.08}) rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas = Canvas(self, -1, self.figure) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) self.canvas.mpl_connect('button_press_event', self.OnMplCanvasClick) self.subplot = self.figure.add_subplot(111) self.subplot.grid(True) mainSizer.Add(self.canvas, 1, wx.EXPAND | wx.ALL, 0) self.SetSizer(mainSizer) self.xMark = None self.mplOnDragHandler = None self.mplOnReleaseHandler = None def draw(self, accurateMarks=True): self.subplot.clear() self.subplot.grid(True) allXs = set() allYs = set() plotData = {} legendData = [] chosenX = self.graphFrame.ctrlPanel.xType chosenY = self.graphFrame.ctrlPanel.yType self.subplot.set(xlabel=self.graphFrame.ctrlPanel.formatLabel(chosenX), ylabel=self.graphFrame.ctrlPanel.formatLabel(chosenY)) mainInput, miscInputs = self.graphFrame.ctrlPanel.getValues() view = self.graphFrame.getView() sources = self.graphFrame.ctrlPanel.sources if view.hasTargets: iterList = tuple( itertools.product(sources, self.graphFrame.ctrlPanel.targets)) else: iterList = tuple((f, None) for f in sources) # Draw plot lines and get data for legend for source, target in iterList: # Get line style data try: colorData = BASE_COLORS[source.colorID] except KeyError: pyfalog.warning('Invalid color "{}" for "{}"'.format( source.colorID, source.name)) continue color = colorData.hsl lineStyle = 'solid' if target is not None: try: lightnessData = LIGHTNESSES[target.lightnessID] except KeyError: pyfalog.warning('Invalid lightness "{}" for "{}"'.format( target.lightnessID, target.name)) continue color = lightnessData.func(color) try: lineStyleData = STYLES[target.lineStyleID] except KeyError: pyfalog.warning('Invalid line style "{}" for "{}"'.format( target.lightnessID, target.name)) continue lineStyle = lineStyleData.mplSpec color = hsv_to_rgb(hsl_to_hsv(color)) # Get point data try: xs, ys = view.getPlotPoints(mainInput=mainInput, miscInputs=miscInputs, xSpec=chosenX, ySpec=chosenY, src=source, tgt=target) if not self.__checkNumbers(xs, ys): pyfalog.warning( 'Failed to plot "{}" vs "{}" due to inf or NaN in values' .format(source.name, '' if target is None else target.name)) continue plotData[(source, target)] = (xs, ys) allXs.update(xs) allYs.update(ys) # If we have single data point, show marker - otherwise line won't be shown if len(xs) == 1 and len(ys) == 1: self.subplot.plot(xs, ys, color=color, linestyle=lineStyle, marker='.') else: self.subplot.plot(xs, ys, color=color, linestyle=lineStyle) # Fill data for legend if target is None: legendData.append((color, lineStyle, source.shortName)) else: legendData.append( (color, lineStyle, '{} vs {}'.format(source.shortName, target.shortName))) except Exception: pyfalog.warning('Failed to plot "{}" vs "{}"'.format( source.name, '' if target is None else target.name)) self.canvas.draw() self.Refresh() return # Setting Y limits for canvas if self.graphFrame.ctrlPanel.showY0: allYs.add(0) canvasMinY, canvasMaxY = self._getLimits(allYs, minExtra=0.05, maxExtra=0.1) canvasMinX, canvasMaxX = self._getLimits(allXs, minExtra=0.02, maxExtra=0.02) self.subplot.set_ylim(bottom=canvasMinY, top=canvasMaxY) self.subplot.set_xlim(left=canvasMinX, right=canvasMaxX) # Process X marks line if self.xMark is not None: minX = min(allXs, default=None) maxX = max(allXs, default=None) if minX is not None and maxX is not None: minY = min(allYs, default=None) maxY = max(allYs, default=None) xMark = max(min(self.xMark, maxX), minX) # If in top 10% of X coordinates, align labels differently if xMark > canvasMinX + 0.9 * (canvasMaxX - canvasMinX): labelAlignment = 'right' labelPrefix = '' labelSuffix = ' ' else: labelAlignment = 'left' labelPrefix = ' ' labelSuffix = '' # Draw line self.subplot.axvline(x=xMark, linestyle='dotted', linewidth=1, color=(0, 0, 0)) # Draw its X position if chosenX.unit is None: xLabel = '{}{}{}'.format(labelPrefix, roundToPrec(xMark, 4), labelSuffix) else: xLabel = '{}{} {}{}'.format(labelPrefix, roundToPrec(xMark, 4), chosenX.unit, labelSuffix) self.subplot.annotate(xLabel, xy=(xMark, canvasMaxY - 0.01 * (canvasMaxY - canvasMinY)), xytext=(0, 0), annotation_clip=False, textcoords='offset pixels', ha=labelAlignment, va='top', fontsize='small') # Get Y values yMarks = set() def addYMark(val): if val is None: return # If due to some bug or insufficient plot density we're # out of bounds, do not add anything if minY <= val <= maxY: if abs(val) < 0.0001: val = 0 else: val = roundToPrec(val, 4) yMarks.add(val) for source, target in iterList: xs, ys = plotData[(source, target)] if not xs or xMark < min(xs) or xMark > max(xs): continue # Fetch values from graphs when we're asked to provide accurate data if accurateMarks: try: y = view.getPoint(x=xMark, miscInputs=miscInputs, xSpec=chosenX, ySpec=chosenY, src=source, tgt=target) addYMark(y) except Exception: pyfalog.warning( 'Failed to get X mark for "{}" vs "{}"'.format( source.name, '' if target is None else target.name)) # Silently skip this mark, otherwise other marks and legend display will fail continue # Otherwise just do linear interpolation between two points else: if xMark in xs: # We might have multiples of the same value in our sequence, pick value for the last one idx = len(xs) - xs[::-1].index(xMark) - 1 addYMark(ys[idx]) continue idx = bisect(xs, xMark) yMark = self._interpolateX(x=xMark, x1=xs[idx - 1], y1=ys[idx - 1], x2=xs[idx], y2=ys[idx]) addYMark(yMark) # Draw Y values for yMark in yMarks: self.subplot.annotate('{}{}{}'.format( labelPrefix, yMark, labelSuffix), xy=(xMark, yMark), xytext=(0, 0), textcoords='offset pixels', ha=labelAlignment, va='center', fontsize='small') legendLines = [] for i, iData in enumerate(legendData): color, lineStyle, label = iData legendLines.append( Line2D([0], [0], color=color, linestyle=lineStyle, label=label.replace('$', '\$'))) if len(legendLines) > 0 and self.graphFrame.ctrlPanel.showLegend: legend = self.subplot.legend(handles=legendLines) for t in legend.get_texts(): t.set_fontsize('small') for l in legend.get_lines(): l.set_linewidth(1) self.canvas.draw() self.Refresh() def markXApproximate(self, x): if x is not None: self.xMark = x self.draw(accurateMarks=False) def unmarkX(self): self.xMark = None self.draw() @staticmethod def _getLimits(vals, minExtra=0, maxExtra=0): minVal = min(vals, default=0) maxVal = max(vals, default=0) # Extend range a little for some visual space valRange = maxVal - minVal minVal -= valRange * minExtra maxVal += valRange * maxExtra # Extend by % of value if we show function of a constant if minVal == maxVal: minVal -= minVal * 0.05 maxVal += minVal * 0.05 # If still equal, function is 0, spread out visual space as special case if minVal == maxVal: minVal -= 5 maxVal += 5 return minVal, maxVal @staticmethod def _interpolateX(x, x1, y1, x2, y2): pos = (x - x1) / (x2 - x1) y = y1 + pos * (y2 - y1) return y @staticmethod def __checkNumbers(xs, ys): for number in itertools.chain(xs, ys): if math.isnan(number) or math.isinf(number): return False return True # Matplotlib event handlers def OnMplCanvasClick(self, event): if event.button == 1: if not self.mplOnDragHandler: self.mplOnDragHandler = self.canvas.mpl_connect( 'motion_notify_event', self.OnMplCanvasDrag) if not self.mplOnReleaseHandler: self.mplOnReleaseHandler = self.canvas.mpl_connect( 'button_release_event', self.OnMplCanvasRelease) self.markXApproximate(event.xdata) elif event.button == 3: self.unmarkX() def OnMplCanvasDrag(self, event): self.markXApproximate(event.xdata) def OnMplCanvasRelease(self, event): if event.button == 1: if self.mplOnDragHandler: self.canvas.mpl_disconnect(self.mplOnDragHandler) self.mplOnDragHandler = None if self.mplOnReleaseHandler: self.canvas.mpl_disconnect(self.mplOnReleaseHandler) self.mplOnReleaseHandler = None # Do not write markX here because of strange mouse behavior: when dragging, # sometimes when you release button, x coordinate changes. To avoid that, # we just re-use coordinates set on click/drag and just request to redraw # using accurate data self.draw(accurateMarks=True)
class WxScatter(wx.Panel): def __init__(self, *args, **kwargs): self.mapwidget = kwargs.pop('map', None) self.timewidget = kwargs.pop('time', None) wx.Panel.__init__(self, *args, **kwargs) self.id = wx.NewId() self.gpxfig = Figure() self.ax = self.gpxfig.add_subplot(111, polar=True) self.ax.set_theta_zero_location("N") self.gpxfig.subplots_adjust(right=0.9, left=0.1) # canvas and events self.gpxcanvas = FigureCanvas(self, -1, self.gpxfig) self.gpxcanvas.mpl_connect('draw_event', self.OnDraw) self.gpxcanvas.mpl_connect('scroll_event', self.OnMouseWheel) self.gpxcanvas.mpl_connect('button_press_event', self.OnLeftMouseDown) self.gpxcanvas.mpl_connect('button_release_event', self.OnLeftMouseUp) self.gpxcanvas.mpl_connect('motion_notify_event', self.OnMouseMotion) self.gpxcanvas.mpl_connect('resize_event', self.OnSize) self.gpxcanvas.mpl_connect('figure_enter_event', self.OnMouseEnter) self.gpxcanvas.mpl_connect('figure_leave_event', self.OnMouseLeave) self.sizer = wx.BoxSizer(wx.VERTICAL) self.sizer.Add(self.gpxcanvas, 1, wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND) self.SetSizer(self.sizer) msgwrap.register(self.OnSigCurChanged, "CurChanged") msgwrap.register(self.OnSigSelChanged, "SelChanged") msgwrap.register(self.OnSigValChanged, "ValChanged") #that code does not work on linux... color = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE) self.gpxfig.set_facecolor( (color.red / 255.0, color.green / 255.0, color.blue / 255.0)) self.gpxfig.set_edgecolor( (color.red / 255.0, color.green / 255.0, color.blue / 255.0)) self.gpxcanvas.SetBackgroundColour(color) #plugin specific initialization self.thetasrc = 'course' self.radiussrc = 'speed' self.autoscale = True self.grid = False self.kwargs = {'color': '#0000FF'} self.grid = False def Plot(self, xrange=None, yrange=None): self.ax.cla() self.ax.scatter(self.gpx[(self.thetasrc,1,1)]/360*2*np.pi,\ self.gpx[(self.radiussrc,1,1)],\ c=self.gpx[(self.radiussrc,1,1)],\ marker='o', cmap=cm.jet) self.ax.set_theta_zero_location("N") self.ax.set_theta_direction(-1) self.ax.grid(self.grid) self.gpxcanvas.draw() self.OnSize(None) def AttachGpx(self, data): self.gpx = data self.Plot() self.OnSize(None) def DetachGpx(self): self.gpx = None def OnSigSelChanged(self, arg1, arg2, arg3): if arg1 == self.id: return def OnSigValChanged(self, arg1): if arg1 == self.id: return self.Plot() def OnSigCurChanged(self, arg1, arg2): if arg1 == self.id: return def OnDraw(self, event): pass def OnSize(self, event): pixels = self.GetClientSize() if pixels[0] < 20 or pixels[1] < 20: return self.gpxfig.set_size_inches( float(pixels[0]) / self.gpxfig.get_dpi(), float(pixels[1]) / self.gpxfig.get_dpi()) self.gpxfig.subplots_adjust(right=0.85, left=0.15, top=0.85, bottom=0.15) def OnLeftMouseDown(self, event): if event.button == 1: if event.dblclick: try: event.guiEvent.GetEventObject().ReleaseMouse() except: pass self.OnLeftMouseDblClick(event) return def OnLeftMouseDblClick(self, event): (dummy,xlo,xhi,ylo,yhi,self.autoscale,self.grid,\ dummy,self.thetasrc,self.radiussrc,extra)=\ WxQuery("Graph Settings",\ [('wxnotebook','Axes',None,None,None), ('wxentry','Theta Low',None,self.ax.get_xlim()[0],'float'), ('wxentry','Theta High',None,self.ax.get_xlim()[1],'float'), ('wxentry','Radius Low',None,self.ax.get_ylim()[0],'float'), ('wxentry','Radius High',None,self.ax.get_ylim()[1],'float'), ('wxcheck','Autoscale',None,self.autoscale,'bool'), ('wxcheck','Show Grid',None,self.grid,'bool'), ('wxnotebook','Polar plot',None,None,None), ('wxcombo','Theta',self.XAxisAllowed(),self.thetasrc,'str'), ('wxcombo','Radius',self.XAxisAllowed(),self.radiussrc,'str'), ('wxentry','Extra arguments',None,{},'str') ]) self.kwargs.update(ast.literal_eval(extra)) if self.autoscale: self.Plot() else: self.Plot((xlo, xhi), (ylo, yhi)) def OnMouseWheel(self, event): scale_factor = 1.2 if event.button == 'down' else (1.0 / 1.2) rmin, rmax = self.ax.get_ylim() self.ax.set_ylim(rmin * scale_factor, rmax * scale_factor) self.gpxcanvas.draw() def OnLeftMouseUp(self, event): pass def OnMouseMotion(self, event): pass def OnMouseEnter(self, event): pass def OnMouseLeave(self, event): pass def XAxisAllowed(self): l = '' for name in self.gpx.get_header_names(): if name not in ['time', 'ok'] and name[0] != '_': l += '|' + name return l[1:]
class Panel_Graphe(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent, -1, style=wx.TAB_TRAVERSAL) self.afficher_valeurs = False self.panel = wx.Panel(self, -1, style=wx.TAB_TRAVERSAL | wx.SUNKEN_BORDER) self.figure = matplotlib.pyplot.figure() self.canvas = Canvas(self.panel, -1, self.figure) self.canvas.SetMinSize((20, 20)) self.SetColor((255, 255, 255)) # Boutons self.bouton_apercu = wx.BitmapButton( self, -1, wx.Bitmap(Chemins.GetStaticPath(u"Images/16x16/Apercu.png"), wx.BITMAP_TYPE_ANY)) self.bouton_options = wx.BitmapButton( self, -1, wx.Bitmap(Chemins.GetStaticPath(u"Images/16x16/Mecanisme.png"), wx.BITMAP_TYPE_ANY)) # Binds self.Bind(wx.EVT_BUTTON, self.Apercu, self.bouton_apercu) self.Bind(wx.EVT_BUTTON, self.Options, self.bouton_options) # Properties self.bouton_apercu.SetToolTipString( _(u"Cliquez ici pour ouvrir le visualiseur de graphe pour accéder aux fonctions d'export et d'impression" )) self.bouton_options.SetToolTipString( _(u"Cliquez ici pour accéder aux options du graphe")) # Layout grid_sizer_base = wx.FlexGridSizer(1, 2, 5, 5) sizer_canvas = wx.BoxSizer(wx.VERTICAL) sizer_canvas.Add(self.canvas, 1, wx.EXPAND, 0) self.panel.SetSizer(sizer_canvas) grid_sizer_base.Add(self.panel, 1, wx.EXPAND | wx.TOP | wx.LEFT | wx.BOTTOM, 10) grid_sizer_boutons = wx.FlexGridSizer(5, 1, 5, 5) grid_sizer_boutons.Add(self.bouton_apercu, 0, 0, 0) grid_sizer_boutons.Add(self.bouton_options, 0, 0, 0) grid_sizer_base.Add(grid_sizer_boutons, 1, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.RIGHT, 10) grid_sizer_base.AddGrowableCol(0) grid_sizer_base.AddGrowableRow(0) self.SetSizer(grid_sizer_base) self.Layout() def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def ConvertCouleur(self, couleur=None): return [c / 255. for c in couleur] def Apercu(self, event): import DLG_Zoom_graphe dlg = DLG_Zoom_graphe.Dialog(self, figure=self.figure) dlg.ShowModal() dlg.Destroy() def Options(self, event): # Création du menu contextuel menuPop = wx.Menu() item = wx.MenuItem(menuPop, 10, _(u"Afficher les valeurs"), _(u"Afficher les valeurs"), wx.ITEM_CHECK) menuPop.AppendItem(item) self.Bind(wx.EVT_MENU, self.On_afficher_valeurs, id=10) if self.afficher_valeurs == True: item.Check(True) self.PopupMenu(menuPop) menuPop.Destroy() def On_afficher_valeurs(self, event): self.afficher_valeurs = not self.afficher_valeurs self.MAJ() def SetDictBudget(self, dictBudget=None): self.dictBudget = dictBudget self.MAJ() def MAJ(self): self.figure.clear() if self.dictBudget == None: wx.CallAfter(self.SendSizeEvent) return # Récupération des données from Ol import OL_Suivi_budget analyse = OL_Suivi_budget.Analyse(self.dictBudget) listeCategories = analyse.GetValeurs() listeRealise = [] listeBudgete = [] listeLabels = [] for dictCategorie in listeCategories: listeRealise.append(dictCategorie["realise"]) listeBudgete.append(dictCategorie["plafond"]) listeLabels.append(dictCategorie["nomCategorie"]) ## if dictCategorie["typeCategorie"] == "debit" : ## solde = plafond - realise ## else : ## solde = realise - plafond ## # TEST ## listeIndex = np.arange(len(listeLabels)) ## bar_width = 0.2 ## opacity = 0.4 ## ## ax = self.figure.add_subplot(111) ## barres = ax.bar(listeIndex, listeRealise, width=bar_width, alpha=opacity, color="g", label=_(u"Réel")) ## barres = ax.bar(listeIndex + bar_width, listeBudgete, width=bar_width, alpha=opacity, color="b", label=_(u"Budgété")) ## ## # Formatage des montants sur y ## majorFormatter = FormatStrFormatter(SYMBOLE + u" %d") ## ax.yaxis.set_major_formatter(majorFormatter) ## ## # Affichage des labels x ## ax.set_xticks(listeIndex + bar_width) ## ax.set_xticklabels(listeLabels) ## ## labels = ax.get_xticklabels() ## setp(labels, rotation=45) ## ## # Légende ## props = matplotlib.font_manager.FontProperties(size=10) ## leg = ax.legend(loc='best', shadow=False, fancybox=True, prop=props) ## leg.get_frame().set_alpha(0.5) ## ## # Espaces autour du graph ## self.figure.subplots_adjust(left=0.12, bottom=0.40, right=None, wspace=None, hspace=None) # TEST listeIndex = np.arange(len(listeLabels)) bar_height = 0.2 opacity = 0.4 ax = self.figure.add_subplot(111) barresRealise = ax.barh(listeIndex, listeRealise, height=bar_height, alpha=opacity, color="g", label=_(u"Réel")) barresBudgete = ax.barh(listeIndex + bar_height, listeBudgete, height=bar_height, alpha=opacity, color="b", label=_(u"Budgété")) # Formatage des montants sur x majorFormatter = FormatStrFormatter(u"%d " + SYMBOLE) ax.xaxis.set_major_formatter(majorFormatter) # Affichage des labels x ax.set_yticks(listeIndex + bar_height) ax.set_yticklabels(listeLabels) def autolabel(rects): # attach some text labels for rect in rects: width = rect.get_width() ax.text(width + 20, rect.get_y() + rect.get_height() / 2., u"%.2f %s" % (int(width), SYMBOLE), ha='left', va='center', fontsize=8, color="grey") if self.afficher_valeurs == True: autolabel(barresRealise) autolabel(barresBudgete) # Recherche la largeur de texte max largeurMax = 0 for label in listeLabels: if len(label) > largeurMax: largeurMax = len(label) # Espaces autour du graph margeGauche = 0.1 + largeurMax * 0.008 self.figure.subplots_adjust(left=margeGauche, right=None, wspace=None, hspace=None) # Légende props = matplotlib.font_manager.FontProperties(size=10) leg = ax.legend(loc='best', shadow=False, fancybox=True, prop=props) leg.get_frame().set_alpha(0.5) # Finalisation ax.autoscale_view('tight') ## ax.grid(True) ax.figure.canvas.draw() wx.CallAfter(self.SendSizeEvent) return
class plotTimeSeries(wx.Panel): def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent) def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_ctrls(self, parent): wx.Panel.__init__(self, parent, -1) self.parent = parent #init Plot # matplotlib.figure.Figure self.figure = plt.figure() # matplotlib.axes.AxesSubplot self.timeSeries = host_subplot(111, axes_class=AA.Axes) self.setTimeSeriesTitle("No Data to Plot") # matplotlib.backends.backend_wxagg.FigureCanvasWxAgg self.canvas = FigCanvas(self, -1, self.figure) self.canvas.SetFont( wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.isShowLegendEnabled = False self.canvas.mpl_connect('figure_leave_event', self._onFigureLeave) Publisher.subscribe(self.updateCursor, "updateCursor") # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, allowselect=True) self.toolbar.Realize() self.seriesPlotInfo = None #set properties self.fontP = FontProperties() self.fontP.set_size('x-small') self.format = '-o' self.alpha = 1 self._setColor("WHITE") left = 0.125 # the left side of the subplots of the figure #right = 0.9 # the right side of the subplots of the figure #bottom = 0.51 # the bottom of the subplots of the figure #top = 1.2 # the top of the subplots of the figure #wspace = .8 # the amount of width reserved for blank space between subplots #hspace = .8 # the amount of height reserved for white space between subplots plt.subplots_adjust( left= left #, bottom=bottom, right=right, top=top, wspace=wspace, hspace=hspace ) plt.tight_layout() #init hover tooltip # create a long tooltip with newline to get around wx bug (in v2.6.3.3) # where newlines aren't recognized on subsequent self.tooltip.SetTip() calls self.tooltip = wx.ToolTip( tip='tip with a long %s line and a newline\n') self.canvas.SetToolTip(self.tooltip) self.tooltip.Enable(False) self.tooltip.SetDelay(0) #init lists #self.lines = {} self.lines = [] self.axislist = {} self.curveindex = -1 self.editseriesID = -1 self.editCurve = None self.editPoint = None self.hoverAction = None self.selplot = None self.cursors = [] self.canvas.draw() self._init_sizers() def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) ''' def changePlotSelection(self, datetime_list=[]): cc= ColorConverter() # k black, # r red # needs to have graph first selected = cc.to_rgba('r', 1) unselected = cc.to_rgba('k', 0.1) allunselected = cc.to_rgba('k', 1) if self.editPoint: colorlist=[allunselected] *len(self.editCurve.dataTable) if len(datetime_list)>0: for i in xrange(len(self.editCurve.dataTable)): if self.editCurve.dataTable[i][1] in datetime_list: colorlist[i]=selected else: colorlist[i]=unselected self.editPoint.set_color(colorlist) #self.editPoint.set_color(['k' if x == 0 else 'r' for x in tflist]) self.canvas.draw() ''' ## TODO 10/15/2014 Change function so that it will accept a list of datavalues. This will remove the need to loop through the values currently plotted and we would instead plot the list of datetimes and datavalues together. def changePlotSelection(self, filtered_datetime): """ Selected points have a scatter plot drawn over them to indicated the point being selected """ if self.selplot: self.selplot.remove() del self.selplot self.selplot = None result = None if isinstance(filtered_datetime, pd.DataFrame): result = filtered_datetime.sort_index() if isinstance(filtered_datetime, list): df = self.editCurve.dataTable result = df[df['LocalDateTime'].isin(filtered_datetime)].astype( datetime.datetime) if isinstance(result, pd.DataFrame): if result.empty: self.canvas.draw() return else: if not result: self.canvas.draw() return values = result['DataValue'].values.tolist() dates = result.index.astype(datetime.datetime) self.selplot = self.axislist[self.editSeries.axisTitle].scatter( dates, values, s=35, c='red', edgecolors='none', zorder=12, marker='s', alpha=1) self.canvas.draw() def lassoChangeSelection(self, filtered_datetime): self.parent.record_service.select_points(dataframe=filtered_datetime) def onShowLegend(self, isVisible): if isVisible: self.isShowLegendEnabled = True plt.subplots_adjust(bottom=.1 + .1) leg = self.timeSeries.legend(loc='upper right', ncol=2, fancybox=True, prop=self.fontP) leg.get_frame().set_alpha(.5) leg.draggable(state=True) else: self.isShowLegendEnabled = False plt.subplots_adjust(bottom=.1) self.timeSeries.legend_ = None plt.gcf().autofmt_xdate() self.canvas.draw() def onPlotType(self, ptype): # self.timeSeries.clear() if ptype == "line": ls = '-' m = 'None' elif ptype == "point": ls = 'None' m = 'o' else: ls = '-' m = 'o' self.format = ls + m for k, v in self.axislist.iteritems(): lines = v.get_lines() for line in lines: plt.setp(line, linestyle=ls, marker=m) if self.isShowLegendEnabled: self.onShowLegend(self.isShowLegendEnabled) plt.gcf().autofmt_xdate() self.canvas.draw() def stopEdit(self): self.clear() self.selectedlist = None self.selplot = None self.lman = None #self.canvas.mpl_disconnect(self.hoverAction) try: self.canvas.mpl_disconnect(self.pointPick) self.pointPick = None except AttributeError as e: logger.error(e) self.hoverAction = None self.xys = None self.alpha = 1 self.curveindex = -1 self.editCurve = None # self.RefreshPlot() if self.seriesPlotInfo and self.seriesPlotInfo.isPlotted( self.editseriesID): self.updatePlot() self.toolbar.stopEdit() self.editseriesID = -1 def updateValues(self): # self.addEdit(self.editCursor, self.editSeries, self.editDataFilter) #clear current edit points and curve if self.editCurve: curraxis = self.axislist[self.editCurve.axisTitle] for l in curraxis.lines: if l.get_label() == self.editCurve.plotTitle: curraxis.lines.remove(l) #redraw editpoints and curve self.seriesPlotInfo.updateEditSeries() self.editCurve = self.seriesPlotInfo.getEditSeriesInfo() self.drawEditPlot(self.editCurve) self.canvas.draw() Publisher.sendMessage("refreshTable", e=self.editCurve.dataTable) # self.parent.parent.dataTable.Refresh() plt.gcf().autofmt_xdate() self.canvas.draw() def drawEditPlot(self, oneSeries): self.axislist[oneSeries.axisTitle].set_zorder(10) self.lines[self.curveindex] = self.axislist[oneSeries.axisTitle] data = oneSeries.dataTable dates = data.index.astype(datetime.datetime) curraxis = self.axislist[oneSeries.axisTitle] curraxis.plot_date(dates, data['DataValue'], "-s", color=oneSeries.color, xdate=True, label=oneSeries.plotTitle, zorder=10, alpha=1, picker=5.0, pickradius=5.0, markersize=4.5) curraxis.set_xlabel('Date') convertedDates = matplotlib.dates.date2num(dates) self.xys = zip(convertedDates, oneSeries.dataTable['DataValue']) self.toolbar.editSeries(self.xys, self.editCurve) self.pointPick = self.canvas.mpl_connect('pick_event', self._onPick) self.editSeries = oneSeries def _setColor(self, color): """Set figure and canvas colours to be the same. :rtype : object """ plt.gcf().set_facecolor(color) plt.gcf().set_edgecolor(color) self.canvas.SetBackgroundColour(color) def close(self): #plt.clf() #plt.close() pass def Plot(self, seriesPlotInfo): self.seriesPlotInfo = seriesPlotInfo self.updatePlot() # resets the home view - will remove any previous zooming self.toolbar.update() self.toolbar.push_current() #self._views.home() #self._positions.home() #self.set_history_buttons() #clear plot def clear(self): """ :return: """ lines = [] for key, ax in self.axislist.items(): ax.clear() self.axislist = {} #self.canvas.draw() # self.stopEdit() #print "TimeSeries: ", dir(self.timeSeries), type(self.timeSeries) #plt.cla() #plt.clf() #self.timeSeries.plot([], [], picker=5) def setUpYAxis(self): """ Setting up multiple axes :return: """ self.axislist = {} left = 0 right = 0 adj = .05 editaxis = None ## Identify Axes and save them to axislist #loop through the list of curves and add an axis for each for oneSeries in self.seriesPlotInfo.getAllSeries(): #test to see if the axis already exists if oneSeries.edit: editaxis = oneSeries.axisTitle if not oneSeries.axisTitle in self.axislist: self.axislist[oneSeries.axisTitle] = None keys = self.axislist.keys() ## Put editing axis at the beginning of the list if editaxis: for i in range(len(keys)): if keys[i] == editaxis: keys.pop(i) break keys.insert(0, editaxis) leftadjust = -30 for i, axis in zip(range(len(self.axislist)), keys): if i % 2 == 0: left = left + 1 #add to the left(yaxis) if i == 0: #if first plot use the orig axis newAxis = self.timeSeries else: newAxis = self.timeSeries.twinx() ''' Spines idea #newAxis.spines["left"].set_position(("axes", leftadjust * left)) newAxis.spines["left"].set_position(("axes", -.1)) newAxis.spines["left"].set_visible(True) newAxis.yaxis.set_label_position("left") newAxis.yaxis.set_ticks_position("left") ''' new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis newAxis.axis['left'] = new_fixed_axis(loc='left', axes=newAxis, offset=(leftadjust * left, 0)) newAxis.axis["left"].toggle(all=True) newAxis.axis["right"].toggle(all=False) leftadjust -= 15 else: right = right + 1 #add to the right(y2axis) newAxis = self.timeSeries.twinx() ''' Spines idea #newAxis.spines["right"].set_position(("axes", -1*60*(right - 1))) newAxis.spines["right"].set_position(("axes", 1.0)) newAxis.spines["right"].set_visible(True) newAxis.yaxis.set_label_position("right") newAxis.yaxis.set_ticks_position("right") ''' new_fixed_axis = newAxis.get_grid_helper().new_fixed_axis newAxis.axis['right'] = new_fixed_axis(loc='right', axes=newAxis, offset=(60 * (right - 1), 0)) newAxis.axis['right'].toggle(all=True) a = newAxis.set_ylabel(axis, picker=True) a.set_picker(True) #logger.debug("axis label: %s" % (axis)) self.axislist[axis] = newAxis plt.tight_layout() self.canvas.draw() def updatePlot(self): self.clear() count = self.seriesPlotInfo.count() self.setUpYAxis() self.lines = [] ## Spine initialization ## for oneSeries in self.seriesPlotInfo.getAllSeries(): if oneSeries.seriesID == self.seriesPlotInfo.getEditSeriesID(): """ Edited Series """ self.curveindex = len(self.lines) self.lines.append("") self.editCurve = oneSeries self.drawEditPlot(oneSeries) else: """ Plotted Series """ curraxis = self.axislist[oneSeries.axisTitle] curraxis.set_zorder(1) data = oneSeries.dataTable dates = data.index.astype(datetime.datetime) #data.plot(ax=curraxis) curraxis.plot_date(dates, data['DataValue'], color=oneSeries.color, fmt=self.format, xdate=True, tz=None, antialiased=True, label=oneSeries.plotTitle, alpha=self.alpha, picker=5.0, pickradius=5.0, markersize=4) curraxis.set_xlabel('Date') ''' data = oneSeries.dataTable #dates = data['LocalDateTime'].astype(datetime.datetime) data['LocalDateTime'] = pd.to_datetime(data['LocalDateTime']) data['LocalDateTime'].astype(datetime.datetime) data.plot(ax=curraxis) oneSeries.dataTable.plot(ax=curraxis) curraxis.set_xlabel('Date') ''' if count > 1: self.setTimeSeriesTitle("") plt.subplots_adjust(bottom=.1 + .1) # self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), # ncol=2, prop = self.fontP) self.timeSeries.legend(loc='upper center', bbox_to_anchor=(0.5, -1.75), ncol=2, prop=self.fontP) elif count == 0: self.setTimeSeriesTitle("") self.timeSeries.legend_ = None else: self.setTimeSeriesTitle(oneSeries.siteName) plt.subplots_adjust(bottom=.1) self.timeSeries.legend_ = None self.timeSeries.set_xlabel("Date", picker=True) #self.timeSeries.set_xlim(matplotlib.dates.date2num([self.seriesPlotInfo.currentStart, self.seriesPlotInfo.currentEnd])) #self.timeSeries.axis[:].set_major_formatter(FormatStrFormatter('%.2f')) self.timeSeries.axis[:].major_ticks.set_tick_out(True) self.timeSeries.axis["bottom"].label.set_pad(20) self.timeSeries.axis["bottom"].major_ticklabels.set_pad(15) self.timeSeries.axis["bottom"].major_ticklabels.set_rotation(15) self.timeSeries.axis[:].major_ticklabels.set_picker(True) plt.gcf().autofmt_xdate() #self.figure.tight_layout() if not self.toolbar._views.empty(): for v in self.toolbar._views: del (v) self.toolbar.push_current() self.canvas.draw() def updateCursor(self, selectedObject=None, deselectedObject=None): """ :param selectedObject: """ try: if selectedObject: """ Activate Cursor. Happens when a plot is selected """ if self.seriesPlotInfo: seriesInfo = self.seriesPlotInfo.getSeries( selectedObject.id) if seriesInfo: currentAxis = None # If there a key with the axisTitle we are interested in, set currentaxis to that. if seriesInfo.axisTitle in self.axislist.keys(): currentAxis = self.axislist[seriesInfo.axisTitle] # If nothing is in the axislist, we don't care about it elif len(self.axislist) < 1: currentAxis = None self.configureCursor(currentAxis=currentAxis) elif deselectedObject: """ Deactivate Cursor. This happens when the plot is deselected """ self.deactivateCursor(deselectedObject) except AttributeError as e: print "Ignoring Attribute Error", e def deactivateCursor(self, deselectedObject=None): # Remove an object if supplied if deselectedObject: for i in self.cursors: if i.selected == deselectedObject: i.disable() break # Disable existing Cursors elif self.cursors: for i in self.cursors: i.disable() def configureCursor(self, currentAxis=None): """Creates the cursors for each axes in order to provide data hovering""" self.deactivateCursor() self.cursors = [] # initialize cursors for axes from currently selected axes for k, v in self.axislist.iteritems(): i = Cursor(self.canvas, self.toolbar, v, k) ## If I have selected an axis that is in the axislist if v == currentAxis: i.enable() i.setSelected(currentAxis) # If there is only one axis in the axislist, default to the first axis elif len(self.axislist) == 1: i.enable() i.setSelected(self.axislist.values()[0]) # Else I disable the other axes that I don't care about else: i.setSelected(None) i.disable() self.cursors.append(i) def setTimeSeriesTitle(self, title=""): """Set the title of the TimeSeries plot""" self.timeSeries.set_title(title, picker=True) def setEdit(self, id): self.editseriesID = id self.alpha = .5 if self.seriesPlotInfo and self.seriesPlotInfo.isPlotted( self.editseriesID): self.editCurve = self.seriesPlotInfo.getSeries(self.editseriesID) ## TODO Duplicate UpdatePlot? logger.debug("Called duplicate updateplot") self.updatePlot() def make_patch_spines_invisible(self, ax): ax.set_frame_on(True) ax.patch.set_visible(False) for sp in ax.spines.itervalues(): sp.set_visible(False) def _onMotion(self, event): """ :type event: matplotlib.backend_bases.MouseEvent :return: """ try: if event.xdata and event.ydata: xValue = matplotlib.dates.num2date( event.xdata).replace(tzinfo=None) #self.toolbar.msg.SetLabelText("X= %s, Y= %.2f" % (xValue.strftime("%Y-%m-%d %H:%M:%S"), event.ydata)) #self.toolbar.msg.SetLabelText("X= %s, Y= %.2f" % (xValue.strftime("%b %d, %Y %H:%M:%S"), event.ydata)) self.toolbar.msg.SetLabelText( "X= %s, Y= %.2f" % (xValue.strftime("%b %d, %Y %H:%M"), event.ydata)) self.toolbar.msg.SetForegroundColour((66, 66, 66)) else: self.toolbar.msg.SetLabelText("") except ValueError: pass def _onPick(self, event): """ :param event: :return: """ if isinstance(event.artist, Line2D): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() ind = event.ind xValue = xdata[ind][0] yValue = ydata[ind][0] #tip = '(%s, %s)' % (xValue.strftime("%Y-%m-%d %H:%M:%S"), yValue) #tip = '(%s, %s)' % (xValue.strftime("%b %d, %Y %H:%M:%S"), yValue) tip = '(%s, %s)' % (xValue.strftime("%b %d, %Y %H:%M"), yValue) self.tooltip.SetTip(tip) self.tooltip.Enable(True) self.tooltip.SetAutoPop(10000) elif isinstance(event.artist, Text): text = event.artist #print "Picking Label: ", text.get_text() def _onFigureLeave(self, event): """Catches mouse leaving the figure :param event: :return: """ if self.tooltip.Window.Enabled: self.tooltip.SetTip("")
class AbstractPlot(wx.Panel): def __init__(self, parent, color=None, dpi=None, **kwargs): from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg from matplotlib.figure import Figure # set default matplotlib parameters import matplotlib as mpl fontSize = 10 mpl.rcParams['font.size'] = fontSize mpl.rcParams['axes.titlesize'] = fontSize mpl.rcParams['axes.labelsize'] = fontSize mpl.rcParams['xtick.labelsize'] = fontSize mpl.rcParams['ytick.labelsize'] = fontSize mpl.rcParams['legend.fontsize'] = fontSize # initialize Panel if 'id' not in kwargs.keys(): kwargs['id'] = wx.ID_ANY if 'style' not in kwargs.keys(): kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE wx.Panel.__init__(self, parent, **kwargs) # initialize matplotlib stuff self.figure = Figure(None, dpi) self.canvas = FigureCanvasWxAgg(self, -1, self.figure) self.SetColor( color ) self.SetPlotSize() self._resizeFlag = False parent.Bind(wx.EVT_SIZE, self._OnSize) self.Bind(wx.EVT_IDLE, self._OnIdle) def _OnSize(self, event): self._resizeFlag = True def _OnIdle(self, event): if self._resizeFlag: self._resizeFlag = False self.SetPlotSize() def SetColor( self, rgbtuple=None ): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get() clr = [c/255. for c in rgbtuple] self.figure.set_facecolor( clr ) self.figure.set_edgecolor( clr ) self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) ) def SetPlotSize( self ): """ Set plot to fill entire frame. """ pixels = tuple( self.GetParent().GetClientSize() ) self.SetSize( pixels ) self.canvas.SetSize( pixels ) self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(), float( pixels[1] )/self.figure.get_dpi() ) def Draw(self): """Function to be overridden in derived class.""" pass def DrawEmptyPlot(self): """Draw empty plot.""" self.figure.clf() emptyAxis = self.figure.add_axes([0.1,0.1,0.85,0.85]) emptyAxis.set_ylabel('y axis') emptyAxis.set_xlabel('x axis') self.canvas.draw() def Clear(self): """ Clear current figure. """ self.figure.clf() def SavePlot(self, dpi=300): """Save plot to file.""" saveImageDlg = SaveImageDlg(self) if saveImageDlg.ShowModal() == wx.ID_OK: if saveImageDlg.filename != None: self.figure.savefig(saveImageDlg.filename, format=saveImageDlg.format, dpi=saveImageDlg.DPI, facecolor='white', edgecolor='white') saveImageDlg.Destroy()
class GraphFrame(wx.Frame): def __init__(self, parent, style=wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.FRAME_FLOAT_ON_PARENT): global graphFrame_enabled global mplImported global mpl_version self.legendFix = False if not graphFrame_enabled: pyfalog.warning( "Matplotlib is not enabled. Skipping initialization.") return try: cache_dir = mpl._get_cachedir() except: cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib")) cache_file = os.path.join(cache_dir, 'fontList.cache') if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file): # remove matplotlib font cache, see #234 os.remove(cache_file) if not mplImported: mpl.use('wxagg') graphFrame_enabled = True if int(mpl.__version__[0]) < 1: pyfalog.warning( "pyfa: Found matplotlib version {} - activating OVER9000 workarounds" .format(mpl.__version__)) pyfalog.warning( "pyfa: Recommended minimum matplotlib version is 1.0.0") self.legendFix = True mplImported = True wx.Frame.__init__(self, parent, title="pyfa: Graph Generator", style=style, size=(520, 390)) i = wx.Icon(BitmapLoader.getBitmap("graphs_small", "gui")) self.SetIcon(i) self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.CreateStatusBar() self.mainSizer = wx.BoxSizer(wx.VERTICAL) self.SetSizer(self.mainSizer) sFit = Fit.getInstance() fit = sFit.getFit(self.mainFrame.getActiveFit()) self.fits = [fit] if fit is not None else [] self.fitList = FitList(self) self.fitList.SetMinSize((270, -1)) self.fitList.fitList.update(self.fits) self.graphSelection = wx.Choice(self, wx.ID_ANY, style=0) self.mainSizer.Add(self.graphSelection, 0, wx.EXPAND) self.figure = Figure(figsize=(4, 3)) rgbtuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas = Canvas(self, -1, self.figure) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) self.subplot = self.figure.add_subplot(111) self.subplot.grid(True) self.mainSizer.Add(self.canvas, 1, wx.EXPAND) self.mainSizer.Add( wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL), 0, wx.EXPAND) self.gridPanel = wx.Panel(self) self.mainSizer.Add(self.gridPanel, 0, wx.EXPAND) dummyBox = wx.BoxSizer(wx.VERTICAL) self.gridPanel.SetSizer(dummyBox) self.gridSizer = wx.FlexGridSizer(0, 4, 0, 0) self.gridSizer.AddGrowableCol(1) dummyBox.Add(self.gridSizer, 0, wx.EXPAND) for view in Graph.views: view = view() self.graphSelection.Append(view.name, view) self.graphSelection.SetSelection(0) self.fields = {} self.select(0) self.sl1 = wx.StaticLine(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.LI_HORIZONTAL) self.mainSizer.Add(self.sl1, 0, wx.EXPAND) self.mainSizer.Add(self.fitList, 0, wx.EXPAND) self.fitList.fitList.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) self.mainFrame.Bind(GE.FIT_CHANGED, self.draw) self.Bind(wx.EVT_CLOSE, self.closeEvent) self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent) self.Fit() self.SetMinSize(self.GetSize()) def handleDrag(self, type, fitID): if type == "fit": self.AppendFitToList(fitID) def closeEvent(self, event): self.closeWindow() event.Skip() def kbEvent(self, event): keycode = event.GetKeyCode() if keycode == wx.WXK_ESCAPE: self.closeWindow() return event.Skip() def closeWindow(self): self.fitList.fitList.Unbind(wx.EVT_LEFT_DCLICK, handler=self.removeItem) self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.draw) self.Destroy() def getView(self): return self.graphSelection.GetClientData( self.graphSelection.GetSelection()) def getValues(self): values = {} for fieldName, field in self.fields.items(): values[fieldName] = field.GetValue() return values def select(self, index): view = self.getView() icons = view.getIcons() labels = view.getLabels() sizer = self.gridSizer self.gridPanel.DestroyChildren() self.fields.clear() # Setup textboxes for field, defaultVal in view.getFields().items(): textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0) self.fields[field] = textBox textBox.Bind(wx.EVT_TEXT, self.onFieldChanged) sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3) if defaultVal is not None: if not isinstance(defaultVal, str): defaultVal = ("%f" % defaultVal).rstrip("0") if defaultVal[-1:] == ".": defaultVal += "0" textBox.ChangeValue(defaultVal) imgLabelSizer = wx.BoxSizer(wx.HORIZONTAL) if icons: icon = icons.get(field) if icon is not None: static = wx.StaticBitmap(self.gridPanel) static.SetBitmap(icon) imgLabelSizer.Add(static, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 1) if labels: label = labels.get(field) label = label if label is not None else field else: label = field imgLabelSizer.Add(wx.StaticText(self.gridPanel, wx.ID_ANY, label), 0, wx.LEFT | wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 3) sizer.Add(imgLabelSizer, 0, wx.ALIGN_CENTER_VERTICAL) self.draw() def draw(self, event=None): global mpl_version if event is not None: event.Skip() # todo: FIX THIS, see #1430. draw() is not being unbound properly when the window closes, this is an easy fix, # but not a proper solution if not self: pyfalog.warning( "GraphFrame handled event, however GraphFrame no longer exists. Ignoring event" ) return values = self.getValues() view = self.getView() self.subplot.clear() self.subplot.grid(True) legend = [] for fit in self.fits: try: success, status = view.getPoints(fit, values) if not success: # TODO: Add a pwetty statys bar to report errors with self.SetStatusText(status) return x, y = success, status self.subplot.plot(x, y) legend.append(fit.name) except Exception as ex: pyfalog.warning("Invalid values in '{0}'", fit.name) self.SetStatusText("Invalid values in '%s'" % fit.name) self.canvas.draw() return if mpl_version < 2: if self.legendFix and len(legend) > 0: leg = self.subplot.legend(tuple(legend), "upper right", shadow=False) for t in leg.get_texts(): t.set_fontsize('small') for l in leg.get_lines(): l.set_linewidth(1) elif not self.legendFix and len(legend) > 0: leg = self.subplot.legend(tuple(legend), "upper right", shadow=False, frameon=False) for t in leg.get_texts(): t.set_fontsize('small') for l in leg.get_lines(): l.set_linewidth(1) elif mpl_version >= 2: legend2 = [] legend_colors = { 0: "blue", 1: "orange", 2: "green", 3: "red", 4: "purple", 5: "brown", 6: "pink", 7: "grey", } for i, i_name in enumerate(legend): try: selected_color = legend_colors[i] except: selected_color = None legend2.append(Patch(color=selected_color, label=i_name), ) if len(legend2) > 0: leg = self.subplot.legend(handles=legend2) for t in leg.get_texts(): t.set_fontsize('small') for l in leg.get_lines(): l.set_linewidth(1) self.canvas.draw() self.SetStatusText("") def onFieldChanged(self, event): self.draw() def AppendFitToList(self, fitID): sFit = Fit.getInstance() fit = sFit.getFit(fitID) if fit not in self.fits: self.fits.append(fit) self.fitList.fitList.update(self.fits) self.draw() def removeItem(self, event): row, _ = self.fitList.fitList.HitTest(event.Position) if row != -1: del self.fits[row] self.fitList.fitList.update(self.fits) self.draw()
class plotBox(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def _init_ctrls(self, prnt): #matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, prnt, -1) Publisher.subscribe(self.monthly, ("box.Monthly")) Publisher.subscribe(self.yearly, ("box.Yearly")) Publisher.subscribe(self.seasonaly, ("box.Seasonal")) Publisher.subscribe(self.overall, ("box.Overall")) self.figure = matplotlib.figure.Figure() self.plot = self.figure.add_subplot(111) self.plot.axis([0, 1, 0, 1]) # self.plot.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, self.figure) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, True) self.toolbar.Realize() #self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_CROSS)) #self.canvas.SetScrollbar(wx.HORIZONTAL, 0,5, 1000) self.SetColor("WHITE") self.canvas.SetFont( wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.canvas.draw() self._init_sizers() def Clear(self): self.figure.clear() def GridSize(self, cells): rows = 1 cols = 1 while rows * cols < cells: if rows == cols: cols = cols + 1 else: rows = rows + 1 return rows, cols def textSize(self, cells): wrap = 50 wrap = wrap - (cells * 3) text = 20 - cells return wrap, text def Plot(self, seriesPlotInfo): self.seriesPlotInfo = seriesPlotInfo self.updatePlot() def updatePlot(self): self.Clear() count = self.seriesPlotInfo.count() rows, cols = self.GridSize(count) self.plots = [] i = 1 for oneSeries in self.seriesPlotInfo.GetSeriesInfo(): self.plots.append( self.figure.add_subplot(repr(rows) + repr(cols) + repr(i))) wrap, text = self.textSize(count) self.plots[i - 1].set_xlabel("\n".join( textwrap.wrap(oneSeries.BoxWhisker.currinterval.title, wrap))) self.plots[i - 1].set_ylabel("\n".join( textwrap.wrap( oneSeries.variableName + "(" + oneSeries.variableUnits + ")", wrap))) self.plots[i - 1].set_title("\n".join( textwrap.wrap( oneSeries.siteName + " " + oneSeries.variableName, wrap))) self.canvas.SetFont( wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) med = oneSeries.BoxWhisker.currinterval.medians cl = oneSeries.BoxWhisker.currinterval.confint mean = oneSeries.BoxWhisker.currinterval.means ci = oneSeries.BoxWhisker.currinterval.conflimit bp = self.plots[i - 1].boxplot( oneSeries.BoxWhisker.currinterval.data, sym="-gs", notch=True, bootstrap=5000, conf_intervals=cl) # Plot Mean and its confidence interval for x in range(len(mean)): self.plots[i - 1].vlines(x + 1, ci[x][0], ci[x][1], color='r', linestyle="solid") self.plots[i - 1].scatter([range(1, len(mean) + 1)], mean, marker='o', c='r', s=10) # Plot Median self.plots[i - 1].scatter([range(1, len(med) + 1)], med, marker='s', c="k", s=10) # Set Colors of the Box Whisker plot plt.setp(bp['whiskers'], color='k', linestyle='-') plt.setp(bp['medians'], color='k', linestyle='-') plt.setp(bp['boxes'], color='GREY', linestyle='-') plt.setp(bp['caps'], color='k') plt.setp(bp['fliers'], markersize=3.5) # self.plot.set_ybound(min(data),max(data)) self.plots[i - 1].set_autoscale_on(True) self.plots[i - 1].set_xticklabels( oneSeries.BoxWhisker.currinterval.xlabels) i = i + 1 self.canvas.draw() def SetColor(self, color): # """Set figure and canvas colours to be the same.""" self.figure.set_facecolor(color) self.figure.set_edgecolor(color) self.canvas.SetBackgroundColour(color) def monthly(self, str): # print "monthly" self.seriesPlotInfo.SetBoxInterval("Monthly") self.updatePlot() def seasonaly(self, str): # print"seasonal" self.seriesPlotInfo.SetBoxInterval("Seasonally") self.updatePlot() def yearly(self, str): # print "yearly" self.seriesPlotInfo.SetBoxInterval("Yearly") self.updatePlot() def overall(self, str): # print "overall" self.seriesPlotInfo.SetBoxInterval("Overall") self.updatePlot() def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class CTRL(wx.Panel): def __init__(self, parent, style=wx.TAB_TRAVERSAL): wx.Panel.__init__(self, parent, id=-1, style=style) self.IDcompte = None self.date_debut = None self.date_fin = None self.figure = matplotlib.pyplot.figure() self.canvas = Canvas(self, -1, self.figure) self.SetColor( (255,255,255) ) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas,1,wx.EXPAND|wx.ALL, 0) self.SetSizer(sizer) def convertCouleur(self, RGB) : couleur = [] for valeur in RGB : couleur.append(valeur/255.0) return couleur def SetColor(self, rgbtuple=None): """Set figure and canvas colours to be the same.""" if rgbtuple is None: rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get() clr = [c/255. for c in rgbtuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgbtuple)) def SetCompte(self, IDcompte=None): self.IDcompte = IDcompte def SetPeriode(self, code="", date_debut=None, date_fin=None): """ Attribue la période """ dateJour = datetime.date.today() self.date_debut = None self.date_fin = None if code == "actuellement" : self.date_debut = dateJour + relativedelta.relativedelta(days=-25) self.date_fin = dateJour + relativedelta.relativedelta(days=+30) if code == "7_prochains_jours" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(days=+7) if code == "14_prochains_jours" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(days=+14) if code == "30_prochains_jours" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(days=+30) if code == "90_prochains_jours" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(days=+90) if code == "6_prochains_mois" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(months=+6) if code == "12_prochains_mois" : self.date_debut = dateJour self.date_fin = dateJour + relativedelta.relativedelta(months=+12) if code == "mois_actuel" : self.date_debut = datetime.date(dateJour.year, dateJour.month, 1) self.date_fin = datetime.date(dateJour.year, dateJour.month, 1) + relativedelta.relativedelta(months=+1) - relativedelta.relativedelta(days=+1) if code == "annee_actuelle" : self.date_debut = datetime.date(dateJour.year, 1, 1) self.date_fin = datetime.date(dateJour.year, 12, 31) if code == "personnalise" : self.date_debut = date_debut self.date_fin = date_fin self.MAJ() def GetDonnees(self): DB = GestionDB.DB() req = """SELECT IDoperation, type, date, IDreleve, montant FROM compta_operations WHERE IDcompte_bancaire=%d ORDER BY date, IDoperation;""" % self.IDcompte DB.ExecuterReq(req) listeOperations = DB.ResultatReq() DB.Close() # Analyse des opérations listeDonnees = [] solde = 0.0 for IDoperation, typeOperation, date, IDreleve, montant in listeOperations : date = UTILS_Dates.DateEngEnDateDD(date) if typeOperation == "debit" : solde -= montant else : solde += montant listeDonnees.append((date, solde)) return listeDonnees def MAJ(self) : self.figure.clear() if self.IDcompte == None or self.date_debut == None or self.date_fin == None : wx.CallAfter(self.SendSizeEvent) return listeDates = [] listeValeurs = [] for date, valeur in self.GetDonnees() : if date >= self.date_debut and date <= self.date_fin : listeDates.append(date) listeValeurs.append(valeur) if len(listeDates) < 2 : wx.CallAfter(self.SendSizeEvent) return ax = self.figure.add_subplot(111) # Sélection du mode d'affichage mode = None nbreJours = (self.date_fin - self.date_debut).days #(max(listeDates) - min(listeDates)).days if nbreJours < 60 : mode = "jour" elif nbreJours < 400 : mode = "mois" else : mode = "annee" # Affichage par année if mode == "annee" : anneeMin = self.date_debut.year anneeMax = self.date_max.year + 1 ax.xaxis.set_major_locator(mdates.YearLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y')) ax.xaxis.set_minor_locator(mdates.MonthLocator()) datemin = datetime.date(anneeMin, 1, 1) datemax = datetime.date(anneeMax, 1, 1) ax.set_xlim(datemin, datemax) ## ax.xaxis.set_major_locator(mdates.AutoDateLocator()) ## ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) ## ax.xaxis.set_major_locator(mdates.DayLocator()) ## ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) if mode == "mois" : ax.xaxis.set_major_locator(mdates.MonthLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y')) if mode == "jour" : ax.xaxis.set_major_locator(mdates.AutoDateLocator()) ## ax.xaxis.set_minor_locator(mdates.DayLocator()) ax.xaxis.set_major_formatter(mdates.DateFormatter('%d/%m/%Y')) ## ax.set_xlim([min(listeDates), max(listeDates)]) ax.set_xlim([self.date_debut, self.date_fin]) ax.fill_between(listeDates, 0, listeValeurs, facecolor='blue', alpha=0.5, label=_(u"Trésorerie")) self.figure.autofmt_xdate() ax.grid(True) ax.figure.canvas.draw() wx.CallAfter(self.SendSizeEvent) return x = [0, 0, 3.5, 4, 5]#np.linspace(0, 1) y = [0, 10, 2, 3, 4] ax.fill(x, y, 'r') ax.grid(True) ax.figure.canvas.draw() return # Création du graph ind = arange(len(listeLabels)) + 0.25 # the x locations for the groups width = 0.5 for x in range(len(listeLabels)) : ## couleur = MODELES.ConvertitCouleur2(MODELES.COULEUR_VERT_POMME) barre = ax.bar(ind[x], listeValeurs[x], width)#, color=couleur) ## # Axe horizontal ## ind = arange(len(listeLabels)) ## ax.set_xticks(ind + width) ## ax.set_xticklabels(listeLabels) ## labelsx = ax.get_xticklabels() ## labelsy = ax.get_yticklabels() ## matplotlib.pyplot.setp(labelsx, rotation=45, fontsize=9, horizontalalignment='right') ## ## # Axe vertical ## ax.set_ylabel("Nbre de familles", fontsize=8) labels = ax.get_yticklabels() matplotlib.pyplot.setp(labels, rotation=0, fontsize=9) # Titre title = ax.set_title(_(u"Comparatif du nombre de familles"), weight="bold", horizontalalignment = 'center')#, position=(0.5, 0.97)) matplotlib.pyplot.setp(title, rotation=0, fontsize=9) self.figure.subplots_adjust(left=None, bottom=0.4, right=None, wspace=None, hspace=None) # Affiche les grilles ax.grid(True) # Re-dessine le canvas ax.figure.canvas.draw()
class MyPlotPanel(wx.Panel): def __init__(self, parent, figsize=None, dpi=None, bgcolor=None, type=None, toolbar=None, aspect=1, **kwargs): """ construction method of MyPlotPanel class :param parent: parent object :param figsize: plot figure size, (w, h) :param dpi: figure dpi, :parma bgcolor: background color of figure and canvas :param type: type of initial figure, 'image' or 'line' :param toolbar: show toolbar if not set None """ wx.Panel.__init__(self, parent, **kwargs) self.parent = parent self.figsize = figsize self.dpi = dpi self.bgcolor = bgcolor self.type = type self.toolbar = toolbar self.aspect = aspect self.figure = Figure(self.figsize, self.dpi) self.canvas = FigureCanvas(self, -1, self.figure) # figure background color self.set_color(self.bgcolor) # initialize plot self._init_plot() # set layout self.set_layout() # binding events self.canvas.mpl_connect('button_press_event', self.on_press) self.canvas.mpl_connect('button_release_event', self.on_release) self.canvas.mpl_connect('motion_notify_event', self.on_motion) self.Bind(wx.EVT_SIZE, self.on_size) def set_layout(self): """ set panel layout """ sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.canvas, 1, wx.EXPAND) hbox = wx.BoxSizer(wx.HORIZONTAL) if self.toolbar is not None: self.toobar = MyToolbar(self.canvas) self.toobar.Realize() hbox.Add(self.toobar, 0, wx.EXPAND | wx.RIGHT, 10) self.pos_st = wx.StaticText(self, label='') hbox.Add(self.pos_st, 0, wx.ALIGN_CENTER_VERTICAL) sizer.Add(hbox, 0, wx.EXPAND | wx.BOTTOM, 0) self.SetSizerAndFit(sizer) def _init_plot(self): if not hasattr(self, 'axes'): self.axes = self.figure.add_subplot(111, aspect=self.aspect) if self.type == 'image': # draw image x = y = np.linspace(-np.pi, np.pi, 100) self.x, self.y = np.meshgrid(x, y) self.z = self._func_peaks(self.x, self.y) self.image = self.axes.imshow(self.z) else: # draw line self.x = np.linspace(-10, 10, 200) self.y = np.sin(self.x) self.line, = self.axes.plot(self.x, self.y) def set_color(self, rgb_tuple): """ set figure and canvas with the same color. :param rgb_tuple: rgb color tuple, e.g. (255, 255, 255) for white color """ if rgb_tuple is None: rgb_tuple = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() clr = [c / 255.0 for c in rgb_tuple] self.figure.set_facecolor(clr) self.figure.set_edgecolor(clr) self.canvas.SetBackgroundColour(wx.Colour(*rgb_tuple)) def on_size(self, event): self.fit_canvas() self.canvas.draw_idle() event.Skip() def on_press(self, event): pass def on_release(self, event): pass def on_motion(self, event): if event.inaxes is not None: self.pos_st.SetLabel("({x:<.4f}, {y:<.4f})".format(x=event.xdata, y=event.ydata)) def fit_canvas(self): """ tight fit canvas layout """ # self.canvas.SetSize(self.GetSize()) self.figure.set_tight_layout(True) def _func_peaks(self, x, y): return 3.0 * (1.0 - x) ** 2.0 * np.exp(-(x ** 2) - (y + 1) ** 2) \ - 10 * (x / 5 - x ** 3 - y ** 5) * np.exp(-x ** 2 - y ** 2) \ - 1.0 / 3.0 * np.exp(-(x + 1) ** 2 - y ** 2)
class plotHist(wx.Panel): def _init_coll_boxSizer1_Items(self, parent): # generated method, don't edit parent.AddWindow(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW) parent.AddWindow(self.toolbar, 0, wx.EXPAND) def _init_sizers(self): # generated method, don't edit self.boxSizer1 = wx.BoxSizer(orient=wx.VERTICAL) self._init_coll_boxSizer1_Items(self.boxSizer1) self.SetSizer(self.boxSizer1) def _init_ctrls(self, prnt): #matplotlib.figure.Figure.__init__(self) wx.Panel.__init__(self, prnt, -1) self.figure = matplotlib.figure.Figure() self.plot=self.figure.add_subplot(111) self.plot.set_title("No Data To Plot") self.canvas = FigCanvas(self, -1, self.figure) # Create the navigation toolbar, tied to the canvas self.toolbar = NavigationToolbar(self.canvas, True) self.toolbar.Realize() self.SetColor("WHITE") self.canvas.SetFont(wx.Font(20, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.canvas.draw() self._init_sizers() self.hist=[] self.bins=50 def ChangeNumOfBins(self, bins): self.bins = bins self.updatePlot() def Clear(self): self.figure.clear() self.hist=[] def GridSize(self, cells): rows = 1 cols = 1 while rows * cols < cells: if rows == cols: cols = cols + 1 else: rows = rows + 1 return rows, cols def textSize(self, cells): wrap = 50 wrap = wrap-(cells*3) text= 20 -cells return wrap, text def Plot(self, seriesPlotInfo): self.seriesPlotInfo= seriesPlotInfo self.updatePlot() def updatePlot(self): self.Clear() count = self.seriesPlotInfo.count() rows, cols = self.GridSize(count) self.plots=[] i=1 for oneSeries in self.seriesPlotInfo.GetSeriesInfo(): self.plots.append(self.figure.add_subplot(repr(rows)+repr(cols)+repr(i))) wrap, text = self.textSize(count) self.plots[i-1].set_xlabel("\n".join(textwrap.wrap(oneSeries.variableName,wrap))) self.plots[i-1].set_ylabel("Number of Observations") self.canvas.SetFont(wx.Font(text, wx.SWISS, wx.NORMAL, wx.NORMAL, False, u'Tahoma')) self.plots[i-1].set_title("\n".join(textwrap.wrap(oneSeries.siteName+" "+oneSeries.variableName,wrap))) self.hist.append(self.plots[i-1].hist([x[0] for x in oneSeries.dataTable], bins=self.bins, normed=False, facecolor='g', alpha=0.75, label = oneSeries.siteName+" "+oneSeries.variableName)) i=i+1 self.canvas.draw() def SetColor( self, color): """Set figure and canvas colours to be the same.""" self.figure.set_facecolor( color ) self.figure.set_edgecolor( color ) self.canvas.SetBackgroundColour( color ) def __init__(self, parent, id, pos, size, style, name): self._init_ctrls(parent)
class PlotPanelMPL(wx.Panel): def __init__(self, parent): global graphFrame_enabled global mplImported global mpl_version if not graphFrame_enabled: pyfalog.warning( "Matplotlib is not enabled. Skipping initialization.") raise Exception() try: cache_dir = mpl._get_cachedir() except: cache_dir = os.path.expanduser(os.path.join("~", ".matplotlib")) cache_file = os.path.join(cache_dir, 'fontList.cache') if os.access(cache_dir, os.W_OK | os.X_OK) and os.path.isfile(cache_file): # remove matplotlib font cache, see #234 os.remove(cache_file) if not mplImported: mpl.use('wxagg') graphFrame_enabled = True self.legendFix = False if int(mpl.__version__[0]) < 1: print("pyfa: Found matplotlib version ", mpl.__version__, " - activating OVER9000 workarounds") print("pyfa: Recommended minimum matplotlib version is 1.0.0") self.legendFix = True mplImported = True wx.Panel.__init__(self, parent) self.sizer = wx.FlexGridSizer(2, 2) self.sizer.AddGrowableRow(0) self.sizer.AddGrowableCol(1) self.SetSizer(self.sizer) self.labelY = wx.StaticText( self, label="") # TODO custom control for rotated text? self.sizer.Add(self.labelY, flag=wx.ALIGN_CENTER | wx.ALL, border=3) self.figure = Figure(figsize=(4, 3)) colorByte = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE).Get() colorFloat = [c / 255. for c in colorByte] self.figure.set_facecolor(colorFloat) self.figure.set_edgecolor(colorFloat) self.subplot = self.figure.add_axes([0, 0, 1, 1]) self.canvas = Canvas(self, -1, self.figure) self.canvas.SetBackgroundColour(wx.Colour(*colorByte)) self.canvas.mpl_connect('pick_event', lambda event: self.onPick(event)) self.canvas.mpl_connect('button_press_event', lambda event: self.onPlotClick(event)) self.sizer.Add(self.canvas, proportion=1, flag=wx.EXPAND) self.sizer.Add(wx.StaticText(self, label=""), flag=wx.ALIGN_CENTER | wx.ALL, border=3) self.labelX = wx.StaticText(self, label="") self.sizer.Add(self.labelX, flag=wx.ALIGN_CENTER | wx.ALL, border=3) self._parent = parent self._lines = {} self.ondrag = None self.onrelease = None def draw(self, lineData, markerX=None): self._lines.clear() self.maxX = 1 self.maxY = 1 self.subplot.clear() self.subplot.grid(True) for lineID, xdata, ydata, markerY, color, selected in lineData: self._lines[lineID], = self.subplot.plot( xdata, ydata, color=color, linewidth=(2 if selected else 1), picker=5) self.maxX = max(self.maxX, max(xdata)) self.maxY = max(self.maxY, max(ydata)) if markerX and (markerY is not None): self.subplot.annotate("%.1f" % (markerY, ), xy=(markerX, markerY), xytext=(-1, 1), textcoords="offset pixels", ha="right", va="bottom", fontsize="small") if markerX: self.subplot.axvline(x=markerX, linestyle="dotted", linewidth=1, color=(0, 0, 0)) self.subplot.annotate("@ %.1f" % (markerX, ), xy=(markerX, self.maxY * 1.1), xytext=(-1, -1), textcoords="offset pixels", ha="right", va="top", fontsize="small") self.subplot.set_xlim(left=0, right=self.maxX * 1.05) self.subplot.set_ylim(bottom=0, top=self.maxY * 1.1) self.subplot.tick_params(direction="in", width=2, length=6) self.subplot.tick_params(axis="x", pad=-5.0) tickvalues = mpl.ticker.MaxNLocator(nbins=15, steps=[1, 2, 5, 10], integer=True, min_n_ticks=10, prune="lower").tick_values( 0, self.maxX * 1.025) xticks = list(int(v) for v in tickvalues) self.subplot.set_xticks(xticks) self.subplot.set_xticklabels(xticks, va="bottom") self.subplot.tick_params(axis="y", pad=-8.0) tickvalues = mpl.ticker.MaxNLocator(nbins=12, steps=[1, 2, 5, 10], integer=True, min_n_ticks=8, prune="lower").tick_values( 0, self.maxY * 1.05) yticks = list(int(v) for v in tickvalues) self.subplot.set_yticks(yticks) self.subplot.set_yticklabels(yticks, ha="left") self.canvas.draw() def onPlotClick(self, event): if event.button == 3: self._parent.setMarkerX(event.xdata) if not self.ondrag: self.ondrag = self.canvas.mpl_connect( 'motion_notify_event', lambda event: self.onPlotDrag(event)) if not self.onrelease: self.onrelease = self.canvas.mpl_connect( 'button_release_event', lambda event: self.onPlotRelease(event)) def onPlotDrag(self, event): self._parent.setMarkerX(event.xdata) def onPlotRelease(self, event): if event.button == 3: self._parent.setMarkerX(event.xdata) if self.ondrag: self.canvas.mpl_disconnect(self.ondrag) self.ondrag = None if self.onrelease: self.canvas.mpl_disconnect(self.onrelease) self.onrelease = None def onPick(self, event): for lineID, line in self._lines.iteritems(): if line == event.artist: self._parent.setSelectedLine(lineID)