source: sasview/guitools/fitDialog.py @ 47f695c9

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 47f695c9 was f193585, checked in by Gervaise Alina <gervyh@…>, 16 years ago

some changes

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