pySAXS.guisaxs.LSModelDlg — pySAXS 77.September2012 documentation

### Navigation

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

# 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,...

    '''

    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)

        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)

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

        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)

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

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

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

        def OnExitClick(self,event):
            self.ModelUpdate()
            self.Destroy()

        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)

        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)

        def OnClickList(self,event):
            choice=self.ytype.GetSelection()
            #print choice
            self.fitexp=choice

### Navigation

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