⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wxpyplot.py

📁 PyChem是用Python语言编写的多元变量分析软件。它包括一个前端图形界面用于管理和保存试验数据
💻 PY
📖 第 1 页 / 共 4 页
字号:
#!/usr/bin/env python2.2

#-----------------------------------------------------------------------------
# Name:        wxPyPlot.py
# Purpose:     
#
# Author:      Gordon Williams
#
# Created:     2003/11/03
# RCS-ID:      $Id: wxPyPlot.py,v 1.1 2005/11/25 16:52:50 baoilleach Exp $
# Copyright:   (c) 2002
# Licence:     Use as you wish.
#-----------------------------------------------------------------------------

"""
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.  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

This file contains two parts; first the re-usable library stuff, then, after
a "if __name__=='__main__'" test, a simple frame and a few default plots
for examples and testing.

Based on wxPlotCanvas
Written by K.Hinsen, R. Srinivasan;
Ported to wxPython Harm van der Heijden, feb 1999

Major Additions Gordon Williams Feb. 2003 (g_will@cyberus.ca)
    -More style options
    -Zooming using mouse "rubber band"
    -Scroll left, right
    -Grid(graticule)
    -Printing, preview, and page set up (margins)
    -Axis and title labels
    -Cursor xy axis values
    -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 only have a few thousand points.

Times for 25,000 points
Line - 0.078 sec
Markers
Square -                   0.22 sec
dot -                      0.10
circle -                   0.87
cross,plus -               0.28
triangle, triangle_down -  0.90

Thanks to Chris Barker for getting this version working on Linux.

Zooming controls with mouse (when enabled):
    Left mouse drag - Zoom box.
    Left mouse double click - reset zoom.
    Right mouse click - zoom out centred on click location.
"""

import time, string, scipy
from wxPython import wx

#
# Plotting classes...
#
class PolyPoints:
    """Base Class for lines and markers
        - All methods are private.
    """

    def __init__(self, points, attr):
        self.points = scipy.array(points)
        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()
            self.attributes[name] = value
        
    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= scipy.array([-1,-1])
            maxXY= scipy.array([ 1, 1])
        else:
            minXY= scipy.minimum.reduce(self.points)
            maxXY= scipy.maximum.reduce(self.points)
        return minXY, maxXY

    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
        #else unchanged use the current scaling
        
    def getLegend(self):
        return self.attributes['legend']


class PolyLine(PolyPoints):
    """Class to define line type and style
        - All methods except __init__ are private.
    """
    
    _attributes = {'colour': 'black',
                   'width': 1,
                   'style': wx.wxSOLID,
                   'legend': ''}

    def __init__(self, points, **attr):
        """Creates PolyLine object
            points - sequence (array, tuple or list) of (x,y) points making up line
            **attr - key word attributes
                Defaults:
                    'colour'= 'black',          - wxPen Colour any wxNamedColour
                    'width'= 1,                 - Pen width
                    'style'= wxSOLID,           - wxPen style
                    'legend'= ''                - Line Legend to display
        """
        PolyPoints.__init__(self, points, attr)

    def draw(self, dc, printerScale, coord= None):
        colour = self.attributes['colour']
        width = self.attributes['width'] * printerScale
        style= self.attributes['style']
        dc.SetPen(wx.wxPen(wx.wxNamedColour(colour), int(width), style))
        if coord == None:
            dc.DrawLines(self.scaled)
        else:
            dc.DrawLines(coord) #draw legend line

    def getSymExtent(self, printerScale):
        """Width and Height of Marker"""
        h= self.attributes['width'] * printerScale
        w= 5 * h
        return (w,h)


