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


[docs]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
[docs]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()
[docs] 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)
[docs] 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)
[docs] def OnMenuFilePageSetup(self, evt): """ Handles File->Page Setup menu events """ self.printer.pageSetup()
[docs] def OnMenuFilePrintPreview(self, evt): """ Handles File->Print Preview menu events """ self.printer.previewFigure(self.get_figure())
[docs] def OnMenuFilePrint(self, evt): """ Handles File->Print menu events """ self.printer.printFigure(self.get_figure())
[docs] def OnMenuFileClose(self, evt): """ Handles File->Close menu events. """ self.Close() self=None
[docs] def OnMenuHelpAbout(self, evt): """ Handles Help->About menu events. """ wx.MessageBox(self.ABOUT_MESSAGE, self.ABOUT_TITLE, parent=self, style=wx.OK)
[docs] def OnGridOn(self,event): self.gridON=True self.replot()
[docs] def OnGridOff(self,event): self.gridON=False self.replot()
[docs] def OnLegendOn(self,event): self.legendON=True self.replot()
[docs] def OnLegendOff(self,event): self.legendON=False self.replot()
[docs] def OnLineFormat(self,event): self.errbar=False self.linetype=event.GetId()-11 self.replot()
[docs] def OnLineFormatErrorBar(self,event): self.errbar=True self.linetype=2 #line and point with error bar self.replot()
[docs] def OnLogPlotType(self, event): self.axetype=event.GetId() self.replot()
[docs] def OnPlotXYType(self,event): self.plotexp=event.GetId()-40 self.replot()
[docs] def OnAutoscale(self,event): ''' if self.autoscaleitem.IsChecked(): self.statusbar.Show() ''' self.replot()
[docs] def OnMarkerChange(self,event): id=event.GetId() if id==100: self.markerSize+=2 elif id==101: self.markerSize-=2 #print self.markerSize self.replot()
[docs] 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()
[docs] 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()
[docs] def get_figure(self): """ Returns the figure associated with this canvas. """ return self.panel.figure
[docs] 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)
[docs] 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)
[docs] 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)
[docs] 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)
[docs] 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)
[docs] 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)
[docs] def draw(self): """ Draw the associated C{Figure} onto the screen. """ self.panel.draw()
[docs] 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()+'-'
[docs] 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]]
[docs] 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()
[docs] 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)
[docs] 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()