source: sasview/guitools/fitDialog.py @ 0954398

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 0954398 was 2e07e8f, checked in by Gervaise Alina <gervyh@…>, 16 years ago

litle change on fit

  • Property mode set to 100644
File size: 15.6 KB
RevLine 
[6cfe703]1#!/usr/bin/python
2
3# fitDialog.py
4
5import wx
[e40b651]6from PlotPanel import PlotPanel
7from plottables import Theory1D
8import math,pylab,fittings
[831149e]9import transform
10
11
[6cfe703]12class LinearFit(wx.Dialog):
[f52bea1]13    def __init__(self, parent, plottable, push_data,transform, id, title):
[90640f2]14        wx.Dialog.__init__(self, parent, id, title, size=(450, 400))
[6cfe703]15        """
[b43a009]16            Dialog window pops- up when select Linear fit on Context menu
17            Displays fitting parameters
[6cfe703]18        """
19        self.parent = parent
[f52bea1]20        self.transform = transform
[e40b651]21        #dialog panel self call function to plot the fitting function
22        self.push_data = push_data
23        #dialog self plottable
[b43a009]24       
[e40b651]25        self.plottable = plottable
[ddff053]26        # Receive transformations of x and y
[b43a009]27        self.xLabel,self.yLabel,self.Avalue,self.Bvalue,\
28        self.ErrAvalue,self.ErrBvalue,self.Chivalue= self.transform()
[e40b651]29        #Dialog interface
[6cfe703]30        panel = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)   
31        vbox  = wx.BoxSizer(wx.VERTICAL)
[106ef4d]32        sizer = wx.GridBagSizer(5,5)
33       
[6cfe703]34        vbox.Add(panel, 1, wx.EXPAND | wx.ALL)
35 
[f63f5ff]36        self.tcA = wx.TextCtrl(panel, -1,size=(120,20),style=wx.SIMPLE_BORDER)
37        self.tcErrA = wx.TextCtrl(panel, -1,size=(120,20),style=wx.SIMPLE_BORDER)
38        self.tcB = wx.TextCtrl(panel, -1,size=(120,20),style=wx.SIMPLE_BORDER)
39        self.tcErrB = wx.TextCtrl(panel, -1,size=(120,20),style=wx.SIMPLE_BORDER)
40        self.tcChi = wx.TextCtrl(panel, -1,size=(120,20),style=wx.SIMPLE_BORDER)
[83fe2cc]41        self.xminFit = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
42        self.xmaxFit = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
43        self.xminTransFit = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
44        self.xmaxTransFit = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
45        self.initXmin = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
46        self.initXmax = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
[106ef4d]47        self.btFit =wx.Button(panel,-1,'Fit',size=(120, 30))
48        self.btClose =wx.Button(panel, wx.ID_CANCEL,'Close',size=(90, 30) )
49        self.static_line_1 = wx.StaticLine(panel, -1)
[8e44d51]50       
[106ef4d]51        ix = 0
[6cfe703]52        iy = 1
[106ef4d]53        sizer.Add(wx.StaticText(panel, -1, 'y = Ax +B'),(iy, ix),(1,1),\
54                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
55        iy+=1
56        sizer.Add(wx.StaticText(panel, -1, 'Param A'),(iy, ix),\
57                 (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[6cfe703]58        ix += 1
[106ef4d]59        sizer.Add(self.tcA,(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]60        ix += 1
[106ef4d]61        sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]62        ix += 1
[106ef4d]63        sizer.Add(self.tcErrA, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]64        iy += 1
[106ef4d]65        ix = 0
66        sizer.Add(wx.StaticText(panel, -1, 'Param B'),(iy, ix),(1,1),\
67                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[6cfe703]68        ix += 1
[106ef4d]69        sizer.Add(self.tcB, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]70        ix += 1
[106ef4d]71        sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]72        ix += 1
[106ef4d]73        sizer.Add(self.tcErrB, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]74        iy += 1
[106ef4d]75        ix = 0
76        sizer.Add(wx.StaticText(panel, -1, 'Chi ^{2}'),(iy, ix),(1,1),\
77                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[6cfe703]78        ix += 1
[106ef4d]79        sizer.Add(self.tcChi, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]80        iy += 1
81        ix = 1
[106ef4d]82        sizer.Add(wx.StaticText(panel, -1, 'Xmin'),(iy, ix),(1,1),\
83                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]84        ix += 2
[106ef4d]85        sizer.Add(wx.StaticText(panel, -1, 'Xmax'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]86        iy += 1
[831149e]87        ix = 0
88        sizer.Add(wx.StaticText(panel, -1, 'Plotted Range'),(iy, ix),(1,1),\
89                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
90        ix +=1
[83fe2cc]91        sizer.Add(self.initXmin, (iy, ix),(1,1),\
[831149e]92                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
93        ix += 2
[83fe2cc]94        sizer.Add(self.initXmax, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[b43a009]95       
[ddff053]96        iy += 1
[831149e]97        ix = 0
[b43a009]98        sizer.Add(wx.StaticText(panel, -1, 'Fit Range of '+self.xLabel),(iy, ix),(1,1),\
[831149e]99                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
100        ix += 1
[83fe2cc]101        sizer.Add(self.xminTransFit, (iy, ix),(1,1),\
[106ef4d]102                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]103        ix += 2
[83fe2cc]104        sizer.Add(self.xmaxTransFit, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[90640f2]105     
[ddff053]106        iy += 1
107        ix = 0
108        sizer.Add(wx.StaticText(panel, -1, 'Fit Range of x'),(iy, ix),(1,1),\
109                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
110        ix += 1
[83fe2cc]111        sizer.Add(self.xminFit, (iy, ix),(1,1),\
[ddff053]112                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
113        ix += 2
[83fe2cc]114        sizer.Add(self.xmaxFit, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6cfe703]115        iy += 1
[106ef4d]116        ix = 1
117       
118        sizer.Add(self.btFit, (iy, ix),(1,1), wx.LEFT|wx.ADJUST_MINSIZE, 0)
[e40b651]119        self.btFit.Bind(wx.EVT_BUTTON, self._onFit)
[106ef4d]120        ix += 2
121        sizer.Add(self.btClose, (iy, ix),(1,1),\
122                  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
123       
[6cfe703]124        panel.SetSizer(sizer)
125        self.SetSizer(vbox)
126        self.Centre()
[8e44d51]127       
[e40b651]128        # Receives the type of model for the fitting
129        from LineModel import LineModel
130        self.model  = LineModel()
[1fdb81d]131         
132        #Display the fittings values
133        self.default_A = self.model.getParam('A') 
134        self.default_B = self.model.getParam('B') 
135        self.cstA = fittings.Parameter(self.model, 'A', self.default_A)
136        self.cstB  = fittings.Parameter(self.model, 'B', self.default_B)
137       
138        # Set default value of parameter in fit dialog
[90640f2]139       
[b43a009]140        if self.Avalue==None:
141            self.tcA.SetLabel(str(self.default_A))
142        else :
143            self.tcA.SetLabel(str(self.Avalue))
144        if self.Bvalue==None:
145            self.tcB.SetLabel(str(self.default_B))
146        else:
147            self.tcB.SetLabel(str(self.Bvalue))
148        if self.ErrAvalue==None:
149            self.tcErrA.SetLabel(str(0.0))
150        else:
151            self.tcErrA.SetLabel(str(self.ErrAvalue))
152        if self.ErrBvalue==None:
153            self.tcErrB.SetLabel(str(0.0))
154        else:
155            self.tcErrB.SetLabel(str(self.ErrBvalue))
156        if self.Chivalue==None:
157            self.tcChi.SetLabel(str(0.0))
158        else:
159            self.tcChi.SetLabel(str(self.Chivalue))
[831149e]160        if self.plottable.x !=[]:
161            self.mini =min(self.plottable.x)
162            self.maxi =max(self.plottable.x)
[83fe2cc]163            #store the values of View in self.x,self.y,self.dx,self.dy
164            self.x,self.y,self.dx,self.dy= self.plottable.returnValuesOfView()
[90640f2]165           
[83fe2cc]166            self.xminTransFit.SetLabel(str(min(self.x)))
167            self.xmaxTransFit.SetLabel(str(max(self.x)))
168            self.xminTransFit.Disable()
169            self.xmaxTransFit.Disable()
[90640f2]170           
[83fe2cc]171            self.initXmin.SetValue(str(self.mini))
172            self.initXmax.SetValue(str(self.maxi))
173            self.initXmin.Disable()
174            self.initXmax.Disable()
[90640f2]175           
[83fe2cc]176            self.xminFit.SetLabel(str(self.mini))
177            self.xmaxFit.SetLabel(str(self.maxi))
[5e14aee]178       
[90640f2]179     
[6cfe703]180    def _onFit(self ,event):
[f52bea1]181        """
182            Performs the fit. Receive an event when clicking on the button Fit.Computes chisqr ,
183            A and B parameters of the best linear fit y=Ax +B
184            Push a plottable to
185        """
186        tempx=[]
187        tempy=[]
[7a03e65]188        tempdy = []
[ddff053]189       
[83fe2cc]190       
191       
[1fdb81d]192       
[106ef4d]193        # Check if View contains a x array .we online fit when x exits
194        # makes transformation for y as a line to fit
[83fe2cc]195        if self.x != []: 
[ddff053]196           
197               
[83fe2cc]198            if(self.checkFitValues(self.xminFit) == True):
[f193585]199                #Check if the field of Fit Dialog contain values and use the x max and min of the user
[83fe2cc]200                xmin,xmax = self._checkVal(self.xminFit.GetValue(),self.xmaxFit.GetValue())
[ddff053]201               
[f193585]202                xminView=self.floatTransform(xmin)
203                xmaxView=self.floatTransform(xmax)
[b43a009]204                if (self.xLabel=="log10(x)"):
[83fe2cc]205                    self.xminTransFit.SetValue(str(math.log10(xminView)))
206                    self.xmaxTransFit.SetValue(str(math.log10(xmaxView)))
[416223d]207                else:
[83fe2cc]208                    self.xminTransFit.SetValue(str(xminView))
209                    self.xmaxTransFit.SetValue(str(xmaxView))
210                self.xminTransFit.Disable()
211                self.xmaxTransFit.Disable()
[f193585]212                # Store the transformed values of view x, y,dy in variables  before the fit
[b43a009]213                if  self.yLabel.lower() == "log10(y)":
214                    if (self.xLabel.lower() == "log10(x)"):
[83fe2cc]215                        for i in range(len(self.x)):
216                            if self.x[i]>= math.log10(xmin):
217                                tempy.append(math.log10(self.y[i])) 
218                                tempdy.append(transform.errToLogX(self.y[i],0,self.dy[i],0))
[f193585]219                    else:
[83fe2cc]220                        for i in range(len(self.y)):
221                            tempy.append(math.log10(self.y[i])) 
222                            tempdy.append(transform.errToLogX(self.y[i],0,self.dy[i],0))
[f193585]223                else:
[83fe2cc]224                    tempy = self.y
225                    tempdy = self.dy
[f193585]226               
[b43a009]227                if (self.xLabel.lower() == "log10(x)"):
[83fe2cc]228                    for x_i in self.x:
[34ae302]229                        if x_i >= math.log10(xmin):
[f193585]230                            tempx.append(math.log10(x_i)) 
231                else:
[83fe2cc]232                    tempx = self.x
[b43a009]233             
[f193585]234                #Find the fitting parameters
[ddff053]235               
[b43a009]236                if (self.xLabel.lower() == "log10(x)"):
[34ae302]237                    chisqr, out, cov = fittings.sansfit(self.model, [self.cstA, self.cstB],
238                    tempx, tempy,tempdy,math.log10(xmin),math.log10(xmax))
239                else:
240                    chisqr, out, cov = fittings.sansfit(self.model, 
[f193585]241                                [self.cstA, self.cstB],tempx, tempy,tempdy,xminView,xmaxView)
[b43a009]242                #print "this out",out
[f193585]243                #Check that cov and out are iterable before displaying them
244                if cov ==None:
245                    errA =0.0
246                    errB =0.0
247                else:
248                    errA= math.sqrt(cov[0][0])
249                    errB= math.sqrt(cov[1][1])
250                if out==None:
251                    cstA=0.0
252                    cstB=0.0
253                else:
254                    cstA=out[0]
255                    cstB=out[1]
256                # Reset model with the right values of A and B
257                self.model.setParam('A', float(cstA))
258                self.model.setParam('B', float(cstB))
[3aa7074]259               
[f193585]260                tempx = []
261                tempy = []
262                y_model = 0.0
263                # load tempy with the minimum transformation
264               
[b43a009]265                if self.xLabel == "log10(x)":
[f193585]266                    y_model = self.model.run(math.log10(xmin))
267                    tempx.append(xmin)
268                else:
269                    y_model = self.model.run(xminView)
270                    tempx.append(xminView)
271                   
[b43a009]272                if self.yLabel == "log10(y)":
[f193585]273                    tempy.append(math.pow(10,y_model))
274                    print "tempy",tempy
275                else:
276                    tempy.append(y_model)
277                   
278                # load tempy with the maximum transformation
[b43a009]279                if self.xLabel == "log10(x)":
[f193585]280                    y_model = self.model.run(math.log10(xmax))
281                    tempx.append(xmax)
282                else:
283                    y_model = self.model.run(xmaxView)
284                    tempx.append(xmaxView)
285                   
[b43a009]286                if self.yLabel == "log10(y)":
[f193585]287                    tempy.append(math.pow(10,y_model))
288                else: 
289                    tempy.append(y_model)
[83fe2cc]290                #Set the fit parameter display when  FitDialog is opened again
[2e07e8f]291                self.Avalue=cstB
292                self.Bvalue=cstA
[b43a009]293                self.ErrAvalue=errA
294                self.ErrBvalue=errB
295                self.Chivalue=chisqr
296                self.push_data(tempx,tempy,xminView,xmaxView,xmin,xmax,self._ongetValues())
[f193585]297               
298                # Display the fitting value on the Fit Dialog
[2e07e8f]299                self._onsetValues(cstB, cstA, errA,errB,chisqr)
[b43a009]300               
301               
[7a03e65]302           
[6cfe703]303    def _onsetValues(self,cstA,cstB,errA,errB,Chi):
[f52bea1]304         """
305              Display  the value on fit Dialog
306         """
307         self.tcA.SetValue(str(cstA))
308         self.tcB.SetValue(str(cstB))
309         self.tcErrA.SetValue(str(errA))
310         self.tcErrB.SetValue(str(errB))
311         self.tcChi.SetValue(str(Chi))
[b43a009]312       
313    def _ongetValues(self):
314         """
315              Display  the value on fit Dialog
316         """
317         return self.Avalue, self.Bvalue,self.ErrAvalue,self.ErrBvalue,self.Chivalue
[e40b651]318         
319   
[831149e]320    def _checkVal(self,usermin, usermax):
[6cfe703]321        """
[831149e]322                Ensure that fields parameter contains a min and a max value
323                within x min and x max range
[6cfe703]324        """
[831149e]325        if float(usermin) < float(usermax):
326            if float(usermin) >= float(self.mini) and float(usermin) < float(self.maxi):
[83fe2cc]327                self.xminFit.SetValue(str(usermin))
[831149e]328            else:
[83fe2cc]329                self.xminFit.SetValue(str(self.mini))
[831149e]330               
331            if float(usermax) > float(self.mini) and float(usermax) <= float(self.maxi):
[83fe2cc]332                self.xmaxFit.SetLabel(str(usermax))
[831149e]333            else:
[83fe2cc]334                self.xmaxFit.SetLabel(str(self.maxi))
[831149e]335               
[83fe2cc]336            mini =float(self.xminFit.GetValue())
337            maxi =float(self.xmaxFit.GetValue())
[831149e]338           
339            return mini, maxi
340    def floatTransform(self,x):
341        """
342             transform a float.It is use to determine the x.View min and x.View max for values
343             not in x
344        """
[b43a009]345        if ( self.xLabel=="x" ):
[831149e]346            return transform.toX(x)
347       
[b43a009]348        if ( self.xLabel=="x^(2)" ): 
[831149e]349            return transform.toX2(x)
350       
[b43a009]351        if (self.xLabel=="log10(x)" ):
[831149e]352            if x >0:
[34ae302]353                return x
[831149e]354            else:
355                raise ValueError,"cannot compute log of a negative number"
[f193585]356           
357    def checkFitValues(self,item):
358        """
359            Check the validity of input values
360        """
361        flag = True
362        value = item.GetValue()
363        # Check for possible values entered
[b43a009]364        if (self.xLabel=="log10(x)"):
[f193585]365            if (float(value) > 0):
366                item.SetBackgroundColour(wx.WHITE)
367                item.Refresh()
368            else:
369                flag = False
370                item.SetBackgroundColour("pink")
371                item.Refresh()
372     
373        return flag
[831149e]374       
[83fe2cc]375    def setFitRange(self,xmin,xmax,xminTrans,xmaxTrans):
376        """
377            Set fit parameters
378        """
379        self.xminFit.SetValue(str(xmin))
380        self.xmaxFit.SetValue(str(xmax))
381        self.xminTransFit.SetValue(str(xminTrans))
382        self.xmaxTransFit.SetValue(str(xmaxTrans))
[ddff053]383       
[106ef4d]384   
[6cfe703]385if __name__ == "__main__": 
386    app = wx.App()
387    dialog=LinearFit(None, -1, 'Fitting')
388    dialog.ShowModal()
389    app.MainLoop()
390
391
Note: See TracBrowser for help on using the repository browser.