Source code for pySAXS.guisaxs.LSModelDlg

#!/usr/bin/python

import wx
import numpy
import sys
#import pySAXS.LS.LSsca as LSsca
from pySAXS.models import *
from pySAXS.tools import isNumeric

'''
    19-05-2011 OT Remove slider 
    04-08-2010 DC textboxes for parameter values and bounds are now active for typing in
    04-08-2010 DC calculation of chi2 corrected
    03-08-2010 DC typos on the interface corrected
    10-11-2009 print the chi carre
    15-06-2009 now support new model class, use a sizer, fit with or without bounds, remove bugs with slider,...

'''


[docs]class LSModelDlg(wx.Frame): def __init__(self, parent,dataset_name,type="model",pos=wx.Point(50,50)): self.Model=parent.data_dict[dataset_name].model wx.Frame.__init__(self, parent, -1, self.Model.name+" model for "+dataset_name, size=wx.Size(700,40+len(self.Model.Arg)*50),pos=pos,style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN) wx.Frame.SetIcon(self,parent.favicon) # Add a panel so it looks correct on all platforms self.parentwindow=parent self.dataset_name=dataset_name self.type=type Blig=10 Bcol=10 self.par=self.Model.getArg() #self.SetBackgroundColour(self.parentwindow.GetBackgroundColour()) #self.SetBackgroundColour("White") self.itf=self.Model.getIstofit() self.qbase=copy(self.Model.q) self.ParDoc=[] self.ParText=[] self.MinText=[] self.MaxText=[] self.SlideMax=1000 self.CheckFit=[] self.slider=[] self.fitexp=0 # top sizer self.pan=wx.Panel(self, wx.ID_ANY) panel = self.pan vbox_top = wx.BoxSizer(wx.VERTICAL) #--- description desc=wx.StaticText(panel,1,"Description : \t"+self.Model.Description,size=wx.Size(400,20)) desc.SetForegroundColour('red') vbox_top.Add(desc,flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) author=wx.StaticText(panel,1,"Author : \t"+self.Model.Author,size=wx.Size(400,20)) author.SetForegroundColour('red') vbox_top.Add(author,flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) #vbox_top.Add(wx.StaticLine(panel),0,wx.EXPAND|wx.TOP|wx.BOTTOM,5) '''if self.type=="data": #compute chi_carre for datas rawdataset_name = self.parentwindow.data_dict[self.dataset_name].rawdata_ref #print rawdataset_name,len(self.parentwindow.data_dict[rawdataset_name].q),len(self.parentwindow.data_dict[rawdataset_name].i) iexp=numpy.array(self.parentwindow.data_dict[rawdataset_name].i) #print len(iexp),len(self.parentwindow.data_dict[rawdataset_name].q) val=self.Model.chi_carre(self.par,iexp) self.chicarre=wx.TextCtrl(panel,1,"Chi carre : "+str(val),size=wx.Size(400,20)) self.chicarre.SetForegroundColour('blue') vbox_top.Add(self.chicarre,flag=wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL|wx.TE_READONLY) ''' #--- Parameters sizer=wx.FlexGridSizer(rows=len(self.par)+1,cols=5,hgap=20,vgap=5) sizer.Add(wx.StaticText(panel,1,"Parameter"),flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) sizer.Add(wx.StaticText(panel,1,"Value"),flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) sizer.Add(wx.StaticText(panel,1,"Fit ?"),flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) sizer.Add(wx.StaticText(panel,1,"Min"),flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) #sizer.Add(wx.StaticText(panel,1,"Value"),flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) sizer.Add(wx.StaticText(panel,1,"Max"),wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) for i in numpy.arange(len(self.par)): #--control par doc self.ParDoc.append(wx.StaticText(panel, 5, self.Model.Doc[i]+" : ")) sizer.Add(self.ParDoc[i],flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) #--control par text self.ParText.append(wx.TextCtrl(panel,i,"",size=wx.Size(100,20), style = wx.TE_PROCESS_ENTER)) self.ParText[i].SetValue(self.Model.Format[i] % self.par[i]) sizer.Add(self.ParText[i],flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) self.ParText[i].Bind(wx.EVT_TEXT,self.textUpdate) #--control check fit self.CheckFit.append(wx.CheckBox(panel,50+i,label="fit")) self.CheckFit[i].SetValue(self.Model.istofit[i]) sizer.Add(self.CheckFit[i],flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) #--control min bounds self.MinText.append(wx.TextCtrl(panel,i,"",size=wx.Size(100,20),style = wx.TE_PROCESS_ENTER)) min=0.0*self.par[i] self.MinText[i].SetValue(self.Model.Format[i] % min) self.MinText[i].Bind(wx.EVT_TEXT,self.textMinMaxUpdate) sizer.Add(self.MinText[i],flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) #--control slider '''self.slider.append(wx.Slider(panel,i,self.SlideMax/2.,0,self.SlideMax,style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS,\ size=(200,20))) self.slider[i].SetTickFreq(100,1) self.Bind(wx.EVT_SCROLL_THUMBRELEASE, self.sliderUpdate) self.Bind(wx.EVT_SCROLL_THUMBTRACK, self.sliderMove) sizer.Add(self.slider[i],flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL)''' #--control max bounds max=2.0*self.par[i] self.MaxText.append(wx.TextCtrl(panel,i,"",size=wx.Size(100,20),style = wx.TE_PROCESS_ENTER)) self.MaxText[i].SetValue(self.Model.Format[i] % max) self.MaxText[i].Bind(wx.EVT_TEXT,self.textMinMaxUpdate) sizer.Add(self.MaxText[i],flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) box0=wx.StaticBox(panel,-1,"Model parameters :") sizerParam=wx.StaticBoxSizer(box0,wx.VERTICAL) sizerParam.Add(sizer) vbox_top.Add(sizerParam) #-------- sliders for qrange sizerSlide=wx.FlexGridSizer(rows=2,cols=3,hgap=20,vgap=5) qmin=0 self.qminIndex=qmin qmax=len(self.qbase)-1 self.qmaxIndex=qmax #qmin sizerSlide.Add(wx.StaticText(panel,1,"qmin"),flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) self.qminSlide=wx.Slider(panel, -1, qmin, qmin, qmax, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS ,\ size=(400,20)) self.qminSlide.SetTickFreq(200,1) self.qminSlide.Bind(wx.EVT_SCROLL_THUMBTRACK, self.sliderQminMove) sizerSlide.Add(self.qminSlide,flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) self.qminTxt=wx.TextCtrl(panel,-1,str(self.qbase[qmin]),size=wx.Size(100,20),style = wx.TE_READONLY) sizerSlide.Add(self.qminTxt,flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) #qmax sizerSlide.Add(wx.StaticText(panel,1,"qmax"),flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) self.qmaxSlide=wx.Slider(panel, -1, qmax, qmin, qmax, style=wx.SL_HORIZONTAL|wx.SL_AUTOTICKS ,\ size=(400,20)) self.qmaxSlide.SetTickFreq(200,1) self.qmaxSlide.Bind(wx.EVT_SCROLL_THUMBTRACK, self.sliderQmaxMove) sizerSlide.Add(self.qmaxSlide,flag=wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL) self.qmaxTxt=wx.TextCtrl(panel,-1,str(self.qbase[qmax]),size=wx.Size(100,20),style = wx.TE_READONLY) sizerSlide.Add(self.qmaxTxt,flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) #qrange boxQ=wx.StaticBox(panel,-1,"Q range :") sizerQ=wx.StaticBoxSizer(boxQ,wx.VERTICAL) sizerQ.Add(sizerSlide) vbox_top.Add(sizerQ) #-------- update fit check box #vbox_top.Add(wx.StaticLine(panel),0,wx.EXPAND|wx.TOP|wx.BOTTOM,5) self.updateFit=wx.CheckBox(panel,300,label="update model when value are changed") self.updateFit.SetValue(True) sizer.Add(self.updateFit,flag=wx.GROW|wx.ALIGN_LEFT|wx.ALIGN_CENTER_VERTICAL) vbox_top.Add(wx.StaticLine(panel),0,wx.EXPAND|wx.TOP|wx.BOTTOM,5) #-- buttons sizerButton=wx.FlexGridSizer(rows=1,cols=5,hgap=20,vgap=5) if self.type=="data": self.Fitbutton=wx.Button(panel,100,"Fit",size=wx.Size(100,30)) self.Fitbutton.Bind(wx.EVT_BUTTON, self.OnClickFitButton) sizerButton.Add(self.Fitbutton,flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) self.FitbuttonBounds=wx.Button(panel,100,"Fit with bounds",size=wx.Size(100,30)) self.FitbuttonBounds.Bind(wx.EVT_BUTTON, self.OnClickFitButtonBounds) sizerButton.Add(self.FitbuttonBounds,flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) #choice with iq iq2 iq4... choicelist=['normal','iq','iq2','iq3','iq4'] self.listText=wx.StaticText(panel,-1,"Y type :",size=wx.Size(100,20)) sizerButton.Add(self.listText,flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) self.ytype=wx.Choice(panel,-1,size=wx.Size(100,20),choices=['normal','iq','iq2','iq3','iq4']) self.ytype.Bind(wx.EVT_CHOICE,self.OnClickList) self.ytype.SetSelection(0) sizerButton.Add(self.ytype,flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) self.QuitButton=wx.Button(panel,wx.ID_OK,"CLOSE",size=wx.Size(100,30)) wx.EVT_BUTTON(self, wx.ID_OK, self.OnExitClick) self.Bind(wx.EVT_CLOSE, self.OnExitClick) sizerButton.Add(self.QuitButton,flag=wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL) vbox_top.Add(sizerButton) panel.SetSizer(vbox_top) vbox_top.Fit(self) self.parentwindow.OnModelUpdate(self)
[docs] def sliderQminMove(self,event): val=self.qminSlide.GetValue() self.qminTxt.SetValue(str(self.qbase[val])) self.qminIndex=val if self.updateFit.GetValue(): self.ModelUpdate() self.parentwindow.OnModelUpdate(self)
[docs] def sliderQmaxMove(self,event): val=self.qmaxSlide.GetValue() self.qmaxTxt.SetValue(str(self.qbase[val])) self.qmaxIndex=val if self.updateFit.GetValue(): self.ModelUpdate() self.parentwindow.OnModelUpdate(self)
'''def sliderUpdate(self,event): #no more used if slider is removed b=self.slider[event.GetId()].GetValue() c=((eval(self.MaxText[event.GetId()].GetValue())-eval(self.MinText[event.GetId()].GetValue()))/self.SlideMax)*b + eval(self.MinText[event.GetId()].GetValue()) self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % c) self.ModelUpdate() self.parentwindow.OnModelUpdate(self) def sliderMove(self,event): #no more used if slider is removed #print "on slider move" n=event.GetId() b=self.slider[event.GetId()].GetValue() #print b minbounds=float(eval(self.MinText[n].GetValue())) maxbounds=float(eval(self.MaxText[n].GetValue())) parValue=float(eval(self.ParText[n].GetValue())) range=(maxbounds-minbounds)/self.SlideMax newvalue=range*b + minbounds #print newvalue #self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % c) self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % newvalue) '''
[docs] def textMinMaxUpdate(self,event): #self.parentwindow.printTXT( "min max update") #b=self.slider[event.GetId()].GetValue() n=event.GetId() max=self.MaxText[event.GetId()].GetValue() min=self.MinText[event.GetId()].GetValue() if (not(isNumeric.isNumeric(max)))or(not(isNumeric.isNumeric(min))): return #not a number : do nothing if float(max)<=float(min): #do nothing return val=self.ParText[event.GetId()].GetValue() if (not(isNumeric.isNumeric(val))): #parameter val is not a number : set as min min=float(min) self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % min) else: if float(val)<float(min): # val is < than min, set as min self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % float(min)) if float(val)>float(max): # val is > than max, set as max self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % float(max)) #c=((eval(self.MaxText[event.GetId()].GetValue())-eval(self.MinText[event.GetId()].GetValue()))/self.SlideMax)*b + eval(self.MinText[event.GetId()].GetValue()) #self.ParText[event.GetId()].SetValue(self.Model.Format[event.GetId()] % c) if self.updateFit.GetValue(): self.ModelUpdate() self.parentwindow.OnModelUpdate(self)
[docs] def textUpdate(self,event): ''' parameter value is updated ''' n=event.GetId() #no of text box updated #print "text updated",n #test if value of text box is coherent with bounds minbounds=eval(self.MinText[n].GetValue()) maxbounds=eval(self.MaxText[n].GetValue()) if not(isNumeric.isNumeric(self.ParText[n].GetValue())): #do nothing return parValue=eval(self.ParText[n].GetValue()) if parValue<minbounds: self.MinText[event.GetId()].SetValue(str(parValue)) minbounds=parValue if parValue>maxbounds: self.MaxText[event.GetId()].SetValue(str(parValue)) maxbounds=parValue #update slider #b=self.slider[event.GetId()].GetValue() #new value of slider in percent #range=maxbounds-minbounds #newvalue=((parValue-minbounds)/range)*self.SlideMax #self.slider[event.GetId()].SetValue(newvalue) if self.updateFit.GetValue(): self.ModelUpdate() self.parentwindow.OnModelUpdate(self)
[docs] def ModelUpdate(self): ''' when a parameter is updated ''' if not(self.parentwindow.data_dict.has_key(self.dataset_name)): self.parentwindow.printTXT(self.dataset_name+" dataset removed ? ") return self.bounds=[] for i in numpy.arange(len(self.Model.Arg)): self.par[i] = float(eval(self.ParText[i].GetValue())) self.itf[i]=self.CheckFit[i].GetValue() bmin=self.MinText[i].GetValue() bmax=self.MaxText[i].GetValue() self.bounds.append((bmin,bmax)) self.Model.setIstofit(self.itf) self.Model.setArg(self.par) if (self.qminIndex!=0) or (self.qmaxIndex!=len(self.qbase)-1): self.Model.q=self.qbase[self.qminIndex:self.qmaxIndex] #print self.Model.q #print self.Model.q #compute chicarre '''if self.type=="data": #compute chi_carre for datas #print 'compute chi_carre' rawdataset_name = self.parentwindow.data_dict[self.dataset_name].rawdata_ref iexp=self.parentwindow.data_dict[rawdataset_name].i[:] val=self.Model.chi_carre(self.par,iexp) self.chicarre.Clear() self.chicarre.AppendText('Chi carre : '+str(val))'''
[docs] def UpdateAfterFit(self,result): ''' update all after a fit ''' val=numpy.array(result).copy() #print "UPDATE AFTER FIT",val for i in range(len(val)): #print i,val[i] self.ParText[i].SetValue(str(val[i]))
[docs] def DlgUpdate(self,event): ###More to do for data validation... for i in numpy.arange(len(self.Model.Arg)): self.ParText[i].SetValue(self.Model.Format[i] % self.par[i]) self.CheckFit[i].SetValue(self.itf[i])
[docs] def OnExitClick(self,event): self.ModelUpdate() self.Destroy()
[docs] def OnClickFitButton(self,event): self.ModelUpdate() self.parentwindow.OnModelFit(self) self.Model=self.parentwindow.data_dict[self.dataset_name].model self.par=self.Model.getArg() self.DlgUpdate(event)
[docs] def OnClickFitButtonBounds(self,event): self.ModelUpdate() self.parentwindow.OnModelFitBounds(self) self.Model=self.parentwindow.data_dict[self.dataset_name].model self.par=self.Model.getArg() self.DlgUpdate(event)
[docs] def OnClickList(self,event): choice=self.ytype.GetSelection() #print choice self.fitexp=choice