source: sasview/guitools/fitDialog.py @ 831149e

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

working better .Since have to think about the zoom

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