diff --git a/wx/lib/plot.py b/wx/lib/plot.py index bcaaffcb..6587fb9b 100644 --- a/wx/lib/plot.py +++ b/wx/lib/plot.py @@ -27,7 +27,7 @@ # # Oct 15, 2004 Gordon Williams (g_will@cyberus.ca) # - Imported modules given leading underscore to name. -# - Added Cursor Line Tracking and User Point Labels. +# - Added Cursor Line Tracking and User Point Labels. # - Demo for Cursor Line Tracking and Point Labels. # - Size of plot preview frame adjusted to show page better. # - Added helper functions PositionUserToScreen and PositionScreenToUser in PlotCanvas. @@ -42,18 +42,18 @@ # - Added PolySpline class and modified demo 1 and 2 to use it # - Added center and diagonal lines option (Set/GetEnableCenterLines, # Set/GetEnableDiagonals) -# - Added anti-aliasing option with optional high-resolution mode +# - Added anti-aliasing option with optional high-resolution mode # (Set/GetEnableAntiAliasing, Set/GetEnableHiRes) and demo # - Added option to specify exact number of tick marks to use for each axis # (SetXSpec(, SetYSpec() -- work like 'min', but with # tick marks) -# - Added support for background and foreground colours (enabled via +# - Added support for background and foreground colours (enabled via # SetBackgroundColour/SetForegroundColour on a PlotCanvas instance) -# - Changed PlotCanvas printing initialization from occuring in __init__ to +# - Changed PlotCanvas printing initialization from occuring in __init__ to # occur on access. This will postpone any IPP and / or CUPS warnings -# which appear on stderr on some Linux systems until printing functionality +# which appear on stderr on some Linux systems until printing functionality # is actually used. -# +# # """ @@ -61,8 +61,8 @@ This is a simple light weight plotting module that can be used with Boa or easily integrated into your own wxPython application. The emphasis is on small size and fast plotting for large data sets. It has a reasonable number of features to do line and scatter graphs -easily as well as simple bar graphs. It is not as sophisticated or -as powerful as SciPy Plt or Chaco. Both of these are great packages +easily as well as simple bar graphs. It is not as sophisticated or +as powerful as SciPy Plt or Chaco. Both of these are great packages but consume huge amounts of computer resources for simple plots. They can be found at http://scipy.com @@ -85,7 +85,7 @@ Major Additions Gordon Williams Feb. 2003 (g_will@cyberus.ca) -Doc strings and lots of comments -Optimizations for large number of points -Legends - + Did a lot of work here to speed markers up. Only a factor of 4 improvement though. Lines are much faster than markers, especially filled markers. Stay away from circles and triangles unless you @@ -144,14 +144,14 @@ class PolyPoints: self.scaled = self.points self.attributes = {} self.attributes.update(self._attributes) - for name, value in attr.items(): + 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() self.attributes[name] = value - + def setLogScale(self, logscale): self._logscale = logscale - + def __getattr__(self, name): if name == 'points': if len(self._points)>0: @@ -165,7 +165,7 @@ class PolyPoints: return self._points else: raise AttributeError, name - + def log10(self, data, ind): data = _Numeric.compress(data[:,ind]>0,data,0) data[:,ind] = _Numeric.log10(data[:,ind]) @@ -192,7 +192,7 @@ class PolyPoints: self.currentScale= scale self.currentShift= shift # else unchanged use the current scaling - + def getLegend(self): return self.attributes['legend'] @@ -215,13 +215,13 @@ class PolyPoints: pntIndex = _Numeric.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. """ - + _attributes = {'colour': 'black', 'width': 1, 'style': wx.SOLID, @@ -230,16 +230,16 @@ class PolyLine(PolyPoints): def __init__(self, points, **attr): """ Creates PolyLine object - + :param `points`: sequence (array, tuple or list) of (x,y) points making up line :keyword `attr`: keyword attributes, default to: - ========================== ================================ - 'colour'= 'black' wx.Pen Colour any wx.NamedColour + ========================== ================================ + 'colour'= 'black' wx.Pen Colour any wx.Colour 'width'= 1 Pen width 'style'= wx.SOLID wx.Pen style 'legend'= '' Line Legend to display - ========================== ================================ + ========================== ================================ """ PolyPoints.__init__(self, points, attr) @@ -249,7 +249,7 @@ class PolyLine(PolyPoints): width = self.attributes['width'] * printerScale * self._pointSize[0] style= self.attributes['style'] if not isinstance(colour, wx.Colour): - colour = wx.NamedColour(colour) + colour = wx.Colour(colour) pen = wx.Pen(colour, width, style) pen.SetCap(wx.CAP_BUTT) dc.SetPen(pen) @@ -282,12 +282,12 @@ class PolySpline(PolyLine): :param `points`: sequence (array, tuple or list) of (x,y) points making up spline :keyword `attr`: keyword attributes, default to: - ========================== ================================ - 'colour'= 'black' wx.Pen Colour any wx.NamedColour + ========================== ================================ + 'colour'= 'black' wx.Pen Colour any wx.Colour 'width'= 1 Pen width 'style'= wx.SOLID wx.Pen style 'legend'= '' Line Legend to display - ========================== ================================ + ========================== ================================ """ PolyLine.__init__(self, points, **attr) @@ -297,7 +297,7 @@ class PolySpline(PolyLine): width = self.attributes['width'] * printerScale * self._pointSize[0] style= self.attributes['style'] if not isinstance(colour, wx.Colour): - colour = wx.NamedColour(colour) + colour = wx.Colour(colour) pen = wx.Pen(colour, width, style) pen.SetCap(wx.CAP_ROUND) dc.SetPen(pen) @@ -311,7 +311,7 @@ class PolyMarker(PolyPoints): """Class to define marker type and style - All methods except __init__ are private. """ - + _attributes = {'colour': 'black', 'width': 1, 'size': 2, @@ -327,16 +327,16 @@ class PolyMarker(PolyPoints): :param `points`: sequence (array, tuple or list) of (x,y) points :keyword `attr`: keyword attributes, default to: - ============================ ================================ - 'colour'= 'black' wx.Pen Colour any wx.NamedColour + ============================ ================================ + 'colour'= 'black' wx.Pen Colour any wx.Colour 'width'= 1 Pen width 'size'= 2 Marker size - 'fillcolour'= same as colour wx.Brush Colour any wx.NamedColour + 'fillcolour'= same as colour wx.Brush Colour any wx.Colour 'fillstyle'= wx.SOLID wx.Brush fill style (use wx.TRANSPARENT for no fill) 'style'= wx.SOLID wx.Pen style 'marker'= 'circle' Marker shape 'legend'= '' Line Legend to display - ============================ ================================ + ============================ ================================ Marker Shapes: - 'circle' @@ -347,7 +347,7 @@ class PolyMarker(PolyPoints): - 'cross' - 'plus' """ - + PolyPoints.__init__(self, points, attr) def draw(self, dc, printerScale, coord= None): @@ -359,10 +359,10 @@ class PolyMarker(PolyPoints): marker = self.attributes['marker'] if colour and not isinstance(colour, wx.Colour): - colour = wx.NamedColour(colour) + colour = wx.Colour(colour) if fillcolour and not isinstance(fillcolour, wx.Colour): - fillcolour = wx.NamedColour(fillcolour) - + fillcolour = wx.Colour(fillcolour) + dc.SetPen(wx.Pen(colour, width)) if fillcolour: dc.SetBrush(wx.Brush(fillcolour,fillstyle)) @@ -413,7 +413,7 @@ class PolyMarker(PolyPoints): poly.shape= (len(coords),3,2) poly += shape dc.DrawPolygonList(poly.astype(_Numeric.Int32)) - + def _cross(self, dc, coords, size=1): fact= 2.5*size for f in [[-fact,-fact,fact,fact],[-fact,fact,fact,-fact]]: @@ -453,7 +453,7 @@ class PlotGraphics: return for o in self.objects: o.setLogScale(logscale) - + def boundingBox(self): p1, p2 = self.objects[0].boundingBox() for o in self.objects[1:]: @@ -477,7 +477,7 @@ class PlotGraphics: def setYLabel(self, yLabel= ''): """Set the Y axis label on the graph""" self.yLabel= yLabel - + def setTitle(self, title= ''): """Set the title at the top of graph""" self.title= title @@ -511,14 +511,14 @@ class PlotGraphics: oSymExt = o.getSymExtent(printerScale) symExt = _Numeric.maximum(symExt, oSymExt) return symExt - + def getLegendNames(self): """Returns list of legend names""" lst = [None]*len(self) for i in range(len(self)): lst[i]= self.objects[i].getLegend() return lst - + def __len__(self): return len(self.objects) @@ -539,7 +539,7 @@ class PlotCanvas(wx.Panel): size=wx.DefaultSize, style=0, name="plotCanvas"): """Constructs a panel, which can be a child of a frame or any other non-control window""" - + wx.Panel.__init__(self, parent, id, pos, size, style, name) sizer = wx.FlexGridSizer(2,2,0,0) @@ -553,20 +553,20 @@ class PlotCanvas(wx.Panel): sizer.Add(self.sb_vert, 0, wx.EXPAND) sizer.Add(self.sb_hor, 0, wx.EXPAND) sizer.Add((0,0)) - + sizer.AddGrowableRow(0, 1) sizer.AddGrowableCol(0, 1) self.sb_vert.Show(False) self.sb_hor.Show(False) - + self.SetSizer(sizer) self.Fit() self.border = (1,1) self.SetBackgroundColour("white") - + # Create some mouse events for zooming self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown) self.canvas.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp) @@ -583,10 +583,10 @@ class PlotCanvas(wx.Panel): # set curser as cross-hairs self.canvas.SetCursor(wx.CROSS_CURSOR) - self.HandCursor = wx.CursorFromImage(Hand.GetImage()) - self.GrabHandCursor = wx.CursorFromImage(GrabHand.GetImage()) - self.MagCursor = wx.CursorFromImage(MagPlus.GetImage()) - + self.HandCursor = wx.Cursor(Hand.GetImage()) + self.GrabHandCursor = wx.Cursor(GrabHand.GetImage()) + self.MagCursor = wx.Cursor(MagPlus.GetImage()) + # Things for printing self._print_data = None self._pageSetupData= None @@ -600,10 +600,10 @@ class PlotCanvas(wx.Panel): self._sb_yfullrange = 0 self._sb_xunit = 0 self._sb_yunit = 0 - + self._dragEnabled = False self._screenCoordinates = _Numeric.array([0.0, 0.0]) - + self._logscale = (False, False) # Zooming variables @@ -613,7 +613,7 @@ class PlotCanvas(wx.Panel): self._zoomCorner2= _Numeric.array([0.0, 0.0]) # left mouse up corner self._zoomEnabled= False self._hasDragged= False - + # Drawing Variables self.last_draw = None self._pointScale= 1 @@ -625,7 +625,7 @@ class PlotCanvas(wx.Panel): self._titleEnabled= True self._centerLinesEnabled = False self._diagonalsEnabled = False - + # Fonts self._fontCache = {} self._fontSizeAxis= 10 @@ -643,7 +643,7 @@ class PlotCanvas(wx.Panel): self._logicalFunction = wx.COPY # wx.EQUIV not supported on Mac OS X self._useScientificNotation = False - + self._antiAliasingEnabled = False self._hiResEnabled = False self._pointSize = (1.0, 1.0) @@ -656,11 +656,11 @@ class PlotCanvas(wx.Panel): # platforms at initialization, but little harm done. self.OnSize(None) # sets the initial size based on client size - self._gridColour = wx.NamedColour('black') + self._gridColour = wx.BLACK def SetCursor(self, cursor): self.canvas.SetCursor(cursor) - + def GetGridColour(self): return self._gridColour @@ -668,15 +668,15 @@ class PlotCanvas(wx.Panel): if isinstance(colour, wx.Colour): self._gridColour = colour else: - self._gridColour = wx.NamedColour(colour) + self._gridColour = wx.Colour(colour) + - # SaveFile 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. - + .bmp Save a Windows bitmap file. .xbm Save an X bitmap file. .xpm Save an XPM bitmap file. @@ -705,7 +705,7 @@ class PlotCanvas(wx.Panel): dlg2.Destroy() else: # FileDialog doesn't exist: just check one dlg1 = wx.FileDialog( - self, + 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 @@ -757,7 +757,7 @@ class PlotCanvas(wx.Panel): self._print_data=wx.PrintData(data.GetPrintData()) # updates print_data finally: dlg.Destroy() - + def Printout(self, paper=None): """Print current plot.""" if paper != None: @@ -804,15 +804,15 @@ class PlotCanvas(wx.Panel): def getLogScale(self): return self._logscale - + def SetFontSizeAxis(self, point= 10): """Set the tick and axis label font size (default is 10 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): """Set Title font size (default is 15 point)""" self._fontSizeTitle= point @@ -820,11 +820,11 @@ class PlotCanvas(wx.Panel): def GetFontSizeTitle(self): """Get current Title font size in points""" return self._fontSizeTitle - + def SetFontSizeLegend(self, point= 7): """Set Legend font size (default is 7 point)""" self._fontSizeLegend= point - + def GetFontSizeLegend(self): """Get current Legend font size in points""" return self._fontSizeLegend @@ -876,10 +876,10 @@ class PlotCanvas(wx.Panel): else: self.SetCursor(wx.CROSS_CURSOR) self._dragEnabled = value - + def GetEnableDrag(self): return self._dragEnabled - + def SetEnableZoom(self, value): """Set True to enable zooming.""" if value not in [True,False]: @@ -919,7 +919,7 @@ class PlotCanvas(wx.Panel): return self._centerLinesEnabled def SetEnableDiagonals(self, value): - """Set True, 'Bottomleft-Topright' or 'Bottomright-Topleft' to enable + """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" @@ -934,7 +934,7 @@ class PlotCanvas(wx.Panel): """Set True to enable legend.""" 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): @@ -945,7 +945,7 @@ class PlotCanvas(wx.Panel): """Set True to enable title.""" 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): @@ -956,7 +956,7 @@ class PlotCanvas(wx.Panel): """Set True to enable pointLabel.""" if value not in [True,False]: raise TypeError, "Value should be True or False" - self._pointLabelEnabled= value + self._pointLabelEnabled= value self.Redraw() #will erase existing pointLabel if present self.last_PointLabel = None @@ -979,8 +979,8 @@ class PlotCanvas(wx.Panel): self.last_PointLabel = None #reset pointLabel if self.last_draw is not None: self._Draw(self.last_draw[0]) - - def ScrollRight(self, units): + + def ScrollRight(self, units): """Move view right number of axis units.""" self.last_PointLabel = None #reset pointLabel if self.last_draw is not None: @@ -1004,7 +1004,7 @@ class PlotCanvas(wx.Panel): if self.getLogScale()[1]: y = _Numeric.power(10,y) return x,y - + def _getXY(self,event): """Takes a mouse event and returns the XY user axis values.""" x,y= self.PositionScreenToUser(event.GetPosition()) @@ -1015,24 +1015,24 @@ class PlotCanvas(wx.Panel): userPos= _Numeric.array(pntXY) x,y= userPos * self._pointScale + self._pointShift return x,y - + def PositionScreenToUser(self, pntXY): """Converts Screen position to User Coordinates""" screenPos= _Numeric.array(pntXY) x,y= (screenPos-self._pointShift)/self._pointScale return x,y - + def SetXSpec(self, type= 'auto'): """xSpec- defines x axis type. Can be 'none', 'min' or 'auto' where: - + * 'none' - shows no axis or tick mark values * 'min' - shows min bounding box values * 'auto' - rounds axis range to sensible values * - like 'min', but with tick marks """ self._xSpec= type - + def SetYSpec(self, type= 'auto'): """ySpec- defines x axis type. Can be 'none', 'min' or 'auto' where: @@ -1047,11 +1047,11 @@ class PlotCanvas(wx.Panel): def GetXSpec(self): """Returns current XSpec for axis""" return self._xSpec - + def GetYSpec(self): """Returns current YSpec for axis""" return self._ySpec - + def GetXMaxRange(self): xAxis = self._getXMaxRange() if self.getLogScale()[0]: @@ -1087,7 +1087,7 @@ class PlotCanvas(wx.Panel): def _getXCurrentRange(self): """Returns (minX, maxX) x-axis for currently displayed portion of graph""" return self.last_draw[1] - + def GetYCurrentRange(self): yAxis = self._getYCurrentRange() if self.getLogScale()[1]: @@ -1100,15 +1100,15 @@ class PlotCanvas(wx.Panel): 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)) - + # check case for axis = (a,b) where a==b caused by improper zooms if xAxis != None: if xAxis[0] == xAxis[1]: @@ -1121,19 +1121,19 @@ class PlotCanvas(wx.Panel): if self.getLogScale()[1]: yAxis = _Numeric.log10(yAxis) self._Draw(graphics, xAxis, yAxis, dc) - + 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 xAxis - tuple with (min, max) axis range to view yAxis - same as xAxis - dc - drawing context - doesn't have to be specified. + dc - drawing context - doesn't have to be specified. If it's not, the offscreen buffer is used """ if dc == None: - # sets new dc and clears it + # sets new dc and clears it dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer) bbr = wx.Brush(self.GetBackgroundColour(), wx.SOLID) dc.SetBackground(bbr) @@ -1161,13 +1161,13 @@ class PlotCanvas(wx.Panel): ppi = dc.GetPPI() self._fontScale = (96.0 / ppi[0] * self._pointSize[0] + 96.0 / ppi[1] * self._pointSize[1]) / 2.0 graphics._pointSize = self._pointSize - + dc.SetTextForeground(self.GetForegroundColour()) dc.SetTextBackground(self.GetBackgroundColour()) - dc.BeginDrawing() + # dc.BeginDrawing() # dc.Clear() - + # set font size for every thing but title and legend dc.SetFont(self._getFont(self._fontSizeAxis)) @@ -1190,7 +1190,7 @@ class PlotCanvas(wx.Panel): self.last_draw = (graphics, _Numeric.array(xAxis), _Numeric.array(yAxis)) # saves most recient values # Get ticks and textExtents for axis if required - if self._xSpec is not 'none': + 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: @@ -1248,12 +1248,12 @@ class PlotCanvas(wx.Panel): scale = (self.plotbox_size-textSize_scale) / (p2-p1)* _Numeric.array((1,-1)) shift = -p1*scale + self.plotbox_origin + textSize_shift * _Numeric.array((1,-1)) self._pointScale= scale / self._pointSize # make available for mouse events - self._pointShift= shift / 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 - + # set clipping area so drawing does not occur outside axis box ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(p1, p2) # allow graph to overlap axis lines by adding units to width and height @@ -1264,10 +1264,10 @@ class PlotCanvas(wx.Panel): # print "entire graphics drawing took: %f second"%(_time.clock() - start) # remove the clipping region dc.DestroyClippingRegion() - dc.EndDrawing() + # dc.EndDrawing() self._adjustScrollbars() - + def Redraw(self, dc=None): """Redraw the existing plot.""" if self.last_draw is not None: @@ -1305,13 +1305,13 @@ class PlotCanvas(wx.Panel): 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): """Returns list with [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] list for each curve. Returns [] if no curves are being plotted. - + x, y in user coords if pointScaled == True based on screen coords if pointScaled == False based on user coords @@ -1335,7 +1335,7 @@ class PlotCanvas(wx.Panel): [curveNumber, legend, index of closest point, pointXY, scaledXY, distance] list for only the closest curve. Returns [] if no curves are being plotted. - + x, y in user coords if pointScaled == True based on screen coords if pointScaled == False based on user coords @@ -1350,7 +1350,7 @@ class PlotCanvas(wx.Panel): 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 def UpdatePointLabel(self, mDataDict): @@ -1363,7 +1363,7 @@ class PlotCanvas(wx.Panel): you specify. This function can be called from parent window with onClick, - onMotion events etc. + onMotion events etc. """ if self.last_PointLabel != None: #compare pointXY @@ -1397,7 +1397,7 @@ class PlotCanvas(wx.Panel): yAxis -= dist[1] xAxis -= dist[0] self._Draw(graphics,xAxis,yAxis) - + def OnMouseLeftDown(self,event): self._zoomCorner1[0], self._zoomCorner1[1]= self._getXY(event) self._screenCoordinates = _Numeric.array(event.GetPosition()) @@ -1431,7 +1431,7 @@ class PlotCanvas(wx.Panel): # before (possibly) removing the scrollbars and trigering # size events, etc. wx.FutureCall(200,self.Reset) - + def OnMouseRightDown(self,event): if self._zoomEnabled: X,Y = self._getXY(event) @@ -1455,11 +1455,11 @@ class PlotCanvas(wx.Panel): Size = self.canvas.GetClientSize() Size.width = max(1, Size.width) Size.height = max(1, Size.height) - + # Make new offscreen bitmap: this bitmap will always have the # current drawing in it, so it can be used to save the image to # a file, or whatever. - self._Buffer = wx.EmptyBitmap(Size.width, Size.height) + self._Buffer = wx.Bitmap(Size.width, Size.height) self._setSize() self.last_PointLabel = None #reset pointLabel @@ -1480,36 +1480,36 @@ class PlotCanvas(wx.Panel): if not self._adjustingSB: self._sb_ignore = True 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]) self.ScrollUp(dist) - + if evt.GetOrientation() == wx.HORIZONTAL: 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() else: - self.width, self.height= width,height + 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*_Numeric.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 = _Numeric.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 - + def _printDraw(self, printDC): """Used for printing.""" if self.last_draw != None: @@ -1521,23 +1521,23 @@ class PlotCanvas(wx.Panel): width = self._Buffer.GetWidth() height = self._Buffer.GetHeight() if sys.platform != "darwin": - tmp_Buffer = wx.EmptyBitmap(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) - dcs.BeginDrawing() + # dcs.BeginDrawing() self._pointLabelFunc(dcs,mDataDict) #custom user pointLabel function - dcs.EndDrawing() + # dcs.EndDrawing() dc = wx.ClientDC( self.canvas ) #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): """Draws legend symbols and text""" @@ -1579,7 +1579,7 @@ class PlotCanvas(wx.Panel): 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: @@ -1593,7 +1593,7 @@ class PlotCanvas(wx.Panel): txtExt= dc.GetTextExtent(txtList[0]) for txt in graphics.getLegendNames()[1:]: txtExt= _Numeric.maximum(txtExt,dc.GetTextExtent(txt)) - maxW= symExt[0]+txtExt[0] + 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 @@ -1607,13 +1607,13 @@ class PlotCanvas(wx.Panel): ptx,pty,rectWidth,rectHeight= self._point2ClientCoord(corner1, corner2) # draw rectangle dc = wx.ClientDC( self.canvas ) - dc.BeginDrawing() + # dc.BeginDrawing() dc.SetPen(wx.Pen(wx.BLACK)) dc.SetBrush(wx.Brush( wx.WHITE, wx.TRANSPARENT ) ) dc.SetLogicalFunction(wx.INVERT) dc.DrawRectangle( ptx,pty, rectWidth,rectHeight) dc.SetLogicalFunction(wx.COPY) - dc.EndDrawing() + # dc.EndDrawing() def _getFont(self,size): """Take font size, adjusts if printing and returns wx.Font""" @@ -1642,8 +1642,8 @@ class PlotCanvas(wx.Panel): plr= _Numeric.maximum(pt1,pt2) # Lower right corner rectWidth, rectHeight= plr-pul ptx,pty= pul - return ptx, pty, rectWidth, rectHeight - + 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)): @@ -1676,10 +1676,10 @@ class PlotCanvas(wx.Panel): raise ValueError, str(spec) + ': illegal axis specification' def _drawAxes(self, dc, p1, p2, scale, shift, xticks, yticks): - + penWidth= self.printerScale * self._pointSize[0] # increases thickness for printing only 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) @@ -1750,14 +1750,14 @@ class PlotCanvas(wx.Panel): else: attr = {'numticks': self._xSpec} return self._ticks(*args, **attr) - + def _yticks(self, *args): if self._logscale[1]: return self._logticks(*args) else: attr = {'numticks': self._ySpec} return self._ticks(*args, **attr) - + def _logticks(self, lower, upper): #lower,upper = map(_Numeric.log10,[lower,upper]) #print 'logticks',lower,upper @@ -1788,7 +1788,7 @@ class PlotCanvas(wx.Panel): if len(ticks) == 0: ticks = [(0,'')] return ticks - + def _ticks(self, lower, upper, numticks=None): if isinstance(numticks, (float, int)): ideal = (upper-lower)/float(numticks) @@ -1809,7 +1809,7 @@ class PlotCanvas(wx.Panel): factor = f grid = factor * 10.**power if self._useScientificNotation and (power > 4 or power < -4): - format = '%+7.1e' + format = '%+7.1e' elif power >= 0: digits = max(1, int(power)) format = '%' + `digits`+'.0f' @@ -1838,7 +1838,7 @@ class PlotCanvas(wx.Panel): self._adjustingSB = True needScrollbars = False - + # horizontal scrollbar r_current = self._getXCurrentRange() r_max = list(self._getXMaxRange()) @@ -1846,12 +1846,12 @@ class PlotCanvas(wx.Panel): 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) - + if pos >= 0: pagesize = int((r_current[1]-r_current[0])/unit) @@ -1868,12 +1868,12 @@ class PlotCanvas(wx.Panel): 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) - + if pos >= 0: pagesize = int((r_current[1]-r_current[0])/unit) pos = (sbfullrange-1-pos-pagesize) @@ -1928,14 +1928,14 @@ class PlotPrintout(wx.Printout): 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() - + # find what the margins are (mm) 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 + pixRight= margRightSize*PPIPrinter[0]/25.4 pixTop= margTopSize*PPIPrinter[1]/25.4 pixBottom= margBottomSize*PPIPrinter[1]/25.4 @@ -1950,10 +1950,10 @@ class PlotPrintout(wx.Printout): pixTop *= ratioH plotAreaW *= ratioW plotAreaH *= ratioH - + # rescale plot to page or preview plot area self.graph._setSize(plotAreaW,plotAreaH) - + # Set offset and scale dc.SetDeviceOrigin(pixLeft,pixTop) @@ -2028,7 +2028,7 @@ def _draw1Objects(): 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") def _draw2Objects(): @@ -2120,16 +2120,16 @@ class TestFrame(wx.Frame): menu = wx.Menu() menu.Append(200, 'Page Setup...', 'Setup the printer page') self.Bind(wx.EVT_MENU, self.OnFilePageSetup, id=200) - + menu.Append(201, 'Print Preview...', 'Show the current plot on page') self.Bind(wx.EVT_MENU, self.OnFilePrintPreview, id=201) - + menu.Append(202, 'Print...', 'Print the current plot') self.Bind(wx.EVT_MENU, self.OnFilePrint, id=202) - + menu.Append(203, 'Save Plot...', 'Save current plot') self.Bind(wx.EVT_MENU, self.OnSaveFile, id=203) - + menu.Append(205, 'E&xit', 'Enough of this already!') self.Bind(wx.EVT_MENU, self.OnFileExit, id=205) self.mainmenu.Append(menu, '&File') @@ -2155,9 +2155,9 @@ class TestFrame(wx.Frame): menu.Append(212, '&Clear', 'Clear canvas') self.Bind(wx.EVT_MENU,self.OnPlotClear, id=212) menu.Append(213, '&Scale', 'Scale canvas') - self.Bind(wx.EVT_MENU,self.OnPlotScale, id=213) + 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.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) @@ -2166,17 +2166,17 @@ class TestFrame(wx.Frame): 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(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') @@ -2185,9 +2185,9 @@ class TestFrame(wx.Frame): 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) menu.Append(235, '&Plot Reset', 'Reset to original plot') @@ -2204,7 +2204,7 @@ class TestFrame(wx.Frame): # A status bar to tell people what's happening self.CreateStatusBar(1) - + self.client = PlotCanvas(self) #define the function for drawing pointLabels self.client.SetPointLabelFunc(self.DrawPointLabel) @@ -2227,7 +2227,7 @@ class TestFrame(wx.Frame): # ---------- dc.SetPen(wx.Pen(wx.BLACK)) dc.SetBrush(wx.Brush( wx.BLACK, wx.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"] @@ -2252,7 +2252,7 @@ class TestFrame(wx.Frame): 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) + #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 @@ -2261,13 +2261,13 @@ class TestFrame(wx.Frame): def OnFilePageSetup(self, event): self.client.PageSetup() - + def OnFilePrintPreview(self, event): self.client.PrintPreview() - + def OnFilePrint(self, event): self.client.Printout() - + def OnSaveFile(self, event): self.client.SaveFile() @@ -2277,11 +2277,11 @@ class TestFrame(wx.Frame): def OnPlotDraw1(self, event): self.resetDefaults() self.client.Draw(_draw1Objects()) - + def OnPlotDraw2(self, event): self.resetDefaults() self.client.Draw(_draw2Objects()) - + def OnPlotDraw3(self, event): self.resetDefaults() self.client.SetFont(wx.Font(10,wx.SCRIPT,wx.NORMAL,wx.NORMAL)) @@ -2296,7 +2296,7 @@ class TestFrame(wx.Frame): drawObj= _draw4Objects() self.client.Draw(drawObj) ## # profile -## start = _time.clock() +## start = _time.clock() ## for x in range(10): ## self.client.Draw(drawObj) ## print "10 plots of Draw4 took: %f sec."%(_time.clock() - start) @@ -2330,7 +2330,7 @@ class TestFrame(wx.Frame): def OnPlotClear(self,event): self.client.Clear() - + def OnPlotScale(self, event): if self.client.last_draw != None: graphics, xAxis, yAxis= self.client.last_draw @@ -2339,14 +2339,14 @@ class TestFrame(wx.Frame): def OnEnableZoom(self, event): self.client.SetEnableZoom(event.IsChecked()) self.mainmenu.Check(217, not event.IsChecked()) - + def OnEnableGrid(self, event): self.client.SetEnableGrid(event.IsChecked()) - + def OnEnableDrag(self, event): self.client.SetEnableDrag(event.IsChecked()) self.mainmenu.Check(214, not event.IsChecked()) - + def OnEnableLegend(self, event): self.client.SetEnableLegend(event.IsChecked()) @@ -2364,15 +2364,15 @@ class TestFrame(wx.Frame): def OnEnableDiagonals(self, event): self.client.SetEnableDiagonals(event.IsChecked()) - + def OnBackgroundGray(self, event): self.client.SetBackgroundColour("#CCCCCC") self.client.Redraw() - + def OnBackgroundWhite(self, event): self.client.SetBackgroundColour("white") self.client.Redraw() - + def OnForegroundRed(self, event): self.client.SetForegroundColour("red") self.client.Redraw() @@ -2383,7 +2383,7 @@ class TestFrame(wx.Frame): def OnScrUp(self, event): self.client.ScrollUp(1) - + def OnScrRt(self,event): self.client.ScrollRight(2) @@ -2403,8 +2403,8 @@ class TestFrame(wx.Frame): self.client.setLogScale((False,False)) self.client.SetXSpec('auto') self.client.SetYSpec('auto') - - + + def __test():