source: sasview/guitools/fitDialog.py @ 49c8dc5

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

more changed on fitdialog

  • Property mode set to 100644
File size: 15.5 KB
Line 
1#!/usr/bin/python
2
3# fitDialog.py
4
5import wx
6from PlotPanel import PlotPanel
7from plottables import Theory1D
8import math,pylab,fittings
9import transform
10
11
12class LinearFit(wx.Dialog):
13    def __init__(self, parent, plottable, push_data,transform, id, title):
14        wx.Dialog.__init__(self, parent, id, title, size=(450, 400))
15        """
16            Dialog window pops- up when select Linear fit on Context menu
17            Displays fitting parameters
18        """
19        self.parent = parent
20        self.transform = transform
21        #dialog panel self call function to plot the fitting function
22        self.push_data = push_data
23        #dialog self plottable
24       
25        self.plottable = plottable
26        # Receive transformations of x and y
27        self.xLabel,self.yLabel,self.Avalue,self.Bvalue,\
28        self.ErrAvalue,self.ErrBvalue,self.Chivalue= self.transform()
29        #Dialog interface
30        panel = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)   
31        vbox  = wx.BoxSizer(wx.VERTICAL)
32        sizer = wx.GridBagSizer(5,5)
33       
34        vbox.Add(panel, 1, wx.EXPAND | wx.ALL)
35 
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)
41        self.FXmin = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
42        self.FXmax = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
43        self.FXminX = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
44        self.FXmaxX = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
45        self.PXmin = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
46        self.PXmax = wx.TextCtrl(panel,-1,size=(120,20),style=wx.SIMPLE_BORDER)
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)
50       
51        ix = 0
52        iy = 1
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)
58        ix += 1
59        sizer.Add(self.tcA,(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
60        ix += 1
61        sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
62        ix += 1
63        sizer.Add(self.tcErrA, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
64        iy += 1
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)
68        ix += 1
69        sizer.Add(self.tcB, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
70        ix += 1
71        sizer.Add(wx.StaticText(panel, -1, '+/-'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
72        ix += 1
73        sizer.Add(self.tcErrB, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
74        iy += 1
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)
78        ix += 1
79        sizer.Add(self.tcChi, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
80        iy += 1
81        ix = 1
82        sizer.Add(wx.StaticText(panel, -1, 'Xmin'),(iy, ix),(1,1),\
83                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
84        ix += 2
85        sizer.Add(wx.StaticText(panel, -1, 'Xmax'),(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
86        iy += 1
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
91        sizer.Add(self.PXmin, (iy, ix),(1,1),\
92                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
93        ix += 2
94        sizer.Add(self.PXmax, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
95       
96        iy += 1
97        ix = 0
98        sizer.Add(wx.StaticText(panel, -1, 'Fit Range of '+self.xLabel),(iy, ix),(1,1),\
99                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
100        ix += 1
101        sizer.Add(self.FXmin, (iy, ix),(1,1),\
102                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
103        ix += 2
104        sizer.Add(self.FXmax, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
105     
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
111        sizer.Add(self.FXminX, (iy, ix),(1,1),\
112                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
113        ix += 2
114        sizer.Add(self.FXmaxX, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
115        iy += 1
116        ix = 1
117       
118        sizer.Add(self.btFit, (iy, ix),(1,1), wx.LEFT|wx.ADJUST_MINSIZE, 0)
119        self.btFit.Bind(wx.EVT_BUTTON, self._onFit)
120        ix += 2
121        sizer.Add(self.btClose, (iy, ix),(1,1),\
122                  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
123       
124        panel.SetSizer(sizer)
125        self.SetSizer(vbox)
126        self.Centre()
127       
128        # Receives the type of model for the fitting
129        from LineModel import LineModel
130        self.model  = LineModel()
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
139       
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))
160        if self.plottable.x !=[]:
161            self.mini =min(self.plottable.x)
162            self.maxi =max(self.plottable.x)
163            xView,yView,dxView,dyView= self.plottable.returnValuesOfView()
164           
165            self.FXmin.SetLabel(str(min(xView)))
166            self.FXmax.SetLabel(str(max(xView)))
167            self.FXmin.Disable()
168            self.FXmax.Disable()
169           
170            self.PXmin.SetValue(str(self.mini))
171            self.PXmax.SetValue(str(self.maxi))
172            self.PXmin.Disable()
173            self.PXmax.Disable()
174           
175            self.FXminX.SetLabel(str(self.mini))
176            self.FXmaxX.SetLabel(str(self.maxi))
177           
178     
179    def _onFit(self ,event):
180        """
181            Performs the fit. Receive an event when clicking on the button Fit.Computes chisqr ,
182            A and B parameters of the best linear fit y=Ax +B
183            Push a plottable to
184        """
185        tempx=[]
186        tempy=[]
187        tempdy = []
188       
189        #store the values of View in x,y, dx,dy
190        x,y,dx,dy=self.plottable.returnValuesOfView()
191       
192        # Check if View contains a x array .we online fit when x exits
193        # makes transformation for y as a line to fit
194        if x != []: 
195           
196               
197            if(self.checkFitValues(self.FXminX) == True):
198                #Check if the field of Fit Dialog contain values and use the x max and min of the user
199                xmin,xmax = self._checkVal(self.FXminX.GetValue(),self.FXmaxX.GetValue())
200               
201                xminView=self.floatTransform(xmin)
202                xmaxView=self.floatTransform(xmax)
203                if (self.xLabel=="log10(x)"):
204                    self.FXmin.SetValue(str(math.log10(xminView)))
205                    self.FXmax.SetValue(str(math.log10(xmaxView)))
206                else:
207                    self.FXmin.SetValue(str(xminView))
208                    self.FXmax.SetValue(str(xmaxView))
209                self.FXmin.Disable()
210                self.FXmax.Disable()
211                # Store the transformed values of view x, y,dy in variables  before the fit
212                if  self.yLabel.lower() == "log10(y)":
213                    if (self.xLabel.lower() == "log10(x)"):
214                        for i in range(len(x)):
215                            if x[i]>= math.log10(xmin):
216                                tempy.append(math.log10(y[i])) 
217                                tempdy.append(transform.errToLogX(y[i],0,dy[i],0))
218                    else:
219                        for i in range(len(y)):
220                            tempy.append(math.log10(y[i])) 
221                            tempdy.append(transform.errToLogX(y[i],0,dy[i],0))
222                else:
223                    tempy = y
224                    tempdy = dy
225               
226                if (self.xLabel.lower() == "log10(x)"):
227                    for x_i in x:
228                        if x_i >= math.log10(xmin):
229                            tempx.append(math.log10(x_i)) 
230                else:
231                    tempx = x
232             
233                #Find the fitting parameters
234               
235                if (self.xLabel.lower() == "log10(x)"):
236                    chisqr, out, cov = fittings.sansfit(self.model, [self.cstA, self.cstB],
237                    tempx, tempy,tempdy,math.log10(xmin),math.log10(xmax))
238                else:
239                    chisqr, out, cov = fittings.sansfit(self.model, 
240                                [self.cstA, self.cstB],tempx, tempy,tempdy,xminView,xmaxView)
241                #print "this out",out
242                #Check that cov and out are iterable before displaying them
243                if cov ==None:
244                    errA =0.0
245                    errB =0.0
246                else:
247                    errA= math.sqrt(cov[0][0])
248                    errB= math.sqrt(cov[1][1])
249                if out==None:
250                    cstA=0.0
251                    cstB=0.0
252                else:
253                    cstA=out[0]
254                    cstB=out[1]
255                # Reset model with the right values of A and B
256                self.model.setParam('A', float(cstA))
257                self.model.setParam('B', float(cstB))
258               
259                tempx = []
260                tempy = []
261                y_model = 0.0
262                # load tempy with the minimum transformation
263               
264                if self.xLabel == "log10(x)":
265                    y_model = self.model.run(math.log10(xmin))
266                    tempx.append(xmin)
267                else:
268                    y_model = self.model.run(xminView)
269                    tempx.append(xminView)
270                   
271                if self.yLabel == "log10(y)":
272                    tempy.append(math.pow(10,y_model))
273                    print "tempy",tempy
274                else:
275                    tempy.append(y_model)
276                   
277                # load tempy with the maximum transformation
278                if self.xLabel == "log10(x)":
279                    y_model = self.model.run(math.log10(xmax))
280                    tempx.append(xmax)
281                else:
282                    y_model = self.model.run(xmaxView)
283                    tempx.append(xmaxView)
284                   
285                if self.yLabel == "log10(y)":
286                    tempy.append(math.pow(10,y_model))
287                else: 
288                    tempy.append(y_model)
289                self.Avalue=cstA
290                self.Bvalue=cstB
291                self.ErrAvalue=errA
292                self.ErrBvalue=errB
293                self.Chivalue=chisqr
294                self.push_data(tempx,tempy,xminView,xmaxView,xmin,xmax,self._ongetValues())
295               
296                # Display the fitting value on the Fit Dialog
297                self._onsetValues(cstA, cstB, errA,errB,chisqr)
298               
299               
300           
301    def _onsetValues(self,cstA,cstB,errA,errB,Chi):
302         """
303              Display  the value on fit Dialog
304         """
305         self.tcA.SetValue(str(cstA))
306         self.tcB.SetValue(str(cstB))
307         self.tcErrA.SetValue(str(errA))
308         self.tcErrB.SetValue(str(errB))
309         self.tcChi.SetValue(str(Chi))
310       
311    def _ongetValues(self):
312         """
313              Display  the value on fit Dialog
314         """
315         return self.Avalue, self.Bvalue,self.ErrAvalue,self.ErrBvalue,self.Chivalue
316         
317    def _returnPlottable(self):
318        return self.file_data1
319   
320    def _checkVal(self,usermin, usermax):
321        """
322                Ensure that fields parameter contains a min and a max value
323                within x min and x max range
324        """
325        if float(usermin) < float(usermax):
326            if float(usermin) >= float(self.mini) and float(usermin) < float(self.maxi):
327                self.FXminX.SetValue(str(usermin))
328            else:
329                self.FXminX.SetValue(str(self.mini))
330               
331            if float(usermax) > float(self.mini) and float(usermax) <= float(self.maxi):
332                self.FXmaxX.SetLabel(str(usermax))
333            else:
334                self.FXmaxX.SetLabel(str(self.maxi))
335               
336            mini =float(self.FXminX.GetValue())
337            maxi =float(self.FXmaxX.GetValue())
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        """
345        if ( self.xLabel=="x" ):
346            return transform.toX(x)
347       
348        if ( self.xLabel=="x^(2)" ): 
349            return transform.toX2(x)
350       
351        if (self.xLabel=="log10(x)" ):
352            if x >0:
353                return x
354            else:
355                raise ValueError,"cannot compute log of a negative number"
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
364        if (self.xLabel=="log10(x)"):
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
374       
375    def setFitRange(self,xmin,xmax,Reelxmin,Reelxmax):
376        if (self.xLabel=="log10(x)"):
377            self.FXmin.SetValue(str(math.log10(xmin)))
378            self.FXmax.SetValue(str(math.log10(xmax)))
379        else:
380            self.FXmin.SetValue(str(xmin))
381            self.FXmax.SetValue(str(xmax))
382        self.FXminX.SetValue(str(Reelxmin))
383        self.FXmaxX.SetValue(str(Reelxmax))
384       
385   
386if __name__ == "__main__": 
387    app = wx.App()
388    dialog=LinearFit(None, -1, 'Fitting')
389    dialog.ShowModal()
390    app.MainLoop()
391
392
Note: See TracBrowser for help on using the repository browser.