class PolyMarker(PolyPoints):
    """Class to define marker type and style
        - All methods except __init__ are private.
    """
  
    _attributes = {'colour': 'black',
                   'width': 1,
                   'size': 2,
                   'fillcolour': None,
                   'fillstyle': wx.wxSOLID,
                   'marker': 'circle',
                   'legend': '',
                   'names': 'XXX',
                   'text_colour': 'black'}

    def __init__(self, points, **attr):
        """Creates PolyMarker object
        points - sequence (array, tuple or list) of (x,y) points
        **attr - key word attributes
            Defaults:
                'colour'= 'black',          - wxPen Colour any wxNamedColour
                'width'= 1,                 - Pen width
                'size'= 2,                  - Marker size
                'fillcolour'= same as colour,      - wxBrush Colour any wxNamedColour
                'fillstyle'= wx.wxSOLID,    - wxBrush fill style (use wxTRANSPARENT for no fill)
                'marker'= 'circle'          - Marker shape
                'legend'= ''                - Marker Legend to display
                
            Marker Shapes:
                - 'circle'
                - 'dot'
                - 'square'
                - 'triangle'
                - 'triangle_down'
                - 'cross'
                - 'plus'
        """
      
        PolyPoints.__init__(self, points, attr)

    def draw(self, dc, printerScale, coord= None):
        colour = self.attributes['colour']
        width = self.attributes['width'] * printerScale
        size = self.attributes['size'] * printerScale
        fillcolour = self.attributes['fillcolour']
        fillstyle = self.attributes['fillstyle']
        marker = self.attributes['marker']
        
        dc.SetPen(wx.wxPen(wx.wxNamedColour(colour),int(width)))
        if fillcolour:
            dc.SetBrush(wx.wxBrush(wx.wxNamedColour(fillcolour),fillstyle))
        else:
            dc.SetBrush(wx.wxBrush(wx.wxNamedColour(colour), fillstyle))
        if coord == None:
            self._drawmarkers(dc, self.scaled, marker, size)
        else:
            self._drawmarkers(dc, coord, marker, size) #draw legend marker

    def getSymExtent(self, printerScale):
        """Width and Height of Marker"""
        s= 5*self.attributes['size'] * printerScale
        return (s,s)

    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= scipy.zeros((len(coords),4),scipy.Float)+[0.0,0.0,wh,wh]
        rect[:,0:2]= coords-[fact,fact]
        dc.DrawEllipseList(rect.astype(scipy.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= scipy.zeros((len(coords),4),scipy.Float)+[0.0,0.0,wh,wh]
        rect[:,0:2]= coords-[fact,fact]
        dc.DrawRectangleList(rect.astype(scipy.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= scipy.repeat(coords,3)
        poly.shape= (len(coords),3,2)
        poly += shape
        dc.DrawPolygonList(poly.astype(scipy.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= scipy.repeat(coords,3)
        poly.shape= (len(coords),3,2)
        poly += shape
        dc.DrawPolygonList(poly.astype(scipy.Int32))
      
    def _cross(self, dc, coords, size=1):
        fact= 2.5*size
        for f in [[-fact,-fact,fact,fact],[-fact,fact,fact,-fact]]:
            lines= scipy.concatenate((coords,coords),axis=1)+f
            dc.DrawLineList(lines.astype(scipy.Int32))

    def _plus(self, dc, coords, size=1):
        fact= 2.5*size
        for f in [[-fact,0,fact,0],[0,-fact,0,fact]]:
            lines= scipy.concatenate((coords,coords),axis=1)+f
            dc.DrawLineList(lines.astype(scipy.Int32))
    
    def _text(self, dc, coords, size=1):
        dc.SetTextForeground(self.attributes['text_colour'])
        if len(coords)==1:
            dc.DrawText(self.attributes['names'],coords[0][0],coords[0][1])
        elif len(coords)==2:
            dc.DrawText(self.attributes['names'],coords[0],coords[1])

class PlotGraphics:
    """Container to hold PolyXXX objects and graph labels
        - All methods except __init__ are private.
    """

    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]:
            raise TypeError, "objects argument should be list or tuple"
        self.objects = objects
        self.title= title
        self.xLabel= xLabel
        self.yLabel= yLabel

    def boundingBox(self):
        p1, p2 = self.objects[0].boundingBox()
        for o in self.objects[1:]:
            p1o, p2o = o.boundingBox()
            p1 = scipy.minimum(p1, p1o)
            p2 = scipy.maximum(p2, p2o)
        return p1, p2

    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

    def setXLabel(self, xLabel= ''):
        """Set the X axis label on the graph"""
        self.xLabel= xLabel

    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

    def getXLabel(self):
        """Get x axis label string"""
        return self.xLabel

    def getYLabel(self):
        """Get y axis label string"""
        return self.yLabel

    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
            o.draw(dc, self.printerScale)
            #dt= time.clock()-t
            #print o, "time=", dt

    def getSymExtent(self, printerScale):
        """Get max width and height of lines and markers symbols for legend"""
        symExt = self.objects[0].getSymExtent(printerScale)
        for o in self.objects[1:]:
            oSymExt = o.getSymExtent(printerScale)
            symExt = scipy.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)

    def __getitem__(self, item):
        return self.objects[item]


#-------------------------------------------------------------------------------
#Main window that you will want to import into your application.

class PlotCanvas(wx.wxWindow):
    """Subclass of a wxWindow to allow simple general plotting
    of data with zoom, labels, and automatic axis scaling."""

    def __init__(self, parent, id = -1, pos=wx.wxDefaultPosition,
            size=wx.wxDefaultSize, style= wx.wxDEFAULT_FRAME_STYLE, name= ""):
        """Constucts a window, which can be a child of a frame, dialog or
        any other non-control window"""
    
        wx.wxWindow.__init__(self, parent, id, pos, size, style, name)
        self.border = (1,1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -