From 6ef7d83d974bc4fc7460bac05bbc3f0a75b6263d Mon Sep 17 00:00:00 2001 From: Robin Dunn Date: Sat, 11 Oct 2014 19:58:21 +0000 Subject: [PATCH] Apply patch updating wx.lib.plot, closes #16590 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxPython/Phoenix/trunk@78006 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- wx/lib/plot.py | 1299 ++++++++++++++++++++++++++---------------------- 1 file changed, 706 insertions(+), 593 deletions(-) diff --git a/wx/lib/plot.py b/wx/lib/plot.py index a1635f14..c9d83a06 100644 --- a/wx/lib/plot.py +++ b/wx/lib/plot.py @@ -108,16 +108,16 @@ Zooming controls with mouse (when enabled): Right mouse click - zoom out centred on click location. """ -import string as _string -import time as _time -import sys -import wx +import string as _string +import time as _time +import sys +import wx # Needs NumPy try: import numpy as np except: - msg= """ + msg = """ This module requires the NumPy module, which could not be imported. It probably is not installed (it's not part of the standard Python distribution). See the Numeric Python site @@ -126,11 +126,11 @@ except: raise ImportError("NumPy not found.\n" + msg) - # # Plotting classes... # class PolyPoints: + """Base Class for lines and markers - All methods are private. """ @@ -139,14 +139,15 @@ class PolyPoints: self._points = np.array(points).astype(np.float64) self._logscale = (False, False) self._pointSize = (1.0, 1.0) - self.currentScale= (1,1) - self.currentShift= (0,0) + self.currentScale = (1, 1) + self.currentShift = (0, 0) self.scaled = self.points self.attributes = {} self.attributes.update(self._attributes) for name, value in attr.items(): if name not in self._attributes.keys(): - raise KeyError("Style attribute incorrect. Should be one of %s" % self._attributes.keys()) + raise KeyError( + "Style attribute incorrect. Should be one of %s" % self._attributes.keys()) self.attributes[name] = value def setLogScale(self, logscale): @@ -154,8 +155,8 @@ class PolyPoints: def __getattr__(self, name): if name == 'points': - if len(self._points)>0: - data = np.array(self._points,copy=True) + if len(self._points) > 0: + data = np.array(self._points, copy=True) if self._logscale[0]: data = self.log10(data, 0) if self._logscale[1]: @@ -167,57 +168,58 @@ class PolyPoints: raise AttributeError(name) def log10(self, data, ind): - data = np.compress(data[:,ind]>0,data,0) - data[:,ind] = np.log10(data[:,ind]) + data = np.compress(data[:, ind] > 0, data, 0) + data[:, ind] = np.log10(data[:, ind]) return data def boundingBox(self): if len(self.points) == 0: # no curves to draw # defaults to (-1,-1) and (1,1) but axis can be set in Draw - minXY= np.array([-1.0,-1.0]) - maxXY= np.array([ 1.0, 1.0]) + minXY = np.array([-1.0, -1.0]) + maxXY = np.array([1.0, 1.0]) else: - minXY= np.minimum.reduce(self.points) - maxXY= np.maximum.reduce(self.points) + minXY = np.minimum.reduce(self.points) + maxXY = np.maximum.reduce(self.points) return minXY, maxXY - def scaleAndShift(self, scale=(1,1), shift=(0,0)): + def scaleAndShift(self, scale=(1, 1), shift=(0, 0)): if len(self.points) == 0: # no curves to draw return if (scale is not self.currentScale) or (shift is not self.currentShift): # update point scaling - self.scaled = scale*self.points+shift - self.currentScale= scale - self.currentShift= shift + self.scaled = scale * self.points + shift + self.currentScale = scale + self.currentShift = shift # else unchanged use the current scaling def getLegend(self): return self.attributes['legend'] - def getClosestPoint(self, pntXY, pointScaled= True): + def getClosestPoint(self, pntXY, pointScaled=True): """Returns the index of closest point on the curve, pointXY, scaledXY, distance x, y in user coords if pointScaled == True based on screen coords if pointScaled == False based on user coords """ if pointScaled == True: - #Using screen coords + # Using screen coords p = self.scaled - pxy = self.currentScale * np.array(pntXY)+ self.currentShift + pxy = self.currentScale * np.array(pntXY) + self.currentShift else: - #Using user coords + # Using user coords p = self.points pxy = np.array(pntXY) - #determine distance for each point - d= np.sqrt(np.add.reduce((p-pxy)**2,1)) #sqrt(dx^2+dy^2) + # determine distance for each point + d = np.sqrt(np.add.reduce((p - pxy) ** 2, 1)) # sqrt(dx^2+dy^2) pntIndex = np.argmin(d) dist = d[pntIndex] return [pntIndex, self.points[pntIndex], self.scaled[pntIndex] / self._pointSize, dist] class PolyLine(PolyPoints): + """Class to define line type and style - All methods except __init__ are private. """ @@ -244,28 +246,30 @@ class PolyLine(PolyPoints): """ PolyPoints.__init__(self, points, attr) - def draw(self, dc, printerScale, coord= None): + def draw(self, dc, printerScale, coord=None): colour = self.attributes['colour'] width = self.attributes['width'] * printerScale * self._pointSize[0] - style= self.attributes['style'] + style = self.attributes['style'] if not isinstance(colour, wx.Colour): colour = wx.Colour(colour) pen = wx.Pen(colour, width, style) pen.SetCap(wx.CAP_BUTT) dc.SetPen(pen) if coord == None: - if len(self.scaled): # bugfix for Mac OS X + if len(self.scaled): # bugfix for Mac OS X dc.DrawLines(self.scaled) else: - dc.DrawLines(coord) # draw legend line + dc.DrawLines(coord) # draw legend line def getSymExtent(self, printerScale): """Width and Height of Marker""" - h= self.attributes['width'] * printerScale * self._pointSize[0] - w= 5 * h - return (w,h) + h = self.attributes['width'] * printerScale * self._pointSize[0] + w = 5 * h + return (w, h) + class PolySpline(PolyLine): + """Class to define line type and style - All methods except __init__ are private. """ @@ -292,22 +296,24 @@ class PolySpline(PolyLine): """ PolyLine.__init__(self, points, **attr) - def draw(self, dc, printerScale, coord= None): + def draw(self, dc, printerScale, coord=None): colour = self.attributes['colour'] width = self.attributes['width'] * printerScale * self._pointSize[0] - style= self.attributes['style'] + style = self.attributes['style'] if not isinstance(colour, wx.Colour): colour = wx.Colour(colour) pen = wx.Pen(colour, width, style) pen.SetCap(wx.CAP_ROUND) dc.SetPen(pen) if coord == None: - if len(self.scaled): # bugfix for Mac OS X + if len(self.scaled): # bugfix for Mac OS X dc.DrawSpline(self.scaled) else: - dc.DrawLines(coord) # draw legend line + dc.DrawLines(coord) # draw legend line + class PolyMarker(PolyPoints): + """Class to define marker type and style - All methods except __init__ are private. """ @@ -350,7 +356,7 @@ class PolyMarker(PolyPoints): PolyPoints.__init__(self, points, attr) - def draw(self, dc, printerScale, coord= None): + def draw(self, dc, printerScale, coord=None): colour = self.attributes['colour'] width = self.attributes['width'] * printerScale * self._pointSize[0] size = self.attributes['size'] * printerScale * self._pointSize[0] @@ -365,90 +371,95 @@ class PolyMarker(PolyPoints): dc.SetPen(wx.Pen(colour, width)) if fillcolour: - dc.SetBrush(wx.Brush(fillcolour,fillstyle)) + dc.SetBrush(wx.Brush(fillcolour, fillstyle)) else: dc.SetBrush(wx.Brush(colour, fillstyle)) if coord == None: - if len(self.scaled): # bugfix for Mac OS X + if len(self.scaled): # bugfix for Mac OS X self._drawmarkers(dc, self.scaled, marker, size) else: - self._drawmarkers(dc, coord, marker, size) # draw legend marker + self._drawmarkers(dc, coord, marker, size) # draw legend marker def getSymExtent(self, printerScale): """Width and Height of Marker""" - s= 5*self.attributes['size'] * printerScale * self._pointSize[0] - return (s,s) + s = 5 * self.attributes['size'] * printerScale * self._pointSize[0] + return (s, s) - def _drawmarkers(self, dc, coords, marker,size=1): - f = eval('self._' +marker) + def _drawmarkers(self, dc, coords, marker, size=1): + f = eval('self._' + marker) f(dc, coords, size) def _circle(self, dc, coords, size=1): - fact= 2.5*size - wh= 5.0*size - rect= np.zeros((len(coords),4),np.float)+[0.0,0.0,wh,wh] - rect[:,0:2]= coords-[fact,fact] + fact = 2.5 * size + wh = 5.0 * size + rect = np.zeros((len(coords), 4), np.float) + [0.0, 0.0, wh, wh] + rect[:, 0:2] = coords - [fact, fact] dc.DrawEllipseList(rect.astype(np.int32)) def _dot(self, dc, coords, size=1): dc.DrawPointList(coords) def _square(self, dc, coords, size=1): - fact= 2.5*size - wh= 5.0*size - rect= np.zeros((len(coords),4),np.float)+[0.0,0.0,wh,wh] - rect[:,0:2]= coords-[fact,fact] + fact = 2.5 * size + wh = 5.0 * size + rect = np.zeros((len(coords), 4), np.float) + [0.0, 0.0, wh, wh] + rect[:, 0:2] = coords - [fact, fact] dc.DrawRectangleList(rect.astype(np.int32)) def _triangle(self, dc, coords, size=1): - shape= [(-2.5*size,1.44*size), (2.5*size,1.44*size), (0.0,-2.88*size)] - poly= np.repeat(coords,3) - poly.shape= (len(coords),3,2) + shape = [(-2.5 * size, 1.44 * size), + (2.5 * size, 1.44 * size), (0.0, -2.88 * size)] + poly = np.repeat(coords, 3, 0) + poly.shape = (len(coords), 3, 2) poly += shape dc.DrawPolygonList(poly.astype(np.int32)) def _triangle_down(self, dc, coords, size=1): - shape= [(-2.5*size,-1.44*size), (2.5*size,-1.44*size), (0.0,2.88*size)] - poly= np.repeat(coords,3) - poly.shape= (len(coords),3,2) + shape = [(-2.5 * size, -1.44 * size), + (2.5 * size, -1.44 * size), (0.0, 2.88 * size)] + poly = np.repeat(coords, 3, 0) + poly.shape = (len(coords), 3, 2) poly += shape dc.DrawPolygonList(poly.astype(np.int32)) def _cross(self, dc, coords, size=1): - fact= 2.5*size - for f in [[-fact,-fact,fact,fact],[-fact,fact,fact,-fact]]: - lines= np.concatenate((coords,coords),axis=1)+f + fact = 2.5 * size + for f in [[-fact, -fact, fact, fact], [-fact, fact, fact, -fact]]: + lines = np.concatenate((coords, coords), axis=1) + f dc.DrawLineList(lines.astype(np.int32)) def _plus(self, dc, coords, size=1): - fact= 2.5*size - for f in [[-fact,0,fact,0],[0,-fact,0,fact]]: - lines= np.concatenate((coords,coords),axis=1)+f + fact = 2.5 * size + for f in [[-fact, 0, fact, 0], [0, -fact, 0, fact]]: + lines = np.concatenate((coords, coords), axis=1) + f dc.DrawLineList(lines.astype(np.int32)) + class PlotGraphics: + """Container to hold PolyXXX objects and graph labels - All methods except __init__ are private. """ - def __init__(self, objects, title='', xLabel='', yLabel= ''): + def __init__(self, objects, title='', xLabel='', yLabel=''): """Creates PlotGraphics object objects - list of PolyXXX objects to make graph title - title shown at top of graph xLabel - label shown on x-axis yLabel - label shown on y-axis """ - if type(objects) not in [list,tuple]: + if type(objects) not in [list, tuple]: raise TypeError("objects argument should be list or tuple") self.objects = objects - self.title= title - self.xLabel= xLabel - self.yLabel= yLabel + self.title = title + self.xLabel = xLabel + self.yLabel = yLabel self._pointSize = (1.0, 1.0) def setLogScale(self, logscale): if type(logscale) != tuple: - raise TypeError('logscale must be a tuple of bools, e.g. (False, False)') + raise TypeError( + 'logscale must be a tuple of bools, e.g. (False, False)') if len(self.objects) == 0: return for o in self.objects: @@ -462,25 +473,25 @@ class PlotGraphics: p2 = np.maximum(p2, p2o) return p1, p2 - def scaleAndShift(self, scale=(1,1), shift=(0,0)): + def scaleAndShift(self, scale=(1, 1), shift=(0, 0)): for o in self.objects: o.scaleAndShift(scale, shift) def setPrinterScale(self, scale): """Thickens up lines and markers only for printing""" - self.printerScale= scale + self.printerScale = scale - def setXLabel(self, xLabel= ''): + def setXLabel(self, xLabel=''): """Set the X axis label on the graph""" - self.xLabel= xLabel + self.xLabel = xLabel - def setYLabel(self, yLabel= ''): + def setYLabel(self, yLabel=''): """Set the Y axis label on the graph""" - self.yLabel= yLabel + self.yLabel = yLabel - def setTitle(self, title= ''): + def setTitle(self, title=''): """Set the title at the top of graph""" - self.title= title + self.title = title def getXLabel(self): """Get x axis label string""" @@ -490,13 +501,13 @@ class PlotGraphics: """Get y axis label string""" return self.yLabel - def getTitle(self, title= ''): + def getTitle(self, title=''): """Get the title at the top of graph""" return self.title def draw(self, dc): for o in self.objects: - #t=_time.clock() # profile info + # t=_time.clock() # profile info o._pointSize = self._pointSize o.draw(dc, self.printerScale) #dt= _time.clock()-t @@ -514,9 +525,9 @@ class PlotGraphics: def getLegendNames(self): """Returns list of legend names""" - lst = [None]*len(self) + lst = [None] * len(self) for i in range(len(self)): - lst[i]= self.objects[i].getLegend() + lst[i] = self.objects[i].getLegend() return lst def __len__(self): @@ -526,10 +537,11 @@ class PlotGraphics: return self.objects[item] -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------- # Main window that you will want to import into your application. class PlotCanvas(wx.Panel): + """ Subclass of a wx.Panel which holds two scrollbars and the actual plotting canvas (self.canvas). It allows for simple general plotting @@ -542,17 +554,17 @@ class PlotCanvas(wx.Panel): wx.Panel.__init__(self, parent, id, pos, size, style, name) - sizer = wx.FlexGridSizer(2,2,0,0) + sizer = wx.FlexGridSizer(2, 2, 0, 0) self.canvas = wx.Window(self, -1) self.sb_vert = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL) - self.sb_vert.SetScrollbar(0,1000,1000,1000) + self.sb_vert.SetScrollbar(0, 1000, 1000, 1000) self.sb_hor = wx.ScrollBar(self, -1, style=wx.SB_HORIZONTAL) - self.sb_hor.SetScrollbar(0,1000,1000,1000) + self.sb_hor.SetScrollbar(0, 1000, 1000, 1000) sizer.Add(self.canvas, 1, wx.EXPAND) sizer.Add(self.sb_vert, 0, wx.EXPAND) sizer.Add(self.sb_hor, 0, wx.EXPAND) - sizer.Add((0,0)) + sizer.Add((0, 0)) sizer.AddGrowableRow(0, 1) sizer.AddGrowableCol(0, 1) @@ -563,7 +575,7 @@ class PlotCanvas(wx.Panel): self.SetSizer(sizer) self.Fit() - self.border = (1,1) + self.border = (1, 1) self.SetBackgroundColour("white") @@ -589,9 +601,9 @@ class PlotCanvas(wx.Panel): # Things for printing self._print_data = None - self._pageSetupData= None + self._pageSetupData = None self.printerScale = 1 - self.parent= parent + self.parent = parent # scrollbar variables self._sb_ignore = False @@ -607,40 +619,41 @@ class PlotCanvas(wx.Panel): self._logscale = (False, False) # Zooming variables - self._zoomInFactor = 0.5 + self._zoomInFactor = 0.5 self._zoomOutFactor = 2 - self._zoomCorner1= np.array([0.0, 0.0]) # left mouse down corner - self._zoomCorner2= np.array([0.0, 0.0]) # left mouse up corner - self._zoomEnabled= False - self._hasDragged= False + self._zoomCorner1 = np.array([0.0, 0.0]) # left mouse down corner + self._zoomCorner2 = np.array([0.0, 0.0]) # left mouse up corner + self._zoomEnabled = False + self._hasDragged = False # Drawing Variables self.last_draw = None - self._pointScale= 1 - self._pointShift= 0 - self._xSpec= 'auto' - self._ySpec= 'auto' - self._gridEnabled= False - self._legendEnabled= False - self._titleEnabled= True + self._pointScale = 1 + self._pointShift = 0 + self._xSpec = 'auto' + self._ySpec = 'auto' + self._gridEnabled = False + self._legendEnabled = False + self._titleEnabled = True self._centerLinesEnabled = False self._diagonalsEnabled = False # Fonts self._fontCache = {} - self._fontSizeAxis= 10 - self._fontSizeTitle= 15 - self._fontSizeLegend= 7 + self._fontSizeAxis = 10 + self._fontSizeTitle = 15 + self._fontSizeLegend = 7 # pointLabels - self._pointLabelEnabled= False - self.last_PointLabel= None - self._pointLabelFunc= None + self._pointLabelEnabled = False + self.last_PointLabel = None + self._pointLabelFunc = None self.canvas.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave) if sys.platform != "darwin": self._logicalFunction = wx.EQUIV # (NOT src) XOR dst else: - self._logicalFunction = wx.COPY # wx.EQUIV not supported on Mac OS X + # wx.EQUIV not supported on Mac OS X + self._logicalFunction = wx.COPY self._useScientificNotation = False @@ -654,7 +667,7 @@ class PlotCanvas(wx.Panel): # OnSize called to make sure the buffer is initialized. # This might result in OnSize getting called twice on some # platforms at initialization, but little harm done. - self.OnSize(None) # sets the initial size based on client size + self.OnSize(None) # sets the initial size based on client size self._gridColour = wx.BLACK @@ -670,9 +683,8 @@ class PlotCanvas(wx.Panel): else: self._gridColour = wx.Colour(colour) - # SaveFile - def SaveFile(self, fileName= ''): + def SaveFile(self, fileName=''): """Saves the file to the type specified in the extension. If no file name is specified a dialog box is provided. Returns True if sucessful, otherwise False. @@ -689,7 +701,7 @@ class PlotCanvas(wx.Panel): "xpm": wx.BITMAP_TYPE_XPM, # Save an XPM bitmap file. "jpg": wx.BITMAP_TYPE_JPEG, # Save a JPG file. "png": wx.BITMAP_TYPE_PNG, # Save a PNG file. - } + } fType = _string.lower(fileName[-3:]) dlg1 = None @@ -697,19 +709,20 @@ class PlotCanvas(wx.Panel): if dlg1: # FileDialog exists: Check for extension dlg2 = wx.MessageDialog(self, 'File name extension\n' - 'must be one of\nbmp, xbm, xpm, png, or jpg', - 'File Name Error', wx.OK | wx.ICON_ERROR) + 'must be one of\nbmp, xbm, xpm, png, or jpg', + 'File Name Error', wx.OK | wx.ICON_ERROR) try: dlg2.ShowModal() finally: dlg2.Destroy() - else: # FileDialog doesn't exist: just check one + # FileDialog doesn't exist: just check one + else: dlg1 = wx.FileDialog( self, "Choose a file with extension bmp, gif, xbm, xpm, png, or jpg", ".", "", "BMP files (*.bmp)|*.bmp|XBM files (*.xbm)|*.xbm|XPM file (*.xpm)|*.xpm|PNG files (*.png)|*.png|JPG files (*.jpg)|*.jpg", - wx.SAVE|wx.OVERWRITE_PROMPT - ) + wx.SAVE | wx.OVERWRITE_PROMPT + ) if dlg1.ShowModal() == wx.ID_OK: fileName = dlg1.GetPath() @@ -722,7 +735,7 @@ class PlotCanvas(wx.Panel): dlg1.Destroy() # Save Bitmap - res= self._Buffer.SaveFile(fileName, extensions[fType]) + res = self._Buffer.SaveFile(fileName, extensions[fType]) return res @property @@ -736,9 +749,9 @@ class PlotCanvas(wx.Panel): @property def pageSetupData(self): if not self._pageSetupData: - self._pageSetupData= wx.PageSetupDialogData() - self._pageSetupData.SetMarginBottomRight((25,25)) - self._pageSetupData.SetMarginTopLeft((25,25)) + self._pageSetupData = wx.PageSetupDialogData() + self._pageSetupData.SetMarginBottomRight((25, 25)) + self._pageSetupData.SetMarginTopLeft((25, 25)) self._pageSetupData.SetPrintData(self.print_data) return self._pageSetupData @@ -749,12 +762,14 @@ class PlotCanvas(wx.Panel): dlg = wx.PageSetupDialog(self.parent, data) try: if dlg.ShowModal() == wx.ID_OK: - data = dlg.GetPageSetupData() # returns wx.PageSetupDialogData + data = dlg.GetPageSetupData() # returns wx.PageSetupDialogData # updates page parameters from dialog - self.pageSetupData.SetMarginBottomRight(data.GetMarginBottomRight()) + self.pageSetupData.SetMarginBottomRight( + data.GetMarginBottomRight()) self.pageSetupData.SetMarginTopLeft(data.GetMarginTopLeft()) self.pageSetupData.SetPrintData(data.GetPrintData()) - self._print_data=wx.PrintData(data.GetPrintData()) # updates print_data + self._print_data = wx.PrintData( + data.GetPrintData()) # updates print_data finally: dlg.Destroy() @@ -767,7 +782,8 @@ class PlotCanvas(wx.Panel): out = PlotPrintout(self) print_ok = printer.Print(self.parent, out) if print_ok: - self._print_data = wx.PrintData(printer.GetPrintDialogData().GetPrintData()) + self._print_data = wx.PrintData( + printer.GetPrintDialogData().GetPrintData()) out.Destroy() def PrintPreview(self): @@ -776,26 +792,27 @@ class PlotCanvas(wx.Panel): printout2 = PlotPrintout(self) self.preview = wx.PrintPreview(printout, printout2, self.print_data) if not self.preview.IsOk(): - wx.MessageDialog(self, "Print Preview failed.\n" \ - "Check that default printer is configured\n", \ - "Print error", wx.OK|wx.CENTRE).ShowModal() + wx.MessageDialog(self, "Print Preview failed.\n" + "Check that default printer is configured\n", + "Print error", wx.OK | wx.CENTRE).ShowModal() self.preview.SetZoom(40) # search up tree to find frame instance - frameInst= self + frameInst = self while not isinstance(frameInst, wx.Frame): - frameInst= frameInst.GetParent() + frameInst = frameInst.GetParent() frame = wx.PreviewFrame(self.preview, frameInst, "Preview") frame.Initialize() frame.SetPosition(self.GetPosition()) - frame.SetSize((600,550)) + frame.SetSize((600, 550)) frame.Centre(wx.BOTH) frame.Show(True) def setLogScale(self, logscale): if type(logscale) != tuple: - raise TypeError('logscale must be a tuple of bools, e.g. (False, False)') + raise TypeError( + 'logscale must be a tuple of bools, e.g. (False, False)') if self.last_draw is not None: - graphics, xAxis, yAxis= self.last_draw + graphics, xAxis, yAxis = self.last_draw graphics.setLogScale(logscale) self.last_draw = (graphics, None, None) self.SetXSpec('min') @@ -805,25 +822,25 @@ class PlotCanvas(wx.Panel): def getLogScale(self): return self._logscale - def SetFontSizeAxis(self, point= 10): + def SetFontSizeAxis(self, point=10): """Set the tick and axis label font size (default is 10 point)""" - self._fontSizeAxis= point + self._fontSizeAxis = point def GetFontSizeAxis(self): """Get current tick and axis label font size in points""" return self._fontSizeAxis - def SetFontSizeTitle(self, point= 15): + def SetFontSizeTitle(self, point=15): """Set Title font size (default is 15 point)""" - self._fontSizeTitle= point + self._fontSizeTitle = point def GetFontSizeTitle(self): """Get current Title font size in points""" return self._fontSizeTitle - def SetFontSizeLegend(self, point= 7): + def SetFontSizeLegend(self, point=7): """Set Legend font size (default is 7 point)""" - self._fontSizeLegend= point + self._fontSizeLegend = point def GetFontSizeLegend(self): """Get current Legend font size in points""" @@ -831,7 +848,7 @@ class PlotCanvas(wx.Panel): def SetShowScrollbars(self, value): """Set True to show scrollbars""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") if value == self.GetShowScrollbars(): return @@ -867,7 +884,7 @@ class PlotCanvas(wx.Panel): def SetEnableDrag(self, value): """Set True to enable drag.""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") if value: if self.GetEnableZoom(): @@ -882,7 +899,7 @@ class PlotCanvas(wx.Panel): def SetEnableZoom(self, value): """Set True to enable zooming.""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") if value: if self.GetEnableDrag(): @@ -890,7 +907,7 @@ class PlotCanvas(wx.Panel): self.SetCursor(self.MagCursor) else: self.SetCursor(wx.CROSS_CURSOR) - self._zoomEnabled= value + self._zoomEnabled = value def GetEnableZoom(self): """True if zooming enabled.""" @@ -898,9 +915,10 @@ class PlotCanvas(wx.Panel): def SetEnableGrid(self, value): """Set True, 'Horizontal' or 'Vertical' to enable grid.""" - if value not in [True,False,'Horizontal','Vertical']: - raise TypeError("Value should be True, False, Horizontal or Vertical") - self._gridEnabled= value + if value not in [True, False, 'Horizontal', 'Vertical']: + raise TypeError( + "Value should be True, False, Horizontal or Vertical") + self._gridEnabled = value self.Redraw() def GetEnableGrid(self): @@ -909,9 +927,10 @@ class PlotCanvas(wx.Panel): def SetEnableCenterLines(self, value): """Set True, 'Horizontal' or 'Vertical' to enable center line(s).""" - if value not in [True,False,'Horizontal','Vertical']: - raise TypeError("Value should be True, False, Horizontal or Vertical") - self._centerLinesEnabled= value + if value not in [True, False, 'Horizontal', 'Vertical']: + raise TypeError( + "Value should be True, False, Horizontal or Vertical") + self._centerLinesEnabled = value self.Redraw() def GetEnableCenterLines(self): @@ -921,9 +940,10 @@ class PlotCanvas(wx.Panel): def SetEnableDiagonals(self, value): """Set True, 'Bottomleft-Topright' or 'Bottomright-Topleft' to enable center line(s).""" - if value not in [True,False,'Bottomleft-Topright','Bottomright-Topleft']: - raise TypeError("Value should be True, False, Bottomleft-Topright or Bottomright-Topleft") - self._diagonalsEnabled= value + if value not in [True, False, 'Bottomleft-Topright', 'Bottomright-Topleft']: + raise TypeError( + "Value should be True, False, Bottomleft-Topright or Bottomright-Topleft") + self._diagonalsEnabled = value self.Redraw() def GetEnableDiagonals(self): @@ -932,9 +952,9 @@ class PlotCanvas(wx.Panel): def SetEnableLegend(self, value): """Set True to enable legend.""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") - self._legendEnabled= value + self._legendEnabled = value self.Redraw() def GetEnableLegend(self): @@ -943,9 +963,9 @@ class PlotCanvas(wx.Panel): def SetEnableTitle(self, value): """Set True to enable title.""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") - self._titleEnabled= value + self._titleEnabled = value self.Redraw() def GetEnableTitle(self): @@ -954,10 +974,10 @@ class PlotCanvas(wx.Panel): def SetEnablePointLabel(self, value): """Set True to enable pointLabel.""" - if value not in [True,False]: + if value not in [True, False]: raise TypeError("Value should be True or False") - self._pointLabelEnabled= value - self.Redraw() #will erase existing pointLabel if present + self._pointLabelEnabled = value + self.Redraw() # will erase existing pointLabel if present self.last_PointLabel = None def GetEnablePointLabel(self): @@ -968,7 +988,7 @@ class PlotCanvas(wx.Panel): """Sets the function with custom code for pointLabel drawing ******** more info needed *************** """ - self._pointLabelFunc= func + self._pointLabelFunc = func def GetPointLabelFunc(self): """Returns pointLabel Drawing Function""" @@ -976,53 +996,53 @@ class PlotCanvas(wx.Panel): def Reset(self): """Unzoom the plot.""" - self.last_PointLabel = None #reset pointLabel + self.last_PointLabel = None # reset pointLabel if self.last_draw is not None: self._Draw(self.last_draw[0]) def ScrollRight(self, units): """Move view right number of axis units.""" - self.last_PointLabel = None #reset pointLabel + self.last_PointLabel = None # reset pointLabel if self.last_draw is not None: - graphics, xAxis, yAxis= self.last_draw - xAxis= (xAxis[0]+units, xAxis[1]+units) - self._Draw(graphics,xAxis,yAxis) + graphics, xAxis, yAxis = self.last_draw + xAxis = (xAxis[0] + units, xAxis[1] + units) + self._Draw(graphics, xAxis, yAxis) def ScrollUp(self, units): """Move view up number of axis units.""" - self.last_PointLabel = None #reset pointLabel + self.last_PointLabel = None # reset pointLabel if self.last_draw is not None: - graphics, xAxis, yAxis= self.last_draw - yAxis= (yAxis[0]+units, yAxis[1]+units) - self._Draw(graphics,xAxis,yAxis) + graphics, xAxis, yAxis = self.last_draw + yAxis = (yAxis[0] + units, yAxis[1] + units) + self._Draw(graphics, xAxis, yAxis) def GetXY(self, event): """Wrapper around _getXY, which handles log scales""" - x,y = self._getXY(event) + x, y = self._getXY(event) if self.getLogScale()[0]: - x = np.power(10,x) + x = np.power(10, x) if self.getLogScale()[1]: - y = np.power(10,y) - return x,y + y = np.power(10, y) + return x, y - def _getXY(self,event): + def _getXY(self, event): """Takes a mouse event and returns the XY user axis values.""" - x,y= self.PositionScreenToUser(event.GetPosition()) - return x,y + x, y = self.PositionScreenToUser(event.GetPosition()) + return x, y def PositionUserToScreen(self, pntXY): """Converts User position to Screen Coordinates""" - userPos= np.array(pntXY) - x,y= userPos * self._pointScale + self._pointShift - return x,y + userPos = np.array(pntXY) + x, y = userPos * self._pointScale + self._pointShift + return x, y def PositionScreenToUser(self, pntXY): """Converts Screen position to User Coordinates""" - screenPos= np.array(pntXY) - x,y= (screenPos-self._pointShift)/self._pointScale - return x,y + screenPos = np.array(pntXY) + x, y = (screenPos - self._pointShift) / self._pointScale + return x, y - def SetXSpec(self, type= 'auto'): + def SetXSpec(self, type='auto'): """xSpec- defines x axis type. Can be 'none', 'min' or 'auto' where: @@ -1031,9 +1051,9 @@ class PlotCanvas(wx.Panel): * 'auto' - rounds axis range to sensible values * - like 'min', but with tick marks """ - self._xSpec= type + self._xSpec = type - def SetYSpec(self, type= 'auto'): + def SetYSpec(self, type='auto'): """ySpec- defines x axis type. Can be 'none', 'min' or 'auto' where: @@ -1042,7 +1062,7 @@ class PlotCanvas(wx.Panel): * 'auto' - rounds axis range to sensible values * - like 'min', but with tick marks """ - self._ySpec= type + self._ySpec = type def GetXSpec(self): """Returns current XSpec for axis""" @@ -1055,25 +1075,25 @@ class PlotCanvas(wx.Panel): def GetXMaxRange(self): xAxis = self._getXMaxRange() if self.getLogScale()[0]: - xAxis = np.power(10,xAxis) + xAxis = np.power(10, xAxis) return xAxis def _getXMaxRange(self): """Returns (minX, maxX) x-axis range for displayed graph""" - graphics= self.last_draw[0] + graphics = self.last_draw[0] p1, p2 = graphics.boundingBox() # min, max points of graphics - xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units + xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units return xAxis def GetYMaxRange(self): yAxis = self._getYMaxRange() if self.getLogScale()[1]: - yAxis = np.power(10,yAxis) + yAxis = np.power(10, yAxis) return yAxis def _getYMaxRange(self): """Returns (minY, maxY) y-axis range for displayed graph""" - graphics= self.last_draw[0] + graphics = self.last_draw[0] p1, p2 = graphics.boundingBox() # min, max points of graphics yAxis = self._axisInterval(self._ySpec, p1[1], p2[1]) return yAxis @@ -1081,7 +1101,7 @@ class PlotCanvas(wx.Panel): def GetXCurrentRange(self): xAxis = self._getXCurrentRange() if self.getLogScale()[0]: - xAxis = np.power(10,xAxis) + xAxis = np.power(10, xAxis) return xAxis def _getXCurrentRange(self): @@ -1091,23 +1111,25 @@ class PlotCanvas(wx.Panel): def GetYCurrentRange(self): yAxis = self._getYCurrentRange() if self.getLogScale()[1]: - yAxis = np.power(10,yAxis) + yAxis = np.power(10, yAxis) return yAxis def _getYCurrentRange(self): """Returns (minY, maxY) y-axis for currently displayed portion of graph""" return self.last_draw[2] - def Draw(self, graphics, xAxis = None, yAxis = None, dc = None): + def Draw(self, graphics, xAxis=None, yAxis=None, dc=None): """Wrapper around _Draw, which handles log axes""" graphics.setLogScale(self.getLogScale()) # check Axis is either tuple or none - if type(xAxis) not in [type(None),tuple]: - raise TypeError("xAxis should be None or (minX,maxX)"+str(type(xAxis))) - if type(yAxis) not in [type(None),tuple]: - raise TypeError("yAxis should be None or (minY,maxY)"+str(type(xAxis))) + if type(xAxis) not in [type(None), tuple]: + raise TypeError( + "xAxis should be None or (minX,maxX)" + str(type(xAxis))) + if type(yAxis) not in [type(None), tuple]: + raise TypeError( + "yAxis should be None or (minY,maxY)" + str(type(xAxis))) # check case for axis = (a,b) where a==b caused by improper zooms if xAxis != None: @@ -1122,7 +1144,7 @@ class PlotCanvas(wx.Panel): yAxis = np.log10(yAxis) self._Draw(graphics, xAxis, yAxis, dc) - def _Draw(self, graphics, xAxis = None, yAxis = None, dc = None): + def _Draw(self, graphics, xAxis=None, yAxis=None, dc=None): """\ Draw objects in graphics with specified x and y axis. graphics- instance of PlotGraphics with list of PolyXXX objects @@ -1147,19 +1169,23 @@ class PlotCanvas(wx.Panel): pass else: if self._hiResEnabled: - dc.SetMapMode(wx.MM_TWIPS) # high precision - each logical unit is 1/20 of a point - self._pointSize = tuple(1.0 / lscale for lscale in dc.GetLogicalScale()) + # high precision - each logical unit is 1/20 of a point + dc.SetMapMode(wx.MM_TWIPS) + self._pointSize = tuple( + 1.0 / lscale for lscale in dc.GetLogicalScale()) self._setSize() elif self._pointSize != (1.0, 1.0): self._pointSize = (1.0, 1.0) self._setSize() - if sys.platform in ("darwin", "win32") or not isinstance(dc, wx.GCDC): + if (sys.platform in ("darwin", "win32") or not isinstance(dc, wx.GCDC) or wx.VERSION >= (2, 9)): self._fontScale = sum(self._pointSize) / 2.0 else: # on Linux, we need to correct the font size by a certain factor if wx.GCDC is used, # to make text the same size as if wx.GCDC weren't used + screenppi = map(float, wx.ScreenDC().GetPPI()) ppi = dc.GetPPI() - self._fontScale = (96.0 / ppi[0] * self._pointSize[0] + 96.0 / ppi[1] * self._pointSize[1]) / 2.0 + self._fontScale = (screenppi[ + 0] / ppi[0] * self._pointSize[0] + screenppi[1] / ppi[1] * self._pointSize[1]) / 2.0 graphics._pointSize = self._pointSize dc.SetTextForeground(self.GetForegroundColour()) @@ -1170,93 +1196,117 @@ class PlotCanvas(wx.Panel): # set font size for every thing but title and legend dc.SetFont(self._getFont(self._fontSizeAxis)) - # sizes axis to axis type, create lower left and upper right corners of plot + # sizes axis to axis type, create lower left and upper right corners of + # plot if xAxis == None or yAxis == None: # One or both axis not specified in Draw p1, p2 = graphics.boundingBox() # min, max points of graphics if xAxis == None: - xAxis = self._axisInterval(self._xSpec, p1[0], p2[0]) # in user units + xAxis = self._axisInterval( + self._xSpec, p1[0], p2[0]) # in user units if yAxis == None: yAxis = self._axisInterval(self._ySpec, p1[1], p2[1]) # Adjust bounding box for axis spec - p1[0],p1[1] = xAxis[0], yAxis[0] # lower left corner user scale (xmin,ymin) - p2[0],p2[1] = xAxis[1], yAxis[1] # upper right corner user scale (xmax,ymax) + # lower left corner user scale (xmin,ymin) + p1[0], p1[1] = xAxis[0], yAxis[0] + # upper right corner user scale (xmax,ymax) + p2[0], p2[1] = xAxis[1], yAxis[1] else: # Both axis specified in Draw - p1= np.array([xAxis[0], yAxis[0]]) # lower left corner user scale (xmin,ymin) - p2= np.array([xAxis[1], yAxis[1]]) # upper right corner user scale (xmax,ymax) + # lower left corner user scale (xmin,ymin) + p1 = np.array([xAxis[0], yAxis[0]]) + # upper right corner user scale (xmax,ymax) + p2 = np.array([xAxis[1], yAxis[1]]) - self.last_draw = (graphics, np.array(xAxis), np.array(yAxis)) # saves most recient values + # saves most recient values + self.last_draw = (graphics, np.array(xAxis), np.array(yAxis)) # Get ticks and textExtents for axis if required if self._xSpec is not 'none': xticks = self._xticks(xAxis[0], xAxis[1]) - xTextExtent = dc.GetTextExtent(xticks[-1][1])# w h of x axis text last number on axis else: xticks = None - xTextExtent= (0,0) # No text for ticks + if xticks: + # w h of x axis text last number on axis + xTextExtent = dc.GetTextExtent(xticks[-1][1]) + else: + xTextExtent = (0, 0) # No text for ticks if self._ySpec is not 'none': yticks = self._yticks(yAxis[0], yAxis[1]) + else: + yticks = None + if yticks: if self.getLogScale()[1]: yTextExtent = dc.GetTextExtent('-2e-2') else: yTextExtentBottom = dc.GetTextExtent(yticks[0][1]) yTextExtentTop = dc.GetTextExtent(yticks[-1][1]) - yTextExtent= (max(yTextExtentBottom[0],yTextExtentTop[0]), - max(yTextExtentBottom[1],yTextExtentTop[1])) + yTextExtent = (max(yTextExtentBottom[0], yTextExtentTop[0]), + max(yTextExtentBottom[1], yTextExtentTop[1])) else: yticks = None - yTextExtent= (0,0) # No text for ticks + yTextExtent = (0, 0) # No text for ticks # TextExtents for Title and Axis Labels - titleWH, xLabelWH, yLabelWH= self._titleLablesWH(dc, graphics) + titleWH, xLabelWH, yLabelWH = self._titleLablesWH(dc, graphics) # TextExtents for Legend legendBoxWH, legendSymExt, legendTextExt = self._legendWH(dc, graphics) # room around graph area - rhsW= max(xTextExtent[0], legendBoxWH[0])+5*self._pointSize[0] # use larger of number width or legend width - lhsW= yTextExtent[0]+ yLabelWH[1] + 3*self._pointSize[0] - bottomH= max(xTextExtent[1], yTextExtent[1]/2.)+ xLabelWH[1] + 2*self._pointSize[1] - topH= yTextExtent[1]/2. + titleWH[1] - textSize_scale= np.array([rhsW+lhsW,bottomH+topH]) # make plot area smaller by text size - textSize_shift= np.array([lhsW, bottomH]) # shift plot area by this amount + # use larger of number width or legend width + rhsW = max(xTextExtent[0], legendBoxWH[0]) + 5 * self._pointSize[0] + lhsW = yTextExtent[0] + yLabelWH[1] + 3 * self._pointSize[0] + bottomH = max( + xTextExtent[1], yTextExtent[1] / 2.) + xLabelWH[1] + 2 * self._pointSize[1] + topH = yTextExtent[1] / 2. + titleWH[1] + # make plot area smaller by text size + textSize_scale = np.array([rhsW + lhsW, bottomH + topH]) + # shift plot area by this amount + textSize_shift = np.array([lhsW, bottomH]) # draw title if requested if self._titleEnabled: dc.SetFont(self._getFont(self._fontSizeTitle)) - titlePos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- titleWH[0]/2., - self.plotbox_origin[1]- self.plotbox_size[1]) - dc.DrawText(graphics.getTitle(),titlePos[0],titlePos[1]) + titlePos = (self.plotbox_origin[0] + lhsW + (self.plotbox_size[0] - lhsW - rhsW) / 2. - titleWH[0] / 2., + self.plotbox_origin[1] - self.plotbox_size[1]) + dc.DrawText(graphics.getTitle(), titlePos[0], titlePos[1]) # draw label text dc.SetFont(self._getFont(self._fontSizeAxis)) - xLabelPos= (self.plotbox_origin[0]+ lhsW + (self.plotbox_size[0]-lhsW-rhsW)/2.- xLabelWH[0]/2., - self.plotbox_origin[1]- xLabelWH[1]) - dc.DrawText(graphics.getXLabel(),xLabelPos[0],xLabelPos[1]) - yLabelPos= (self.plotbox_origin[0] - 3*self._pointSize[0], - self.plotbox_origin[1]- bottomH- (self.plotbox_size[1]-bottomH-topH)/2.+ yLabelWH[0]/2.) + xLabelPos = (self.plotbox_origin[0] + lhsW + (self.plotbox_size[0] - lhsW - rhsW) / 2. - xLabelWH[0] / 2., + self.plotbox_origin[1] - xLabelWH[1]) + dc.DrawText(graphics.getXLabel(), xLabelPos[0], xLabelPos[1]) + yLabelPos = (self.plotbox_origin[0] - 3 * self._pointSize[0], + self.plotbox_origin[1] - bottomH - (self.plotbox_size[1] - bottomH - topH) / 2. + yLabelWH[0] / 2.) if graphics.getYLabel(): # bug fix for Linux - dc.DrawRotatedText(graphics.getYLabel(),yLabelPos[0],yLabelPos[1],90) + dc.DrawRotatedText( + graphics.getYLabel(), yLabelPos[0], yLabelPos[1], 90) # drawing legend makers and text if self._legendEnabled: - self._drawLegend(dc,graphics,rhsW,topH,legendBoxWH, legendSymExt, legendTextExt) + self._drawLegend( + dc, graphics, rhsW, topH, legendBoxWH, legendSymExt, legendTextExt) # allow for scaling and shifting plotted points - scale = (self.plotbox_size-textSize_scale) / (p2-p1)* np.array((1,-1)) - shift = -p1*scale + self.plotbox_origin + textSize_shift * np.array((1,-1)) - self._pointScale= scale / self._pointSize # make available for mouse events - self._pointShift= shift / self._pointSize + scale = (self.plotbox_size - textSize_scale) / \ + (p2 - p1) * np.array((1, -1)) + shift = -p1 * scale + self.plotbox_origin + \ + textSize_shift * np.array((1, -1)) + # make available for mouse events + self._pointScale = scale / self._pointSize + self._pointShift = shift / self._pointSize self._drawAxes(dc, p1, p2, scale, shift, xticks, yticks) graphics.scaleAndShift(scale, shift) - graphics.setPrinterScale(self.printerScale) # thicken up lines and markers if printing + # thicken up lines and markers if printing + graphics.setPrinterScale(self.printerScale) # set clipping area so drawing does not occur outside axis box - ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(p1, p2) + ptx, pty, rectWidth, rectHeight = self._point2ClientCoord(p1, p2) # allow graph to overlap axis lines by adding units to width and height - dc.SetClippingRegion(ptx*self._pointSize[0],pty*self._pointSize[1],rectWidth*self._pointSize[0]+2,rectHeight*self._pointSize[1]+1) + dc.SetClippingRegion(ptx * self._pointSize[0], pty * self._pointSize[ + 1], rectWidth * self._pointSize[0] + 2, rectHeight * self._pointSize[1] + 1) # Draw the lines and markers #start = _time.clock() graphics.draw(dc) @@ -1269,12 +1319,12 @@ class PlotCanvas(wx.Panel): def Redraw(self, dc=None): """Redraw the existing plot.""" if self.last_draw is not None: - graphics, xAxis, yAxis= self.last_draw - self._Draw(graphics,xAxis,yAxis,dc) + graphics, xAxis, yAxis = self.last_draw + self._Draw(graphics, xAxis, yAxis, dc) def Clear(self): """Erase the window.""" - self.last_PointLabel = None #reset pointLabel + self.last_PointLabel = None # reset pointLabel dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer) bbr = wx.Brush(self.GetBackgroundColour(), wx.SOLID) dc.SetBackground(bbr) @@ -1294,17 +1344,17 @@ class PlotCanvas(wx.Panel): Centers on the X,Y coords given in Center Zooms by the Ratio = (Xratio, Yratio) given """ - self.last_PointLabel = None #reset maker - x,y = Center + self.last_PointLabel = None # reset maker + x, y = Center if self.last_draw != None: (graphics, xAxis, yAxis) = self.last_draw w = (xAxis[1] - xAxis[0]) * Ratio[0] h = (yAxis[1] - yAxis[0]) * Ratio[1] - xAxis = ( x - w/2, x + w/2 ) - yAxis = ( y - h/2, y + h/2 ) + xAxis = (x - w / 2, x + w / 2) + yAxis = (y - h / 2, y + h / 2) self._Draw(graphics, xAxis, yAxis) - def GetClosestPoints(self, pntXY, pointScaled= True): + def GetClosestPoints(self, pntXY, pointScaled=True): """Returns list with [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] list for each curve. @@ -1315,20 +1365,21 @@ class PlotCanvas(wx.Panel): if pointScaled == False based on user coords """ if self.last_draw == None: - #no graph available + # no graph available return [] - graphics, xAxis, yAxis= self.last_draw + graphics, xAxis, yAxis = self.last_draw l = [] - for curveNum,obj in enumerate(graphics): - #check there are points in the curve + for curveNum, obj in enumerate(graphics): + # check there are points in the curve if len(obj.points) == 0: - continue #go to next obj + continue # go to next obj #[curveNumber, legend, index of closest point, pointXY, scaledXY, distance] - cn = [curveNum]+ [obj.getLegend()]+ obj.getClosestPoint( pntXY, pointScaled) + cn = [curveNum] + \ + [obj.getLegend()] + obj.getClosestPoint(pntXY, pointScaled) l.append(cn) return l - def GetClosestPoint(self, pntXY, pointScaled= True): + def GetClosestPoint(self, pntXY, pointScaled=True): """Returns list with [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] list for only the closest curve. @@ -1338,16 +1389,16 @@ class PlotCanvas(wx.Panel): if pointScaled == True based on screen coords if pointScaled == False based on user coords """ - #closest points on screen based on screen scaling (pointScaled= True) - #list [curveNumber, index, pointXY, scaledXY, distance] for each curve - closestPts= self.GetClosestPoints(pntXY, pointScaled) + # closest points on screen based on screen scaling (pointScaled= True) + # list [curveNumber, index, pointXY, scaledXY, distance] for each curve + closestPts = self.GetClosestPoints(pntXY, pointScaled) if closestPts == []: - return [] #no graph present - #find one with least distance + return [] # no graph present + # find one with least distance dists = [c[-1] for c in closestPts] - mdist = min(dists) #Min dist - i = dists.index(mdist) #index for min dist - return closestPts[i] #this is the closest point on closest curve + mdist = min(dists) # Min dist + i = dists.index(mdist) # index for min dist + return closestPts[i] # this is the closest point on closest curve GetClosetPoint = GetClosestPoint @@ -1364,40 +1415,43 @@ class PlotCanvas(wx.Panel): onMotion events etc. """ if self.last_PointLabel != None: - #compare pointXY + # compare pointXY if np.sometrue(mDataDict["pointXY"] != self.last_PointLabel["pointXY"]): - #closest changed - self._drawPointLabel(self.last_PointLabel) #erase old - self._drawPointLabel(mDataDict) #plot new + # closest changed + self._drawPointLabel(self.last_PointLabel) # erase old + self._drawPointLabel(mDataDict) # plot new else: - #just plot new with no erase - self._drawPointLabel(mDataDict) #plot new - #save for next erase + # just plot new with no erase + self._drawPointLabel(mDataDict) # plot new + # save for next erase self.last_PointLabel = mDataDict # event handlers ********************************** def OnMotion(self, event): if self._zoomEnabled and event.LeftIsDown(): if self._hasDragged: - self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # remove old + self._drawRubberBand( + self._zoomCorner1, self._zoomCorner2) # remove old else: - self._hasDragged= True + self._hasDragged = True self._zoomCorner2[0], self._zoomCorner2[1] = self._getXY(event) - self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # add new + self._drawRubberBand( + self._zoomCorner1, self._zoomCorner2) # add new elif self._dragEnabled and event.LeftIsDown(): coordinates = event.GetPosition() - newpos, oldpos = map(np.array, map(self.PositionScreenToUser, [coordinates, self._screenCoordinates])) - dist = newpos-oldpos + newpos, oldpos = map(np.array, map( + self.PositionScreenToUser, [coordinates, self._screenCoordinates])) + dist = newpos - oldpos self._screenCoordinates = coordinates if self.last_draw is not None: - graphics, xAxis, yAxis= self.last_draw + graphics, xAxis, yAxis = self.last_draw yAxis -= dist[1] xAxis -= dist[0] - self._Draw(graphics,xAxis,yAxis) + self._Draw(graphics, xAxis, yAxis) - def OnMouseLeftDown(self,event): - self._zoomCorner1[0], self._zoomCorner1[1]= self._getXY(event) + def OnMouseLeftDown(self, event): + self._zoomCorner1[0], self._zoomCorner1[1] = self._getXY(event) self._screenCoordinates = np.array(event.GetPosition()) if self._dragEnabled: self.SetCursor(self.GrabHandCursor) @@ -1406,16 +1460,18 @@ class PlotCanvas(wx.Panel): def OnMouseLeftUp(self, event): if self._zoomEnabled: if self._hasDragged == True: - self._drawRubberBand(self._zoomCorner1, self._zoomCorner2) # remove old - self._zoomCorner2[0], self._zoomCorner2[1]= self._getXY(event) + self._drawRubberBand( + self._zoomCorner1, self._zoomCorner2) # remove old + self._zoomCorner2[0], self._zoomCorner2[1] = self._getXY(event) self._hasDragged = False # reset flag - minX, minY= np.minimum( self._zoomCorner1, self._zoomCorner2) - maxX, maxY= np.maximum( self._zoomCorner1, self._zoomCorner2) - self.last_PointLabel = None #reset pointLabel + minX, minY = np.minimum(self._zoomCorner1, self._zoomCorner2) + maxX, maxY = np.maximum(self._zoomCorner1, self._zoomCorner2) + self.last_PointLabel = None # reset pointLabel if self.last_draw != None: - self._Draw(self.last_draw[0], xAxis = (minX,maxX), yAxis = (minY,maxY), dc = None) - #else: # A box has not been drawn, zoom in on a point - ## this interfered with the double click, so I've disables it. + self._Draw( + self.last_draw[0], xAxis=(minX, maxX), yAxis = (minY, maxY), dc = None) + # else: # A box has not been drawn, zoom in on a point + # this interfered with the double click, so I've disables it. # X,Y = self._getXY(event) # self.Zoom( (X,Y), (self._zoomInFactor,self._zoomInFactor) ) if self._dragEnabled: @@ -1423,22 +1479,22 @@ class PlotCanvas(wx.Panel): if self.canvas.HasCapture(): self.canvas.ReleaseMouse() - def OnMouseDoubleClick(self,event): + def OnMouseDoubleClick(self, event): if self._zoomEnabled: # Give a little time for the click to be totally finished # before (possibly) removing the scrollbars and trigering # size events, etc. - wx.CallLater(200,self.Reset) + wx.CallLater(200, self.Reset) - def OnMouseRightDown(self,event): + def OnMouseRightDown(self, event): if self._zoomEnabled: - X,Y = self._getXY(event) - self.Zoom( (X,Y), (self._zoomOutFactor, self._zoomOutFactor) ) + X, Y = self._getXY(event) + self.Zoom((X, Y), (self._zoomOutFactor, self._zoomOutFactor)) def OnPaint(self, event): # All that is needed here is to draw the buffer to screen if self.last_PointLabel != None: - self._drawPointLabel(self.last_PointLabel) #erase old + self._drawPointLabel(self.last_PointLabel) # erase old self.last_PointLabel = None dc = wx.BufferedPaintDC(self.canvas, self._Buffer) if self._antiAliasingEnabled: @@ -1447,10 +1503,10 @@ class PlotCanvas(wx.Panel): except Exception: pass - def OnSize(self,event): + def OnSize(self, event): # The Buffer init is done here, to make sure the buffer is always # the same size as the Window - Size = self.canvas.GetClientSize() + Size = self.canvas.GetClientSize() Size.width = max(1, Size.width) Size.height = max(1, Size.height) @@ -1460,18 +1516,18 @@ class PlotCanvas(wx.Panel): self._Buffer = wx.Bitmap(Size.width, Size.height) self._setSize() - self.last_PointLabel = None #reset pointLabel + self.last_PointLabel = None # reset pointLabel if self.last_draw is None: self.Clear() else: graphics, xSpec, ySpec = self.last_draw - self._Draw(graphics,xSpec,ySpec) + self._Draw(graphics, xSpec, ySpec) def OnLeave(self, event): """Used to erase pointLabel when mouse outside window""" if self.last_PointLabel != None: - self._drawPointLabel(self.last_PointLabel) #erase old + self._drawPointLabel(self.last_PointLabel) # erase old self.last_PointLabel = None def OnScroll(self, evt): @@ -1480,181 +1536,192 @@ class PlotCanvas(wx.Panel): sbpos = evt.GetPosition() if evt.GetOrientation() == wx.VERTICAL: - fullrange,pagesize = self.sb_vert.GetRange(),self.sb_vert.GetPageSize() - sbpos = fullrange-pagesize-sbpos - dist = sbpos*self._sb_yunit-(self._getYCurrentRange()[0]-self._sb_yfullrange[0]) + fullrange, pagesize = self.sb_vert.GetRange( + ), self.sb_vert.GetPageSize() + sbpos = fullrange - pagesize - sbpos + dist = sbpos * self._sb_xunit - \ + (self._getXCurrentRange()[0] - self._sb_xfullrange) self.ScrollUp(dist) if evt.GetOrientation() == wx.HORIZONTAL: - dist = sbpos*self._sb_xunit-(self._getXCurrentRange()[0]-self._sb_xfullrange[0]) + dist = sbpos * self._sb_xunit - \ + (self._getXCurrentRange()[0] - self._sb_xfullrange[0]) self.ScrollRight(dist) # Private Methods ************************************************** def _setSize(self, width=None, height=None): """DC width and height.""" if width == None: - (self.width,self.height) = self.canvas.GetClientSize() + (self.width, self.height) = self.canvas.GetClientSize() else: - self.width, self.height= width,height - self.width *= self._pointSize[0] # high precision - self.height *= self._pointSize[1] # high precision - self.plotbox_size = 0.97*np.array([self.width, self.height]) - xo = 0.5*(self.width-self.plotbox_size[0]) - yo = self.height-0.5*(self.height-self.plotbox_size[1]) + self.width, self.height = width, height + self.width *= self._pointSize[0] # high precision + self.height *= self._pointSize[1] # high precision + self.plotbox_size = 0.97 * np.array([self.width, self.height]) + xo = 0.5 * (self.width - self.plotbox_size[0]) + yo = self.height - 0.5 * (self.height - self.plotbox_size[1]) self.plotbox_origin = np.array([xo, yo]) def _setPrinterScale(self, scale): """Used to thicken lines and increase marker size for print out.""" # line thickness on printer is very thin at 600 dot/in. Markers small - self.printerScale= scale + self.printerScale = scale def _printDraw(self, printDC): """Used for printing.""" if self.last_draw != None: - graphics, xSpec, ySpec= self.last_draw - self._Draw(graphics,xSpec,ySpec,printDC) + graphics, xSpec, ySpec = self.last_draw + self._Draw(graphics, xSpec, ySpec, printDC) def _drawPointLabel(self, mDataDict): """Draws and erases pointLabels""" width = self._Buffer.GetWidth() height = self._Buffer.GetHeight() if sys.platform != "darwin": - tmp_Buffer = wx.Bitmap(width,height) + tmp_Buffer = wx.Bitmap(width, height) dcs = wx.MemoryDC() dcs.SelectObject(tmp_Buffer) dcs.Clear() else: tmp_Buffer = self._Buffer.GetSubBitmap((0, 0, width, height)) dcs = wx.MemoryDC(self._Buffer) - self._pointLabelFunc(dcs,mDataDict) #custom user pointLabel function + self._pointLabelFunc(dcs, mDataDict) # custom user pointLabel function - dc = wx.ClientDC( self.canvas ) - #this will erase if called twice + dc = wx.ClientDC(self.canvas) + dc = wx.BufferedDC(dc, self._Buffer) + # this will erase if called twice dc.Blit(0, 0, width, height, dcs, 0, 0, self._logicalFunction) if sys.platform == "darwin": self._Buffer = tmp_Buffer - - def _drawLegend(self,dc,graphics,rhsW,topH,legendBoxWH, legendSymExt, legendTextExt): + def _drawLegend(self, dc, graphics, rhsW, topH, legendBoxWH, legendSymExt, legendTextExt): """Draws legend symbols and text""" # top right hand corner of graph box is ref corner - trhc= self.plotbox_origin+ (self.plotbox_size-[rhsW,topH])*[1,-1] - legendLHS= .091* legendBoxWH[0] # border space between legend sym and graph box - lineHeight= max(legendSymExt[1], legendTextExt[1]) * 1.1 #1.1 used as space between lines + trhc = self.plotbox_origin + \ + (self.plotbox_size - [rhsW, topH]) * [1, -1] + # border space between legend sym and graph box + legendLHS = .091 * legendBoxWH[0] + # 1.1 used as space between lines + lineHeight = max(legendSymExt[1], legendTextExt[1]) * 1.1 dc.SetFont(self._getFont(self._fontSizeLegend)) for i in range(len(graphics)): o = graphics[i] - s= i*lineHeight - if isinstance(o,PolyMarker): + s = i * lineHeight + if isinstance(o, PolyMarker): # draw marker with legend - pnt= (trhc[0]+legendLHS+legendSymExt[0]/2., trhc[1]+s+lineHeight/2.) - o.draw(dc, self.printerScale, coord= np.array([pnt])) - elif isinstance(o,PolyLine): + pnt = (trhc[0] + legendLHS + legendSymExt[0] / 2., + trhc[1] + s + lineHeight / 2.) + o.draw(dc, self.printerScale, coord=np.array([pnt])) + elif isinstance(o, PolyLine): # draw line with legend - pnt1= (trhc[0]+legendLHS, trhc[1]+s+lineHeight/2.) - pnt2= (trhc[0]+legendLHS+legendSymExt[0], trhc[1]+s+lineHeight/2.) - o.draw(dc, self.printerScale, coord= np.array([pnt1,pnt2])) + pnt1 = (trhc[0] + legendLHS, trhc[1] + s + lineHeight / 2.) + pnt2 = (trhc[0] + legendLHS + legendSymExt[0], + trhc[1] + s + lineHeight / 2.) + o.draw(dc, self.printerScale, coord=np.array([pnt1, pnt2])) else: - raise TypeError("object is neither PolyMarker or PolyLine instance") + raise TypeError( + "object is neither PolyMarker or PolyLine instance") # draw legend txt - pnt= (trhc[0]+legendLHS+legendSymExt[0]+5*self._pointSize[0], trhc[1]+s+lineHeight/2.-legendTextExt[1]/2) - dc.DrawText(o.getLegend(),pnt[0],pnt[1]) - dc.SetFont(self._getFont(self._fontSizeAxis)) # reset + pnt = (trhc[0] + legendLHS + legendSymExt[0] + 5 * self._pointSize[0], + trhc[1] + s + lineHeight / 2. - legendTextExt[1] / 2) + dc.DrawText(o.getLegend(), pnt[0], pnt[1]) + dc.SetFont(self._getFont(self._fontSizeAxis)) # reset def _titleLablesWH(self, dc, graphics): """Draws Title and labels and returns width and height for each""" # TextExtents for Title and Axis Labels dc.SetFont(self._getFont(self._fontSizeTitle)) if self._titleEnabled: - title= graphics.getTitle() - titleWH= dc.GetTextExtent(title) + title = graphics.getTitle() + titleWH = dc.GetTextExtent(title) else: - titleWH= (0,0) + titleWH = (0, 0) dc.SetFont(self._getFont(self._fontSizeAxis)) - xLabel, yLabel= graphics.getXLabel(),graphics.getYLabel() - xLabelWH= dc.GetTextExtent(xLabel) - yLabelWH= dc.GetTextExtent(yLabel) + xLabel, yLabel = graphics.getXLabel(), graphics.getYLabel() + xLabelWH = dc.GetTextExtent(xLabel) + yLabelWH = dc.GetTextExtent(yLabel) return titleWH, xLabelWH, yLabelWH def _legendWH(self, dc, graphics): """Returns the size in screen units for legend box""" if self._legendEnabled != True: - legendBoxWH= symExt= txtExt= (0,0) + legendBoxWH = symExt = txtExt = (0, 0) else: # find max symbol size - symExt= graphics.getSymExtent(self.printerScale) + symExt = graphics.getSymExtent(self.printerScale) # find max legend text extent dc.SetFont(self._getFont(self._fontSizeLegend)) - txtList= graphics.getLegendNames() - txtExt= dc.GetTextExtent(txtList[0]) + txtList = graphics.getLegendNames() + txtExt = dc.GetTextExtent(txtList[0]) for txt in graphics.getLegendNames()[1:]: - txtExt= np.maximum(txtExt,dc.GetTextExtent(txt)) - maxW= symExt[0]+txtExt[0] - maxH= max(symExt[1],txtExt[1]) + txtExt = np.maximum(txtExt, dc.GetTextExtent(txt)) + maxW = symExt[0] + txtExt[0] + maxH = max(symExt[1], txtExt[1]) # padding .1 for lhs of legend box and space between lines - maxW= maxW* 1.1 - maxH= maxH* 1.1 * len(txtList) + maxW = maxW * 1.1 + maxH = maxH * 1.1 * len(txtList) dc.SetFont(self._getFont(self._fontSizeAxis)) - legendBoxWH= (maxW,maxH) + legendBoxWH = (maxW, maxH) return (legendBoxWH, symExt, txtExt) def _drawRubberBand(self, corner1, corner2): """Draws/erases rect box from corner1 to corner2""" - ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(corner1, corner2) + ptx, pty, rectWidth, rectHeight = self._point2ClientCoord( + corner1, corner2) # draw rectangle - dc = wx.ClientDC( self.canvas ) + dc = wx.ClientDC(self.canvas) dc.SetPen(wx.Pen(wx.BLACK)) - dc.SetBrush(wx.Brush( wx.WHITE, wx.BRUSHSTYLE_TRANSPARENT ) ) + dc.SetBrush(wx.Brush(wx.WHITE, wx.BRUSHSTYLE_TRANSPARENT)) dc.SetLogicalFunction(wx.INVERT) - dc.DrawRectangle( ptx,pty, rectWidth,rectHeight) + dc.DrawRectangle(ptx, pty, rectWidth, rectHeight) dc.SetLogicalFunction(wx.COPY) - def _getFont(self,size): + def _getFont(self, size): """Take font size, adjusts if printing and returns wx.Font""" - s = size*self.printerScale*self._fontScale + s = size * self.printerScale * self._fontScale of = self.GetFont() # Linux speed up to get font from cache rather than X font server - key = (int(s), of.GetFamily (), of.GetStyle (), of.GetWeight ()) - font = self._fontCache.get (key, None) + key = (int(s), of.GetFamily(), of.GetStyle(), of.GetWeight()) + font = self._fontCache.get(key, None) if font: return font # yeah! cache hit else: - font = wx.Font(int(s), of.GetFamily(), of.GetStyle(), of.GetWeight()) + font = wx.Font( + int(s), of.GetFamily(), of.GetStyle(), of.GetWeight()) self._fontCache[key] = font return font - def _point2ClientCoord(self, corner1, corner2): """Converts user point coords to client screen int coords x,y,width,height""" - c1= np.array(corner1) - c2= np.array(corner2) + c1 = np.array(corner1) + c2 = np.array(corner2) # convert to screen coords - pt1= c1*self._pointScale+self._pointShift - pt2= c2*self._pointScale+self._pointShift + pt1 = c1 * self._pointScale + self._pointShift + pt2 = c2 * self._pointScale + self._pointShift # make height and width positive - pul= np.minimum(pt1,pt2) # Upper left corner - plr= np.maximum(pt1,pt2) # Lower right corner - rectWidth, rectHeight= plr-pul - ptx,pty= pul + pul = np.minimum(pt1, pt2) # Upper left corner + plr = np.maximum(pt1, pt2) # Lower right corner + rectWidth, rectHeight = plr - pul + ptx, pty = pul return ptx, pty, rectWidth, rectHeight def _axisInterval(self, spec, lower, upper): """Returns sensible axis range for given spec""" if spec == 'none' or spec == 'min' or isinstance(spec, (float, int)): if lower == upper: - return lower-0.5, upper+0.5 + return lower - 0.5, upper + 0.5 else: return lower, upper elif spec == 'auto': - range = upper-lower + range = upper - lower if range == 0.: - return lower-0.5, upper+0.5 + return lower - 0.5, upper + 0.5 log = np.log10(range) power = np.floor(log) - fraction = log-power + fraction = log - power if fraction <= 0.05: - power = power-1 - grid = 10.**power + power = power - 1 + grid = 10. ** power lower = lower - lower % grid mod = upper % grid if mod != 0: @@ -1671,72 +1738,82 @@ class PlotCanvas(wx.Panel): def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks): - penWidth= self.printerScale * self._pointSize[0] # increases thickness for printing only + # increases thickness for printing only + penWidth = self.printerScale * self._pointSize[0] dc.SetPen(wx.Pen(self._gridColour, penWidth)) # set length of tick marks--long ones make grid if self._gridEnabled: - x,y,width,height= self._point2ClientCoord(p1,p2) + x, y, width, height = self._point2ClientCoord(p1, p2) if self._gridEnabled == 'Horizontal': - yTickLength= (width/2.0 +1) * self._pointSize[1] - xTickLength= 3 * self.printerScale * self._pointSize[0] + yTickLength = (width / 2.0 + 1) * self._pointSize[1] + xTickLength = 3 * self.printerScale * self._pointSize[0] elif self._gridEnabled == 'Vertical': - yTickLength= 3 * self.printerScale * self._pointSize[1] - xTickLength= (height/2.0 +1) * self._pointSize[0] + yTickLength = 3 * self.printerScale * self._pointSize[1] + xTickLength = (height / 2.0 + 1) * self._pointSize[0] else: - yTickLength= (width/2.0 +1) * self._pointSize[1] - xTickLength= (height/2.0 +1) * self._pointSize[0] + yTickLength = (width / 2.0 + 1) * self._pointSize[1] + xTickLength = (height / 2.0 + 1) * self._pointSize[0] else: - yTickLength= 3 * self.printerScale * self._pointSize[1] # lengthens lines for printing - xTickLength= 3 * self.printerScale * self._pointSize[0] + # lengthens lines for printing + yTickLength = 3 * self.printerScale * self._pointSize[1] + xTickLength = 3 * self.printerScale * self._pointSize[0] if self._xSpec is not 'none': - lower, upper = p1[0],p2[0] + lower, upper = p1[0], p2[0] text = 1 - for y, d in [(p1[1], -xTickLength), (p2[1], xTickLength)]: # miny, maxy and tick lengths + # miny, maxy and tick lengths + for y, d in [(p1[1], -xTickLength), (p2[1], xTickLength)]: for x, label in xticks: - pt = scale*np.array([x, y])+shift - dc.DrawLine(pt[0],pt[1],pt[0],pt[1] + d) # draws tick mark d units + pt = scale * np.array([x, y]) + shift + # draws tick mark d units + dc.DrawLine(pt[0], pt[1], pt[0], pt[1] + d) if text: - dc.DrawText(label,pt[0],pt[1]+2*self._pointSize[1]) - a1 = scale*np.array([lower, y])+shift - a2 = scale*np.array([upper, y])+shift - dc.DrawLine(a1[0],a1[1],a2[0],a2[1]) # draws upper and lower axis line + dc.DrawText( + label, pt[0], pt[1] + 2 * self._pointSize[1]) + a1 = scale * np.array([lower, y]) + shift + a2 = scale * np.array([upper, y]) + shift + # draws upper and lower axis line + dc.DrawLine(a1[0], a1[1], a2[0], a2[1]) text = 0 # axis values not drawn on top side if self._ySpec is not 'none': - lower, upper = p1[1],p2[1] + lower, upper = p1[1], p2[1] text = 1 h = dc.GetCharHeight() for x, d in [(p1[0], -yTickLength), (p2[0], yTickLength)]: for y, label in yticks: - pt = scale*np.array([x, y])+shift - dc.DrawLine(pt[0],pt[1],pt[0]-d,pt[1]) + pt = scale * np.array([x, y]) + shift + dc.DrawLine(pt[0], pt[1], pt[0] - d, pt[1]) if text: - dc.DrawText(label,pt[0]-dc.GetTextExtent(label)[0]-3*self._pointSize[0], - pt[1]-0.75*h) - a1 = scale*np.array([x, lower])+shift - a2 = scale*np.array([x, upper])+shift - dc.DrawLine(a1[0],a1[1],a2[0],a2[1]) + dc.DrawText(label, pt[0] - dc.GetTextExtent(label)[0] - 3 * self._pointSize[0], + pt[1] - 0.75 * h) + a1 = scale * np.array([x, lower]) + shift + a2 = scale * np.array([x, upper]) + shift + dc.DrawLine(a1[0], a1[1], a2[0], a2[1]) text = 0 # axis values not drawn on right side if self._centerLinesEnabled: if self._centerLinesEnabled in ('Horizontal', True): - y1 = scale[1]*p1[1]+shift[1] - y2 = scale[1]*p2[1]+shift[1] + y1 = scale[1] * p1[1] + shift[1] + y2 = scale[1] * p2[1] + shift[1] y = (y1 - y2) / 2.0 + y2 - dc.DrawLine(scale[0] * p1[0] + shift[0], y, scale[0] * p2[0] + shift[0], y) + dc.DrawLine( + scale[0] * p1[0] + shift[0], y, scale[0] * p2[0] + shift[0], y) if self._centerLinesEnabled in ('Vertical', True): - x1 = scale[0]*p1[0]+shift[0] - x2 = scale[0]*p2[0]+shift[0] + x1 = scale[0] * p1[0] + shift[0] + x2 = scale[0] * p2[0] + shift[0] x = (x1 - x2) / 2.0 + x2 - dc.DrawLine(x, scale[1] * p1[1] + shift[1], x, scale[1] * p2[1] + shift[1]) + dc.DrawLine( + x, scale[1] * p1[1] + shift[1], x, scale[1] * p2[1] + shift[1]) if self._diagonalsEnabled: if self._diagonalsEnabled in ('Bottomleft-Topright', True): - dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p1[1] + shift[1], scale[0] * p2[0] + shift[0], scale[1] * p2[1] + shift[1]) + dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p1[1] + + shift[1], scale[0] * p2[0] + shift[0], scale[1] * p2[1] + shift[1]) if self._diagonalsEnabled in ('Bottomright-Topleft', True): - dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p2[1] + shift[1], scale[0] * p2[0] + shift[0], scale[1] * p1[1] + shift[1]) + dc.DrawLine(scale[0] * p1[0] + shift[0], scale[1] * p2[1] + + shift[1], scale[0] * p2[0] + shift[0], scale[1] * p1[1] + shift[1]) def _xticks(self, *args): if self._logscale[0]: @@ -1754,54 +1831,56 @@ class PlotCanvas(wx.Panel): def _logticks(self, lower, upper): #lower,upper = map(np.log10,[lower,upper]) - #print('logticks',lower,upper) + # print('logticks',lower,upper) ticks = [] - mag = np.power(10,np.floor(lower)) - if upper-lower > 6: - t = np.power(10,np.ceil(lower)) - base = np.power(10,np.floor((upper-lower)/6)) + mag = np.power(10, np.floor(lower)) + if upper - lower > 6: + t = np.power(10, np.ceil(lower)) + base = np.power(10, np.floor((upper - lower) / 6)) + def inc(t): - return t*base-t + return t * base - t else: - t = np.ceil(np.power(10,lower)/mag)*mag + t = np.ceil(np.power(10, lower) / mag) * mag + def inc(t): - return 10**int(np.floor(np.log10(t)+1e-16)) + return 10 ** int(np.floor(np.log10(t) + 1e-16)) majortick = int(np.log10(mag)) - while t <= pow(10,upper): - if majortick != int(np.floor(np.log10(t)+1e-16)): - majortick = int(np.floor(np.log10(t)+1e-16)) - ticklabel = '1e%d'%majortick + while t <= pow(10, upper): + if majortick != int(np.floor(np.log10(t) + 1e-16)): + majortick = int(np.floor(np.log10(t) + 1e-16)) + ticklabel = '1e%d' % majortick else: - if upper-lower < 2: - minortick = int(t/pow(10,majortick)+.5) - ticklabel = '%de%d'%(minortick,majortick) + if upper - lower < 2: + minortick = int(t / pow(10, majortick) + .5) + ticklabel = '%de%d' % (minortick, majortick) else: ticklabel = '' ticks.append((np.log10(t), ticklabel)) t += inc(t) if len(ticks) == 0: - ticks = [(0,'')] + ticks = [(0, '')] return ticks def _ticks(self, lower, upper, numticks=None): if isinstance(numticks, (float, int)): - ideal = (upper-lower)/float(numticks) + ideal = (upper - lower) / float(numticks) else: - ideal = (upper-lower)/7. + ideal = (upper - lower) / 7. log = np.log10(ideal) power = np.floor(log) if isinstance(numticks, (float, int)): grid = ideal else: - fraction = log-power + fraction = log - power factor = 1. error = fraction for f, lf in self._multiples: - e = np.fabs(fraction-lf) + e = np.fabs(fraction - lf) if e < error: error = e factor = f - grid = factor * 10.**power + grid = factor * 10. ** power if self._useScientificNotation and (power > 4 or power < -4): format = '%+7.1e' elif power >= 0: @@ -1809,19 +1888,18 @@ class PlotCanvas(wx.Panel): format = '%' + repr(digits) + '.0f' else: digits = -int(power) - format = '%' + repr(digits+2) + '.' + repr(digits) + 'f' + format = '%' + repr(digits + 2) + '.' + repr(digits) + 'f' ticks = [] - t = -grid*np.floor(-lower/grid) + t = -grid * np.floor(-lower / grid) while t <= upper: if t == -0: t = 0 - ticks.append( (t, format % (t,)) ) + ticks.append((t, format % (t,))) t = t + grid return ticks _multiples = [(2., np.log10(2.)), (5., np.log10(5.))] - def _adjustScrollbars(self): if self._sb_ignore: self._sb_ignore = False @@ -1838,16 +1916,16 @@ class PlotCanvas(wx.Panel): r_max = list(self._getXMaxRange()) sbfullrange = float(self.sb_hor.GetRange()) - r_max[0] = min(r_max[0],r_current[0]) - r_max[1] = max(r_max[1],r_current[1]) + r_max[0] = min(r_max[0], r_current[0]) + r_max[1] = max(r_max[1], r_current[1]) self._sb_xfullrange = r_max - unit = (r_max[1]-r_max[0])/float(self.sb_hor.GetRange()) - pos = int((r_current[0]-r_max[0])/unit) + unit = (r_max[1] - r_max[0]) / float(self.sb_hor.GetRange()) + pos = int((r_current[0] - r_max[0]) / unit) if pos >= 0: - pagesize = int((r_current[1]-r_current[0])/unit) + pagesize = int((r_current[1] - r_current[0]) / unit) self.sb_hor.SetScrollbar(pos, pagesize, sbfullrange, pagesize) self._sb_xunit = unit @@ -1860,17 +1938,17 @@ class PlotCanvas(wx.Panel): r_max = list(self._getYMaxRange()) sbfullrange = float(self.sb_vert.GetRange()) - r_max[0] = min(r_max[0],r_current[0]) - r_max[1] = max(r_max[1],r_current[1]) + r_max[0] = min(r_max[0], r_current[0]) + r_max[1] = max(r_max[1], r_current[1]) self._sb_yfullrange = r_max - unit = (r_max[1]-r_max[0])/sbfullrange - pos = int((r_current[0]-r_max[0])/unit) + unit = (r_max[1] - r_max[0]) / sbfullrange + pos = int((r_current[0] - r_max[0]) / unit) if pos >= 0: - pagesize = int((r_current[1]-r_current[0])/unit) - pos = (sbfullrange-1-pos-pagesize) + pagesize = int((r_current[1] - r_current[0]) / unit) + pos = (sbfullrange - 1 - pos - pagesize) self.sb_vert.SetScrollbar(pos, pagesize, sbfullrange, pagesize) self._sb_yunit = unit needScrollbars = needScrollbars or (pagesize != sbfullrange) @@ -1880,13 +1958,16 @@ class PlotCanvas(wx.Panel): self.SetShowScrollbars(needScrollbars) self._adjustingSB = False -#------------------------------------------------------------------------------- +#------------------------------------------------------------------------- # Used to layout the printer page + class PlotPrintout(wx.Printout): + """Controls how the plot is made in printing and previewing""" # Do not change method names in this class, # we have to override wx.Printout methods here! + def __init__(self, graph): """graph is instance of plotCanvas to be printed or previewed""" wx.Printout.__init__(self) @@ -1909,9 +1990,9 @@ class PlotPrintout(wx.Printout): ## print("GetPageSizePixels", self.GetPageSizePixels()) # Note PPIScreen does not give the correct number # Calulate everything for printer and then scale for preview - PPIPrinter= self.GetPPIPrinter() # printer dots/inch (w,h) - #PPIScreen= self.GetPPIScreen() # screen dots/inch (w,h) - dcSize= dc.GetSize() # DC size + PPIPrinter = self.GetPPIPrinter() # printer dots/inch (w,h) + # PPIScreen= self.GetPPIScreen() # screen dots/inch (w,h) + dcSize = dc.GetSize() # DC size if self.graph._antiAliasingEnabled and not isinstance(dc, wx.GCDC): try: dc = wx.GCDC(dc) @@ -1919,52 +2000,54 @@ class PlotPrintout(wx.Printout): pass else: if self.graph._hiResEnabled: - dc.SetMapMode(wx.MM_TWIPS) # high precision - each logical unit is 1/20 of a point - pageSize= self.GetPageSizePixels() # page size in terms of pixcels - clientDcSize= self.graph.GetClientSize() + # high precision - each logical unit is 1/20 of a point + dc.SetMapMode(wx.MM_TWIPS) + pageSize = self.GetPageSizePixels() # page size in terms of pixcels + clientDcSize = self.graph.GetClientSize() # find what the margins are (mm) - margLeftSize,margTopSize= self.graph.pageSetupData.GetMarginTopLeft() - margRightSize, margBottomSize= self.graph.pageSetupData.GetMarginBottomRight() + margLeftSize, margTopSize = self.graph.pageSetupData.GetMarginTopLeft() + margRightSize, margBottomSize = self.graph.pageSetupData.GetMarginBottomRight() # calculate offset and scale for dc - pixLeft= margLeftSize*PPIPrinter[0]/25.4 # mm*(dots/in)/(mm/in) - pixRight= margRightSize*PPIPrinter[0]/25.4 - pixTop= margTopSize*PPIPrinter[1]/25.4 - pixBottom= margBottomSize*PPIPrinter[1]/25.4 + pixLeft = margLeftSize * PPIPrinter[0] / 25.4 # mm*(dots/in)/(mm/in) + pixRight = margRightSize * PPIPrinter[0] / 25.4 + pixTop = margTopSize * PPIPrinter[1] / 25.4 + pixBottom = margBottomSize * PPIPrinter[1] / 25.4 - plotAreaW= pageSize[0]-(pixLeft+pixRight) - plotAreaH= pageSize[1]-(pixTop+pixBottom) + plotAreaW = pageSize[0] - (pixLeft + pixRight) + plotAreaH = pageSize[1] - (pixTop + pixBottom) # ratio offset and scale to screen size if preview if self.IsPreview(): - ratioW= float(dcSize[0])/pageSize[0] - ratioH= float(dcSize[1])/pageSize[1] + ratioW = float(dcSize[0]) / pageSize[0] + ratioH = float(dcSize[1]) / pageSize[1] pixLeft *= ratioW pixTop *= ratioH plotAreaW *= ratioW plotAreaH *= ratioH # rescale plot to page or preview plot area - self.graph._setSize(plotAreaW,plotAreaH) + self.graph._setSize(plotAreaW, plotAreaH) # Set offset and scale - dc.SetDeviceOrigin(pixLeft,pixTop) + dc.SetDeviceOrigin(pixLeft, pixTop) # Thicken up pens and increase marker size for printing - ratioW= float(plotAreaW)/clientDcSize[0] - ratioH= float(plotAreaH)/clientDcSize[1] - aveScale= (ratioW+ratioH)/2 + ratioW = float(plotAreaW) / clientDcSize[0] + ratioH = float(plotAreaH) / clientDcSize[1] + aveScale = (ratioW + ratioH) / 2 if self.graph._antiAliasingEnabled and not self.IsPreview(): scale = dc.GetUserScale() - dc.SetUserScale(scale[0] / self.graph._pointSize[0], scale[1] / self.graph._pointSize[1]) + dc.SetUserScale( + scale[0] / self.graph._pointSize[0], scale[1] / self.graph._pointSize[1]) self.graph._setPrinterScale(aveScale) # tickens up pens for printing self.graph._printDraw(dc) # rescale back to original self.graph._setSize() self.graph._setPrinterScale(1) - self.graph.Redraw() #to get point label scale and shift correct + self.graph.Redraw() # to get point label scale and shift correct return True @@ -2004,61 +2087,68 @@ Hand = PyEmbeddedImage( # ...a sample implementation using the above # + def _draw1Objects(): # 100 points sin function, plotted as green circles - data1 = 2.*np.pi*np.arange(200)/200. + data1 = 2. * np.pi * np.arange(200) / 200. data1.shape = (100, 2) - data1[:,1] = np.sin(data1[:,0]) - markers1 = PolyMarker(data1, legend='Green Markers', colour='green', marker='circle',size=1) + data1[:, 1] = np.sin(data1[:, 0]) + markers1 = PolyMarker( + data1, legend='Green Markers', colour='green', marker='circle', size=1) # 50 points cos function, plotted as red line - data1 = 2.*np.pi*np.arange(100)/100. - data1.shape = (50,2) - data1[:,1] = np.cos(data1[:,0]) - lines = PolySpline(data1, legend= 'Red Line', colour='red') + data1 = 2. * np.pi * np.arange(100) / 100. + data1.shape = (50, 2) + data1[:, 1] = np.cos(data1[:, 0]) + lines = PolySpline(data1, legend='Red Line', colour='red') # A few more points... pi = np.pi - markers2 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.), - (3.*pi/4., -1)], legend='Cross Legend', colour='blue', + markers2 = PolyMarker([(0., 0.), (pi / 4., 1.), (pi / 2, 0.), + (3. * pi / 4., -1)], legend='Cross Legend', colour='blue', marker='cross') - return PlotGraphics([markers1, lines, markers2],"Graph Title", "X Axis", "Y Axis") + return PlotGraphics([markers1, lines, markers2], "Graph Title", "X Axis", "Y Axis") + def _draw2Objects(): # 100 points sin function, plotted as green dots - data1 = 2.*np.pi*np.arange(200)/200. + data1 = 2. * np.pi * np.arange(200) / 200. data1.shape = (100, 2) - data1[:,1] = np.sin(data1[:,0]) - line1 = PolySpline(data1, legend='Green Line', colour='green', width=6, style=wx.PENSTYLE_DOT) + data1[:, 1] = np.sin(data1[:, 0]) + line1 = PolySpline( + data1, legend='Green Line', colour='green', width=6, style=wx.PENSTYLE_DOT) # 50 points cos function, plotted as red dot-dash - data1 = 2.*np.pi*np.arange(100)/100. - data1.shape = (50,2) - data1[:,1] = np.cos(data1[:,0]) - line2 = PolySpline(data1, legend='Red Line', colour='red', width=3, style= wx.PENSTYLE_DOT_DASH) + data1 = 2. * np.pi * np.arange(100) / 100. + data1.shape = (50, 2) + data1[:, 1] = np.cos(data1[:, 0]) + line2 = PolySpline( + data1, legend='Red Line', colour='red', width=3, style=wx.PENSTYLE_DOT_DASH) # A few more points... pi = np.pi - markers1 = PolyMarker([(0., 0.), (pi/4., 1.), (pi/2, 0.), - (3.*pi/4., -1)], legend='Cross Hatch Square', colour='blue', width= 3, size= 6, - fillcolour= 'red', fillstyle= wx.CROSSDIAG_HATCH, + markers1 = PolyMarker([(0., 0.), (pi / 4., 1.), (pi / 2, 0.), + (3. * pi / 4., -1)], legend='Cross Hatch Square', colour='blue', width=3, size=6, + fillcolour='red', fillstyle=wx.CROSSDIAG_HATCH, marker='square') return PlotGraphics([markers1, line1, line2], "Big Markers with Different Line Styles") + def _draw3Objects(): - markerList= ['circle', 'dot', 'square', 'triangle', 'triangle_down', - 'cross', 'plus', 'circle'] - m=[] + markerList = ['circle', 'dot', 'square', 'triangle', 'triangle_down', + 'cross', 'plus', 'circle'] + m = [] for i in range(len(markerList)): - m.append(PolyMarker([(2*i+.5,i+.5)], legend=markerList[i], colour='blue', - marker=markerList[i])) + m.append(PolyMarker([(2 * i + .5, i + .5)], legend=markerList[i], colour='blue', + marker=markerList[i])) return PlotGraphics(m, "Selection of Markers", "Minimal Axis", "No Axis") + def _draw4Objects(): # 25,000 point line - data1 = np.arange(5e5,1e6,10) + data1 = np.arange(5e5, 1e6, 10) data1.shape = (25000, 2) line1 = PolyLine(data1, legend='Wide Line', colour='green', width=5) @@ -2067,43 +2157,48 @@ def _draw4Objects(): marker='square') return PlotGraphics([line1, markers2], "25,000 Points", "Value X", "") + def _draw5Objects(): # Empty graph with axis defined but no points/lines - points=[] + points = [] line1 = PolyLine(points, legend='Wide Line', colour='green', width=5) return PlotGraphics([line1], "Empty Plot With Just Axes", "Value X", "Value Y") + def _draw6Objects(): # Bar graph - points1=[(1,0), (1,10)] + points1 = [(1, 0), (1, 10)] line1 = PolyLine(points1, colour='green', legend='Feb.', width=10) - points1g=[(2,0), (2,4)] + points1g = [(2, 0), (2, 4)] line1g = PolyLine(points1g, colour='red', legend='Mar.', width=10) - points1b=[(3,0), (3,6)] + points1b = [(3, 0), (3, 6)] line1b = PolyLine(points1b, colour='blue', legend='Apr.', width=10) - points2=[(4,0), (4,12)] + points2 = [(4, 0), (4, 12)] line2 = PolyLine(points2, colour='Yellow', legend='May', width=10) - points2g=[(5,0), (5,8)] + points2g = [(5, 0), (5, 8)] line2g = PolyLine(points2g, colour='orange', legend='June', width=10) - points2b=[(6,0), (6,4)] + points2b = [(6, 0), (6, 4)] line2b = PolyLine(points2b, colour='brown', legend='July', width=10) return PlotGraphics([line1, line1g, line1b, line2, line2g, line2b], "Bar Graph - (Turn on Grid, Legend)", "Months", "Number of Students") + + def _draw7Objects(): # Empty graph with axis defined but no points/lines - x = np.arange(1,1000,1) - y1 = 4.5*x**2 - y2 = 2.2*x**3 - points1 = np.transpose([x,y1]) - points2 = np.transpose([x,y2]) + x = np.arange(1, 1000, 1) + y1 = 4.5 * x ** 2 + y2 = 2.2 * x ** 3 + points1 = np.transpose([x, y1]) + points2 = np.transpose([x, y2]) line1 = PolyLine(points1, legend='quadratic', colour='blue', width=1) line2 = PolyLine(points2, legend='cubic', colour='red', width=1) - return PlotGraphics([line1,line2], "double log plot", "Value X", "Value Y") + return PlotGraphics([line1, line2], "double log plot", "Value X", "Value Y") class TestFrame(wx.Frame): + def __init__(self, parent, id, title): wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, (600, 400)) @@ -2130,62 +2225,74 @@ class TestFrame(wx.Frame): menu = wx.Menu() menu.Append(206, 'Draw1', 'Draw plots1') - self.Bind(wx.EVT_MENU,self.OnPlotDraw1, id=206) + self.Bind(wx.EVT_MENU, self.OnPlotDraw1, id=206) menu.Append(207, 'Draw2', 'Draw plots2') - self.Bind(wx.EVT_MENU,self.OnPlotDraw2, id=207) + self.Bind(wx.EVT_MENU, self.OnPlotDraw2, id=207) menu.Append(208, 'Draw3', 'Draw plots3') - self.Bind(wx.EVT_MENU,self.OnPlotDraw3, id=208) + self.Bind(wx.EVT_MENU, self.OnPlotDraw3, id=208) menu.Append(209, 'Draw4', 'Draw plots4') - self.Bind(wx.EVT_MENU,self.OnPlotDraw4, id=209) + self.Bind(wx.EVT_MENU, self.OnPlotDraw4, id=209) menu.Append(210, 'Draw5', 'Draw plots5') - self.Bind(wx.EVT_MENU,self.OnPlotDraw5, id=210) + self.Bind(wx.EVT_MENU, self.OnPlotDraw5, id=210) menu.Append(260, 'Draw6', 'Draw plots6') - self.Bind(wx.EVT_MENU,self.OnPlotDraw6, id=260) + self.Bind(wx.EVT_MENU, self.OnPlotDraw6, id=260) menu.Append(261, 'Draw7', 'Draw plots7') - self.Bind(wx.EVT_MENU,self.OnPlotDraw7, id=261) + self.Bind(wx.EVT_MENU, self.OnPlotDraw7, id=261) menu.Append(211, '&Redraw', 'Redraw plots') - self.Bind(wx.EVT_MENU,self.OnPlotRedraw, id=211) + self.Bind(wx.EVT_MENU, self.OnPlotRedraw, id=211) menu.Append(212, '&Clear', 'Clear canvas') - self.Bind(wx.EVT_MENU,self.OnPlotClear, id=212) + self.Bind(wx.EVT_MENU, self.OnPlotClear, id=212) menu.Append(213, '&Scale', 'Scale canvas') - self.Bind(wx.EVT_MENU,self.OnPlotScale, id=213) - menu.Append(214, 'Enable &Zoom', 'Enable Mouse Zoom', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableZoom, id=214) + self.Bind(wx.EVT_MENU, self.OnPlotScale, id=213) + menu.Append( + 214, 'Enable &Zoom', 'Enable Mouse Zoom', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableZoom, id=214) menu.Append(215, 'Enable &Grid', 'Turn on Grid', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableGrid, id=215) - menu.Append(217, 'Enable &Drag', 'Activates dragging mode', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableDrag, id=217) - menu.Append(220, 'Enable &Legend', 'Turn on Legend', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableLegend, id=220) - menu.Append(222, 'Enable &Point Label', 'Show Closest Point', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnablePointLabel, id=222) + self.Bind(wx.EVT_MENU, self.OnEnableGrid, id=215) + menu.Append( + 217, 'Enable &Drag', 'Activates dragging mode', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableDrag, id=217) + menu.Append( + 220, 'Enable &Legend', 'Turn on Legend', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableLegend, id=220) + menu.Append( + 222, 'Enable &Point Label', 'Show Closest Point', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnablePointLabel, id=222) - menu.Append(223, 'Enable &Anti-Aliasing', 'Smooth output', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableAntiAliasing, id=223) - menu.Append(224, 'Enable &High-Resolution AA', 'Draw in higher resolution', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableHiRes, id=224) + menu.Append( + 223, 'Enable &Anti-Aliasing', 'Smooth output', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableAntiAliasing, id=223) + menu.Append(224, 'Enable &High-Resolution AA', + 'Draw in higher resolution', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableHiRes, id=224) - menu.Append(226, 'Enable Center Lines', 'Draw center lines', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableCenterLines, id=226) - menu.Append(227, 'Enable Diagonal Lines', 'Draw diagonal lines', kind=wx.ITEM_CHECK) - self.Bind(wx.EVT_MENU,self.OnEnableDiagonals, id=227) + menu.Append( + 226, 'Enable Center Lines', 'Draw center lines', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableCenterLines, id=226) + menu.Append( + 227, 'Enable Diagonal Lines', 'Draw diagonal lines', kind=wx.ITEM_CHECK) + self.Bind(wx.EVT_MENU, self.OnEnableDiagonals, id=227) - menu.Append(231, 'Set Gray Background', 'Change background colour to gray') - self.Bind(wx.EVT_MENU,self.OnBackgroundGray, id=231) - menu.Append(232, 'Set &White Background', 'Change background colour to white') - self.Bind(wx.EVT_MENU,self.OnBackgroundWhite, id=232) - menu.Append(233, 'Set Red Label Text', 'Change label text colour to red') - self.Bind(wx.EVT_MENU,self.OnForegroundRed, id=233) - menu.Append(234, 'Set &Black Label Text', 'Change label text colour to black') - self.Bind(wx.EVT_MENU,self.OnForegroundBlack, id=234) + menu.Append( + 231, 'Set Gray Background', 'Change background colour to gray') + self.Bind(wx.EVT_MENU, self.OnBackgroundGray, id=231) + menu.Append( + 232, 'Set &White Background', 'Change background colour to white') + self.Bind(wx.EVT_MENU, self.OnBackgroundWhite, id=232) + menu.Append( + 233, 'Set Red Label Text', 'Change label text colour to red') + self.Bind(wx.EVT_MENU, self.OnForegroundRed, id=233) + menu.Append( + 234, 'Set &Black Label Text', 'Change label text colour to black') + self.Bind(wx.EVT_MENU, self.OnForegroundBlack, id=234) menu.Append(225, 'Scroll Up 1', 'Move View Up 1 Unit') - self.Bind(wx.EVT_MENU,self.OnScrUp, id=225) + self.Bind(wx.EVT_MENU, self.OnScrUp, id=225) menu.Append(230, 'Scroll Rt 2', 'Move View Right 2 Units') - self.Bind(wx.EVT_MENU,self.OnScrRt, id=230) + self.Bind(wx.EVT_MENU, self.OnScrRt, id=230) menu.Append(235, '&Plot Reset', 'Reset to original plot') - self.Bind(wx.EVT_MENU,self.OnReset, id=235) + self.Bind(wx.EVT_MENU, self.OnReset, id=235) self.mainmenu.Append(menu, '&Plot') @@ -2200,7 +2307,7 @@ class TestFrame(wx.Frame): self.CreateStatusBar(1) self.client = PlotCanvas(self) - #define the function for drawing pointLabels + # define the function for drawing pointLabels self.client.SetPointLabelFunc(self.DrawPointLabel) # Create mouse event for showing cursor coords in status bar self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) @@ -2220,38 +2327,43 @@ class TestFrame(wx.Frame): """ # ---------- dc.SetPen(wx.Pen(wx.BLACK)) - dc.SetBrush(wx.Brush( wx.BLACK, wx.BRUSHSTYLE_SOLID ) ) + dc.SetBrush(wx.Brush(wx.BLACK, wx.BRUSHSTYLE_SOLID)) - sx, sy = mDataDict["scaledXY"] #scaled x,y of closest point - dc.DrawRectangle( sx-5,sy-5, 10, 10) #10by10 square centered on point - px,py = mDataDict["pointXY"] + sx, sy = mDataDict["scaledXY"] # scaled x,y of closest point + # 10by10 square centered on point + dc.DrawRectangle(sx - 5, sy - 5, 10, 10) + px, py = mDataDict["pointXY"] cNum = mDataDict["curveNum"] pntIn = mDataDict["pIndex"] legend = mDataDict["legend"] - #make a string to display - s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn) - dc.DrawText(s, sx , sy+1) + # make a string to display + s = "Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" % ( + cNum, legend, px, py, pntIn) + dc.DrawText(s, sx, sy + 1) # ----------- - def OnMouseLeftDown(self,event): - s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(event) + def OnMouseLeftDown(self, event): + s = "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY( + event) self.SetStatusText(s) - event.Skip() #allows plotCanvas OnMouseLeftDown to be called + event.Skip() # allows plotCanvas OnMouseLeftDown to be called def OnMotion(self, event): - #show closest point (when enbled) + # show closest point (when enbled) if self.client.GetEnablePointLabel() == True: - #make up dict with info for the pointLabel - #I've decided to mark the closest point on the closest curve - dlst= self.client.GetClosestPoint( self.client._getXY(event), pointScaled= True) - if dlst != []: #returns [] if none + # make up dict with info for the pointLabel + # I've decided to mark the closest point on the closest curve + dlst = self.client.GetClosestPoint( + self.client._getXY(event), pointScaled=True) + if dlst != []: # returns [] if none curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst - #make up dictionary to pass to my user function (see DrawPointLabel) - mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\ - "pointXY":pointXY, "scaledXY":scaledXY} - #pass dict to update the pointLabel + # make up dictionary to pass to my user function (see + # DrawPointLabel) + mDataDict = {"curveNum": curveNum, "legend": legend, "pIndex": pIndex, + "pointXY": pointXY, "scaledXY": scaledXY} + # pass dict to update the pointLabel self.client.UpdatePointLabel(mDataDict) - event.Skip() #go to next handler + event.Skip() # go to next handler def OnFilePageSetup(self, event): self.client.PageSetup() @@ -2278,7 +2390,8 @@ class TestFrame(wx.Frame): def OnPlotDraw3(self, event): self.resetDefaults() - self.client.SetFont(wx.Font(10,wx.FONTFAMILY_SCRIPT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL)) + self.client.SetFont( + wx.Font(10, wx.FONTFAMILY_SCRIPT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) self.client.SetFontSizeAxis(20) self.client.SetFontSizeLegend(12) self.client.SetXSpec('min') @@ -2287,48 +2400,48 @@ class TestFrame(wx.Frame): def OnPlotDraw4(self, event): self.resetDefaults() - drawObj= _draw4Objects() + drawObj = _draw4Objects() self.client.Draw(drawObj) -## # profile +# profile ## start = _time.clock() -## for x in range(10): -## self.client.Draw(drawObj) +# for x in range(10): +# self.client.Draw(drawObj) ## print("10 plots of Draw4 took: %f sec."%(_time.clock() - start)) -## # profile end +# profile end def OnPlotDraw5(self, event): # Empty plot with just axes self.resetDefaults() - drawObj= _draw5Objects() + drawObj = _draw5Objects() # make the axis X= (0,5), Y=(0,10) # (default with None is X= (-1,1), Y= (-1,1)) - self.client.Draw(drawObj, xAxis= (0,5), yAxis= (0,10)) + self.client.Draw(drawObj, xAxis=(0, 5), yAxis= (0, 10)) def OnPlotDraw6(self, event): - #Bar Graph Example + # Bar Graph Example self.resetDefaults() - #self.client.SetEnableLegend(True) #turn on Legend - #self.client.SetEnableGrid(True) #turn on Grid - self.client.SetXSpec('none') #turns off x-axis scale + # self.client.SetEnableLegend(True) #turn on Legend + # self.client.SetEnableGrid(True) #turn on Grid + self.client.SetXSpec('none') # turns off x-axis scale self.client.SetYSpec('auto') - self.client.Draw(_draw6Objects(), xAxis= (0,7)) + self.client.Draw(_draw6Objects(), xAxis=(0, 7)) def OnPlotDraw7(self, event): - #log scale example + # log scale example self.resetDefaults() - self.client.setLogScale((True,True)) + self.client.setLogScale((True, True)) self.client.Draw(_draw7Objects()) - def OnPlotRedraw(self,event): + def OnPlotRedraw(self, event): self.client.Redraw() - def OnPlotClear(self,event): + def OnPlotClear(self, event): self.client.Clear() def OnPlotScale(self, event): if self.client.last_draw != None: - graphics, xAxis, yAxis= self.client.last_draw - self.client.Draw(graphics,(1,3.05),(0,1)) + graphics, xAxis, yAxis = self.client.last_draw + self.client.Draw(graphics, (1, 3.05), (0, 1)) def OnEnableZoom(self, event): self.client.SetEnableZoom(event.IsChecked()) @@ -2378,10 +2491,10 @@ class TestFrame(wx.Frame): def OnScrUp(self, event): self.client.ScrollUp(1) - def OnScrRt(self,event): + def OnScrRt(self, event): self.client.ScrollRight(2) - def OnReset(self,event): + def OnReset(self, event): self.client.Reset() def OnHelpAbout(self, event): @@ -2391,26 +2504,26 @@ class TestFrame(wx.Frame): def resetDefaults(self): """Just to reset the fonts back to the PlotCanvas defaults""" - self.client.SetFont(wx.Font(10,wx.FONTFAMILY_SWISS,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL)) + self.client.SetFont( + wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)) self.client.SetFontSizeAxis(10) self.client.SetFontSizeLegend(7) - self.client.setLogScale((False,False)) + self.client.setLogScale((False, False)) self.client.SetXSpec('auto') self.client.SetYSpec('auto') - def __test(): class MyApp(wx.App): + def OnInit(self): wx.InitAllImageHandlers() frame = TestFrame(None, -1, "PlotCanvas") - #frame.Show(True) + # frame.Show(True) self.SetTopWindow(frame) return True - app = MyApp(0) app.MainLoop()