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 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 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 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()