pySAXS.guisaxs.matplotlibwx — pySAXS 77.September2012 documentation

### Navigation

- index
- modules |
- pySAXS 77.September2012 documentation »
- Module code »

# Source code for pySAXS.guisaxs.matplotlibwx

    from numpy import arange, sin, pi
    import matplotlib

    # uncomment the following to use wx rather than wxagg
    #matplotlib.use('WX')
    #from matplotlib.backends.backend_wx import FigureCanvasWx as FigureCanvas

    # comment out the following to use wx rather than wxagg
    matplotlib.use('WXAgg',warn=False)
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
    from matplotlib.backends.backend_wx import NavigationToolbar2Wx
    from matplotlib import colors
    from matplotlib.figure import Figure
    import matplotlib.font_manager as font_manager
    from pySAXS.guisaxs import pySaxsColors
    import wx
    from pySAXS.guisaxs import wxmpl
    import os
    import itertools

    class data:
        def __init__(self,x,y,label=None,id=None,error=None,color=None):
            self.x=x
            self.y=y
            self.label=label
            self.id=id #id in the list of datas
            self.error=error
            self.color=color

    class PlotFrame(wx.Frame):
        """
        A matplotlib canvas embedded in a wxPython top-level window.

        @cvar ABOUT_TITLE: Title of the "About" dialog.
        @cvar ABOUT_MESSAGE: Contents of the "About" dialog.
        """

        ABOUT_TITLE = 'About wxmpl.PlotFrame'
        ABOUT_MESSAGE = ('wxmpl.PlotFrame \n'
            + 'Written by Ken McIvor <mcivor@iit.edu>\n'
            + 'Copyright 2005-2009 Illinois Institute of Technology\n'
            + "modified for PySAXS by Olivier Tach'e\n"
            + ' CEA / LIONS 2009')

        def __init__(self, parent, id, title, size=(4,4), dpi=96, cursor=True,
         location=True, crosshairs=True, selection=True, zoom=True,
         autoscaleUnzoom=True,axetype=None,**kwds):
            """
            Creates a new PlotFrame top-level window that is the child of the
            wxPython window C{parent} with the wxPython identifier C{id} and the
            title of C{title}.

            All of the named keyword arguments to this constructor have the same
            meaning as those arguments to the constructor of C{PlotPanel}.

            Any additional keyword arguments are passed to the constructor of
            C{wx.Frame}.
            """
            wx.Frame.__init__(self, parent, id, title,size=size, **kwds)
            #convert size (in pixels) into INCH for figure
            sizex=float(size[0])/dpi
            sizey=float(size[1])/dpi
            sizeINCH=(sizex,sizey)

            self.panel = wxmpl.PlotPanel(self, -1, sizeINCH, dpi, cursor, location,
                crosshairs, selection, zoom)

            pData = wx.PrintData()
            pData.SetPaperId(wx.PAPER_LETTER)
            if callable(getattr(pData, 'SetPrinterCommand', None)):
                pData.SetPrinterCommand(POSTSCRIPT_PRINTING_COMMAND)
            self.printer = wxmpl.FigurePrinter(self, pData)

            self.datalist=[]
            self.gridON=True
            self.legendON=True
            self.axetype=4 #lin lin
            if axetype!=None:
                self.axetype=axetype
            self.plotexp=0 #x vs y
            self.linetype=1
            self.ylabel=""
            self.xlabel=""
            self.marker_cycle=itertools.cycle(['.','o','^','v','<','>','s','+','x','D','d','1','2','3','4','h','H','p','|','_'])
            self.marker_fixed=['.','-','.-','o',',','x']
            self.colors=pySaxsColors.listOfColors()
            self.errbar=False
            self.markerSize=5

            self.create_menus()
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.panel, 1, wx.ALL|wx.EXPAND, 5)
            self.SetSizer(sizer)
            self.Fit()

        def create_menus(self):
            mainMenu = wx.MenuBar()
            menu = wx.Menu()

            id = wx.NewId()
            menu.Append(id, '&Save As...\tCtrl+S','Save a copy of the current plot')
            wx.EVT_MENU(self, id, self.OnMenuFileSave)

            menu.AppendSeparator()

            if wx.Platform != '__WXMAC__':
                id = wx.NewId()
                menu.Append(id, 'Page Set&up...',
                    'Set the size and margins of the printed figure')
                wx.EVT_MENU(self, id, self.OnMenuFilePageSetup)

                id = wx.NewId()
                menu.Append(id, 'Print Pre&view...',
                    'Preview the print version of the current plot')
                wx.EVT_MENU(self, id, self.OnMenuFilePrintPreview)

            id = wx.NewId()
            menu.Append(id, '&Print...\tCtrl+P', 'Print the current plot')
            wx.EVT_MENU(self, id, self.OnMenuFilePrint)

            menu.AppendSeparator()

            id = wx.NewId()
            menu.Append(id, '&Close Window\tCtrl+W',
                'Close the current plot window')
            wx.EVT_MENU(self, id, self.OnMenuFileClose)

            mainMenu.Append(menu, '&File')
            #-- grid --
            menu=wx.Menu()
            submenu=wx.Menu()
            item = submenu.Append(30, 'Grid ON', 'Grid On',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnGridOn, item)
            submenu.Check(30, True)
            item = submenu.Append(31, 'Grid OFF', 'Grid Off',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnGridOff, item)
            item=menu.AppendMenu(wx.ID_ANY, '&Grid',submenu)
            #-- legend --
            submenu=wx.Menu()
            item = submenu.Append(20, 'Legend ON', 'Legend On',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLegendOn, item)
            submenu.Check(20, True)
            item = submenu.Append(21, 'Legend OFF', 'Legend Off',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLegendOff, item)
            item = submenu.Append(22, 'x Label', 'x Label')
            self.Bind(wx.EVT_MENU, self.OnLegendXYtitle, item)
            item = submenu.Append(23, 'y Label', 'y Label')
            self.Bind(wx.EVT_MENU, self.OnLegendXYtitle, item)
            item=menu.AppendMenu(wx.ID_ANY, '&Legend and title',submenu)
            #-- line format --
            submenu=wx.Menu()
            item = submenu.Append(11, 'Points', 'With points',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(12, 'Line', 'With lines',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            submenu.Check(12, True)
            item = submenu.Append(13, 'Line and Points', 'With linepoints',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(17, 'Automatic marker with line', 'Automatic marker',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(14, 'Circle', 'With circle',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(15, 'Pixel', 'With pixel marker',kind=wx.wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(16, 'x', 'With x marker',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormat, item)
            item = submenu.Append(17, 'Line With error bar', 'With error bar (if any)',kind=wx.ITEM_RADIO)#kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLineFormatErrorBar, item)
            item=menu.AppendMenu(wx.ID_ANY, '&Line format',submenu)

            #-- marker --
            submenu=wx.Menu()
            item = submenu.Append(100, '+', 'marker size +')
            self.Bind(wx.EVT_MENU, self.OnMarkerChange, item)
            item = submenu.Append(101, '-', 'marker size -')
            self.Bind(wx.EVT_MENU, self.OnMarkerChange, item)
            item=menu.AppendMenu(wx.ID_ANY, 'Marker size',submenu)
            #-- axes --
            submenu=wx.Menu()
            self.autoscaleitem = submenu.Append(5, 'Autoscale', 'autoscale',kind=wx.ITEM_CHECK)
            self.Bind(wx.EVT_MENU, self.OnAutoscale, self.autoscaleitem)
            submenu.Check(5, True)
            item = submenu.Append(6, 'Set X range', 'Set X range')
            self.Bind(wx.EVT_MENU, self.OnXYRange, item)
            item = submenu.Append(7, 'Set Y range', 'Set Y range')
            self.Bind(wx.EVT_MENU, self.OnXYRange, item)
            item = submenu.Append(4, '&xLin-xLin', 'Lin-Lin Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLogPlotType, item)
            item = submenu.Append(1, '&xLog-yLog', 'Log-Log Plot type',kind=wx.ITEM_RADIO)

            self.Bind(wx.EVT_MENU, self.OnLogPlotType, item)
            item = submenu.Append(2, '&xLog-yLin', 'Log-Lin Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLogPlotType, item)
            item = submenu.Append(3, '&xLin-yLog', 'Lin-Log Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnLogPlotType, item)
            submenu.Check(self.axetype, True)
            item=menu.AppendMenu(wx.ID_ANY, '&Axes',submenu)

            #-- type --
            submenu=wx.Menu()
            item = submenu.Append(40, 'x y', 'x vs y type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnPlotXYType, item)
            item = submenu.Append(41, 'x*y', 'x vs x*y Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnPlotXYType, item)
            item = submenu.Append(42, 'x*y2', 'x vs x*y2 Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnPlotXYType, item)
            item = submenu.Append(43, 'x*y3', 'x vs x*y3 Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnPlotXYType, item)
            item = submenu.Append(44, 'x*y4', 'x vs x*y4 Plot type',kind=wx.ITEM_RADIO)
            self.Bind(wx.EVT_MENU, self.OnPlotXYType, item)
            item=menu.AppendMenu(wx.ID_ANY, '&Y Axes',submenu)

            mainMenu.Append(menu, '&Plot') # Add the file menu to the menu bar

            menu = wx.Menu()
            id = wx.NewId()
            menu.Append(id, '&About...', 'Display version information')
            wx.EVT_MENU(self, id, self.OnMenuHelpAbout)

            mainMenu.Append(menu, '&Help')
            self.SetMenuBar(mainMenu)

        def OnMenuFileSave(self, evt):
            """
            Handles File->Save menu events.
            """
            fileName = wx.FileSelector('Save Plot', default_extension='png',
                wildcard=('Portable Network Graphics (*.png)|*.png|'
                    + 'Encapsulated Postscript (*.eps)|*.eps|All files (*.*)|*.*'),
                parent=self, flags=wx.SAVE|wx.OVERWRITE_PROMPT)

            if not fileName:
                return

            path, ext = os.path.splitext(fileName)
            ext = ext[1:].lower()

            if ext != 'png' and ext != 'eps':
                error_message = (
                    'Only the PNG and EPS image formats are supported.\n'
                    'A file extension of `png\' or `eps\' must be used.')
                wx.MessageBox(error_message, 'Error - plotit',
                    parent=self, style=wx.OK|wx.ICON_ERROR)
                return

            try:
                self.panel.print_figure(fileName)
            except IOError, e:
                if e.strerror:
                    err = e.strerror
                else:
                    err = e

                wx.MessageBox('Could not save file: %s' % err, 'Error - plotit',
                    parent=self, style=wx.OK|wx.ICON_ERROR)

        def OnMenuFilePageSetup(self, evt):
            """
            Handles File->Page Setup menu events
            """
            self.printer.pageSetup()

        def OnMenuFilePrintPreview(self, evt):
            """
            Handles File->Print Preview menu events
            """
            self.printer.previewFigure(self.get_figure())

        def OnMenuFilePrint(self, evt):
            """
            Handles File->Print menu events
            """
            self.printer.printFigure(self.get_figure())

        def OnMenuFileClose(self, evt):
            """
            Handles File->Close menu events.
            """
            self.Close()
            self=None

        def OnMenuHelpAbout(self, evt):
            """
            Handles Help->About menu events.
            """
            wx.MessageBox(self.ABOUT_MESSAGE, self.ABOUT_TITLE, parent=self,
                style=wx.OK)

        def OnGridOn(self,event):
            self.gridON=True
            self.replot()

        def OnGridOff(self,event):
            self.gridON=False
            self.replot()

        def OnLegendOn(self,event):
            self.legendON=True
            self.replot()

        def OnLegendOff(self,event):
            self.legendON=False
            self.replot()
        def OnLineFormat(self,event):
            self.errbar=False
            self.linetype=event.GetId()-11
            self.replot()

        def OnLineFormatErrorBar(self,event):
            self.errbar=True
            self.linetype=2 #line and point with error bar
            self.replot()

        def OnLogPlotType(self, event):
            self.axetype=event.GetId()
            self.replot()

        def OnPlotXYType(self,event):
            self.plotexp=event.GetId()-40
            self.replot()

        def OnAutoscale(self,event):
            '''
            if self.autoscaleitem.IsChecked():
            self.statusbar.Show()
            '''
            self.replot()
        def OnMarkerChange(self,event):
            id=event.GetId()
            if id==100:
                self.markerSize+=2
            elif id==101:
                self.markerSize-=2
            #print self.markerSize
            self.replot()

        def OnLegendXYtitle(self,event):
            if event.GetId()==22:
                #set x title
                #message box for entry
                dlg=wx.TextEntryDialog(None,
                                   "Value for x Label :",
                                   "Insert a text for x Label",
                                   self.axes.get_xlabel(),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=str(dlg.GetValue())
                    self.xlabel=value
                    self.replot()
            if event.GetId()==23:
                #set y title
                #message box for entry
                dlg=wx.TextEntryDialog(None,
                                   "Value for y Label :",
                                   "Insert a text for y Label",
                                   self.axes.get_ylabel(),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=str(dlg.GetValue())
                    self.ylabel=value
                    self.replot()

        def OnXYRange(self,event):
            fig = self.get_figure()
            self.axes = fig.gca()
            xlim_min,xlim_max=self.axes.get_xlim()
            ylim_min,ylim_max=self.axes.get_ylim()
            if event.GetId()==6:
                #set x range
                #message box for entry
                dlg=wx.TextEntryDialog(None,
                                   "Value for x min :",
                                   "Value for x min",
                                   defaultValue=str(xlim_min),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=float(dlg.GetValue())
                    xlim_min=value
                    self.autoscaleitem.Check(False)
                dlg=wx.TextEntryDialog(None,
                                   "Value for x max :",
                                   "Value for x max",
                                   defaultValue=str(xlim_max),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=float(dlg.GetValue())
                    xlim_max=value
                    self.autoscaleitem.Check(False)

            if event.GetId()==7:
                #set y range
                #message box for entry
                dlg=wx.TextEntryDialog(None,
                                   "Value for y min :",
                                   "Value for y min",
                                   defaultValue=str(ylim_min),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=float(dlg.GetValue())
                    ylim_min=value
                    self.autoscaleitem.Check(False)
                dlg=wx.TextEntryDialog(None,
                                   "Value for y max :",
                                   "Value for y max",
                                   defaultValue=str(ylim_max),
                                   style=wx.OK|wx.CANCEL)
                if dlg.ShowModal()==wx.ID_OK:
                    value=float(dlg.GetValue())
                    ylim_max=value
                    self.autoscaleitem.Check(False)

            #replot
            self.axes.set_xlim((xlim_min,xlim_max))
            self.axes.set_ylim((ylim_min,ylim_max))
            self.replot()

        def get_figure(self):
            """
            Returns the figure associated with this canvas.
            """
            return self.panel.figure

        def set_cursor(self, state):
            """
            Enable or disable the changing mouse cursor.  When enabled, the cursor
            changes from the normal arrow to a square cross when the mouse enters a
            matplotlib axes on this canvas.
            """
            self.panel.set_cursor(state)

        def set_location(self, state):
            """
            Enable or disable the display of the matplotlib axes coordinates of the
            mouse in the lower left corner of the canvas.
            """
            self.panel.set_location(state)

        def set_crosshairs(self, state):
            """
            Enable or disable drawing crosshairs through the mouse cursor when it
            is inside a matplotlib axes.
            """
            self.panel.set_crosshairs(state)

        def set_selection(self, state):
            """
            Enable or disable area selections, where user selects a rectangular
            area of the canvas by left-clicking and dragging the mouse.
            """
            self.panel.set_selection(state)

        def set_zoom(self, state):
            """
            Enable or disable zooming in when the user makes an area selection and
            zooming out again when the user right-clicks.
            """
            self.panel.set_zoom(state)

        def set_autoscale_unzoom(self, state):
            """
            Enable or disable automatic view rescaling when the user zooms out to
            the initial figure.
            """
            self.panel.set_autoscale_unzoom(state)

        def draw(self):
            """
            Draw the associated C{Figure} onto the screen.
            """
            self.panel.draw()

        def get_marker(self):
            """ Return an infinite, cycling iterator over the available marker symbols.
            or a fixed marker symbol
            """

            #--line style
            if self.linetype<=5:
                #predifined marker
                lstyle=self.marker_fixed[self.linetype]
                #print lstyle
                return lstyle
            else:
                #automatic marker
                return self.marker_cycle.next()+'-'

        def get_color(self,n):
            ''' return a color name from the list of colors
            if n> length of list of colors, return at the beginning
            '''
            if n==None:
                return None
            t=divmod(n,len(self.colors)) #return the no of color in the list
            return self.colors[t[1]]

        def replot(self):
            fig = self.get_figure()
            self.axes = fig.gca()
            xlim_min,xlim_max=self.axes.get_xlim()
            ylim_min,ylim_max=self.axes.get_ylim()
            self.axes.cla() #clear
            #-- autoscale
            if self.autoscaleitem.IsChecked():
                #self.axes.autoscale_view(tight=False, scalex=True, scaley=True)
                self.axes.set_autoscale_on(True)
                pass
            else :
                #print "not auto scale", xlim_min,ylim_min, xlim_max,ylim_max
                #self.axes.autoscale_view(tight=False, scalex=False, scaley=False)
                self.axes.set_autoscale_on(False)
                #self.axes.set_autoscalex_on(False)
                #self.axes.set_autoscaley_on(False)
                self.axes.set_xlim((xlim_min,xlim_max))
                self.axes.set_ylim((ylim_min,ylim_max))
            #-- datas
            for d in self.datalist:
                #which color ?
                col=self.get_color(d.id)
                if d.color!=None:
                    col=d.color
                #print d.label,d.y,d.color
                if d.error!=None and self.errbar:
                    #print "with errorbar"
                    if d.id!=None:
                        self.axes.errorbar(d.x,d.y*(d.x**self.plotexp),yerr=d.error*(d.y**self.plotexp),linestyle='-',marker='.',\
                                           ecolor='b',\
                                           label=d.label,markersize=self.markerSize,color=col)#,label=d.label,markersize=5,fmt=None)
                    else:
                        self.axes.errorbar(d.x,d.y*(d.x**self.plotexp),yerr=d.error,\
                                           linestyle='-',marker='.',label=d.label,markersize=self.markerSize)#,label=d.label,markersize=5,fmt=None)

                elif col!=None:
                    self.axes.plot(d.x,d.y*(d.x**self.plotexp),\
                                   self.get_marker(),\
                                   label=d.label,\
                                   color=col,\
                                   markersize=self.markerSize)
                else :
                    self.axes.plot(d.x,d.y*(d.x**self.plotexp),self.get_marker(),\
                                   label=d.label,markersize=self.markerSize)
            #--grid
            if self.gridON:
                self.axes.get_xaxis().grid(True)
                self.axes.get_yaxis().grid(True)
            else :
                self.axes.get_xaxis().grid(False)
                self.axes.get_yaxis().grid(False)

            #--scale
            if self.axetype==1:
                self.axes.set_xscale('log')
                self.axes.set_yscale('log')
            if self.axetype==2:
                self.axes.set_xscale('log')
                self.axes.set_yscale('linear')
            if self.axetype==3:
                self.axes.set_xscale('linear')
                self.axes.set_yscale('log')
            if self.axetype==4:
                self.axes.set_xscale('linear')
                self.axes.set_yscale('linear')

            #--legend
            if self.legendON:
                font=font_manager.FontProperties(style='italic',size='x-small')
                leg=self.axes.legend(loc='upper right',prop=font)
                #leg.get_frame().set_alpha(0.5)
            else:
                self.axes.legend_ = None
            #-- x and y label
            self.axes.set_xlabel(self.xlabel)
            self.axes.set_ylabel(self.ylabel)
            #self.axes.set_title('Minimum Message Length')
            self.draw()

        def addData(self,x,y,label=None,id=None,error=None,color=None):
            ''' datas to the plot
            x and y are datas
            label : the name of datas
            id : no of datas in a list -> give the colors
            '''
            newdata=data(x,y,label,id,error,color=color)
            #self.datalist.append([x,y,label,id])
            self.datalist.append(newdata)

        def clearData(self):
            self.datalist=[]

    if __name__== '__main__':
        from numpy import *
        app = wx.App()
        frame = PlotFrame(None, 1,"Monocylinder",size=(700,500))
        frame.Show(True)
        from pySAXS.models import MonoCylinder
        modl=MonoCylinder()
        x=modl.q
        y=modl.getIntensity()
        err=ones(shape(x))#random.rand(len(x))/10
        #err=err*y
        #print err
        frame.addData(x, y, label='monocylinder',error=err)
        frame.xlabel="q (A)"
        frame.ylabel="I (cm-1)"
        frame.replot()
        app.MainLoop()

### Navigation

- index
- modules |
- pySAXS 77.September2012 documentation »
- Module code »