source: sasview/sansview/perspectives/fitting/fitpage.py @ 847091f

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 847091f was 847091f, checked in by Gervaise Alina <gervyh@…>, 15 years ago

disabling smearing for data with no smearing info

  • Property mode set to 100644
File size: 46.7 KB
Line 
1
2
3import sys
4import wx
5import wx.lib.newevent
6import numpy
7import copy
8import math
9from sans.models.dispersion_models import ArrayDispersion, GaussianDispersion
10
11from sans.guicomm.events import StatusEvent   
12from sans.guiframe.utils import format_number,check_float
13
14## event to post model to fit to fitting plugins
15(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
16
17## event to know the selected fit engine
18(FitterTypeEvent, EVT_FITTER_TYPE)   = wx.lib.newevent.NewEvent()
19_BOX_WIDTH = 80
20
21import basepage
22from basepage import BasicPage
23from basepage import PageInfoEvent
24from DataLoader.qsmearing import smear_selection
25
26class FitPage(BasicPage):
27    """
28        FitPanel class contains fields allowing to display results when
29        fitting  a model and one data
30        @note: For Fit to be performed the user should check at least one parameter
31        on fit Panel window.
32 
33    """
34    def __init__(self,parent, page_info):
35        BasicPage.__init__(self, parent, page_info)
36        """
37            Initialization of the Panel
38        """
39        ## fit page does not content npts txtcrtl
40        self.npts=None
41        ## if no dispersity parameters is avaible
42        self.text_disp_1=None
43        ## default fitengine type
44        self.engine_type = None
45        ## draw sizer
46        self._fill_datainfo_sizer()
47        self._fill_model_sizer( self.sizer1)
48        self._fill_range_sizer() 
49        self._on_select_model(event=None)
50        if self.data !=None:
51            self.smearer = smear_selection( self.data )
52            if self.smearer ==None:
53                self.enable_smearer.Disable()
54                self.disable_smearer.Disable()
55               
56        ## to update the panel according to the fit engine type selected
57        self.Bind(EVT_FITTER_TYPE,self._on_engine_change)
58   
59   
60    def _on_engine_change(self, event):
61        """
62            get an event containing the current name of the fit engine type
63            @param event: FitterTypeEvent containing  the name of the current engine
64        """
65        self.engine_type = event.type
66         
67        if len(self.parameters)==0:
68            return
69        for item in self.parameters:
70            if event.type =="scipy":
71                item[5].SetValue("")
72                item[5].Hide()
73                item[6].SetValue("")
74                item[6].Hide()
75                self.text2_min.Hide()
76                self.text2_max.Hide()
77            else:
78                item[5].Show(True)
79                item[6].Show(True)
80                self.text2_min.Show(True)
81                self.text2_max.Show(True)
82               
83        self.sizer3.Layout()
84        self.SetScrollbars(20,20,200,100)
85       
86   
87    def _fill_range_sizer(self):
88        """
89            Fill the sizer containing the plotting range
90            add  access to npts
91        """
92        sizer_fit = wx.GridSizer(1, 1,0, 0)
93   
94        self.btFit = wx.Button(self,wx.NewId(),'Fit')
95        self.btFit.Bind(wx.EVT_BUTTON, self._onFit,id= self.btFit.GetId())
96        self.btFit.SetToolTipString("Perform fit.")
97     
98       
99        sizer_fit.Add((5,5),1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)       
100        sizer_fit.Add(self.btFit,0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) 
101       
102        sizer_smearer = wx.BoxSizer(wx.HORIZONTAL)
103        #Filling the sizer containing instruments smearing info.
104        self.disable_smearer = wx.RadioButton(self, -1, 'No', style=wx.RB_GROUP)
105        self.enable_smearer = wx.RadioButton(self, -1, 'Yes')
106        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId())
107        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId())
108       
109        sizer_smearer.Add(wx.StaticText(self,-1,'Instrument Smearing? '))
110        sizer_smearer.Add((10, 10))
111        sizer_smearer.Add( self.enable_smearer )
112        sizer_smearer.Add((10,10))
113        sizer_smearer.Add( self.disable_smearer )
114       
115        #Display Chi^2/dof
116        sizer_smearer.Add((68,10))
117        box_description= wx.StaticBox(self, -1,'Chi2/dof')
118        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
119        boxsizer1.SetMinSize((60,-1))
120        self.tcChi    =  wx.StaticText(self, -1, "-", style=wx.ALIGN_LEFT)       
121        boxsizer1.Add( self.tcChi )   
122        sizer_smearer.Add( boxsizer1 )
123               
124        #Set sizer for Fitting section
125        self._set_range_sizer( title="Fitting",
126                               object1=sizer_smearer, object= sizer_fit)
127 
128       
129    def _fill_datainfo_sizer(self):
130        """
131            fill sizer 0 with data info
132        """
133        self.sizer0.Clear(True)
134        ## no loaded data , don't fill the sizer
135        if self.data== None:
136            self.sizer0.Layout()
137            return
138       
139        box_description= wx.StaticBox(self, -1, 'Data')
140        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
141        #----------------------------------------------------------
142        sizer_data = wx.GridSizer(3, 3,5, 5)
143        #Filling the sizer containing data related fields
144        DataSource  =wx.StaticText(self, -1,str(self.data.name))
145
146        sizer_data.Add(wx.StaticText(self, -1, 'Source Name : '))
147        sizer_data.Add(DataSource )
148        sizer_data.Add( (0,5) )
149       
150        #---------sizer 2 draw--------------------------------
151        #set maximum range for x in linear scale
152        if not hasattr(self.data,"data"): #Display only for 1D data fit
153            # Minimum value of data   
154            #data_min = str(format_number(numpy.min(self.data.x)))
155            data_min = str((numpy.min(self.data.x)))
156            # Maximum value of data 
157#            data_max = str(format_number(numpy.max(self.data.x)))
158            data_max = str((numpy.max(self.data.x)))
159            text4_3 = wx.StaticText(self, -1, 'Total Q Range (1/A)',
160                                     style=wx.ALIGN_LEFT)
161            sizer_data.Add( text4_3 )
162            sizer_data.Add(wx.StaticText(self, -1, "Min : %s"%data_min))
163           
164            sizer_data.Add(wx.StaticText(self, -1, "Max : %s"%data_max))
165           
166        else:
167            radius_min= 0
168            x= numpy.max(self.data.xmin, self.data.xmax)
169            y= numpy.max(self.data.ymin, self.data.ymax)
170            radius_max = math.sqrt(x*x + y*y)
171           
172            #For qmin and qmax, do not use format_number.(If do, qmin and max could be different from what is in the data.)
173            # Minimum value of data   
174            #data_min = str(format_number(radius_min))
175            data_min = str((radius_min))
176            # Maximum value of data 
177            #data_max = str(format_number(radius_max))
178            data_max = str((radius_max))
179            text4_3 = wx.StaticText(self, -1, "Total Q Range (1/A)",
180                                     style=wx.ALIGN_LEFT)
181            sizer_data.Add( text4_3 )
182            sizer_data.Add(wx.StaticText(self, -1, "Min : %s"%data_min))
183            sizer_data.Add(wx.StaticText(self, -1, "Max : %s"%data_max))
184           
185        boxsizer1.Add(sizer_data)
186        #------------------------------------------------------------
187        self.sizer0.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
188        self.sizer0.Layout()
189       
190        self.qmin_x= data_min
191        self.qmax_x= data_max
192       
193       
194    def _fill_model_sizer(self, sizer):
195        """
196            fill sizer containing model info
197        """
198       
199        ## class base method  to add view 2d button   
200        self._set_model_sizer(sizer=sizer, title="Model",object=None )   
201       
202   
203    def _set_sizer_gaussian(self):
204        """
205            draw sizer with gaussian dispersity parameters
206        """
207        self.fittable_param=[]
208        self.fixed_param=[]
209        self.orientation_params_disp=[]
210       
211        self.sizer4_4.Clear(True)
212       
213        if self.model==None:
214            ##no model is selected
215            return
216        if not self.enable_disp.GetValue():
217            ## the user didn't select dispersity display
218            return 
219       
220        self._reset_dispersity()
221        # Create the dispersion objects
222        for item in self.model.dispersion.keys():
223            disp_model =  GaussianDispersion()
224            self._disp_obj_dict[item] = disp_model
225            self.model.set_dispersion(item, disp_model)
226
227        ix=0
228        iy=1
229        disp = wx.StaticText(self, -1, 'Names')
230        self.sizer4_4.Add(disp,( iy, ix),(1,1), 
231                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
232        ix += 1 
233        values = wx.StaticText(self, -1, 'Values')
234        self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
235        ix +=2 
236        self.text_disp_1 = wx.StaticText(self, -1, 'Errors')
237        self.sizer4_4.Add( self.text_disp_1,(iy, ix),(1,1),\
238                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
239        self.text_disp_1.Hide()
240        ix += 1 
241        npts = wx.StaticText(self, -1, 'Npts')
242        self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
243        ix += 1 
244        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
245        self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
246       
247        for item in self.model.dispersion.keys():
248            if not item in self.model.orientation_params:
249                self.disp_cb_dict[item]= None
250                name1=item+".width"
251                name2=item+".npts"
252                name3=item+".nsigmas"
253                iy += 1
254                for p in self.model.dispersion[item].keys(): 
255       
256                    if p=="width":
257                        ix = 0
258                        cb = wx.CheckBox(self, -1, name1, (10, 10))
259                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
260                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
261                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
262                        ix = 1
263                        value= self.model.getParam(name1)
264                        ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
265                                            style=wx.TE_PROCESS_ENTER)
266                        ctl1.SetValue(str (format_number(value)))
267                        ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
268                        ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
269                        ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
270                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
271                        ## text to show error sign
272                        ix = 2
273                        text2=wx.StaticText(self, -1, '+/-')
274                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
275                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
276                        text2.Hide() 
277                        ## txtcrtl to add error from fit
278                        ix = 3
279                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
280                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
281                        ctl2.Hide()
282                        self.fittable_param.append([cb,name1,ctl1,text2,
283                                                    ctl2, None, None,None])
284                    elif p=="npts":
285                            ix = 4
286                            value= self.model.getParam(name2)
287                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
288                                                style=wx.TE_PROCESS_ENTER)
289                           
290                            Tctl.SetValue(str (format_number(value)))
291                            Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
292                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
293                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
294                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
295                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
296                            self.fixed_param.append([None,name2, Tctl,None,None,
297                                                      None, None,None])
298                    elif p=="nsigmas":
299                            ix = 5
300                            value= self.model.getParam(name3)
301                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
302                                                style=wx.TE_PROCESS_ENTER)
303                            Tctl.SetValue(str (format_number(value)))
304                            Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
305                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
306                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
307                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
308                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
309                            ix +=1
310                            self.sizer4_4.Add((20,20), (iy,ix),(1,1),
311                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
312                           
313                            self.fixed_param.append([None,name3, Tctl
314                                                     ,None,None, None, None,None])
315        ix =0
316        iy +=1 
317        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
318        for item in self.model.dispersion.keys():
319            if  item in self.model.orientation_params:
320                self.disp_cb_dict[item]= None
321                name1=item+".width"
322                name2=item+".npts"
323                name3=item+".nsigmas"
324                iy += 1
325                for p in self.model.dispersion[item].keys(): 
326       
327                    if p=="width":
328                        ix = 0
329                        cb = wx.CheckBox(self, -1, name1, (10, 10))
330                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
331                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
332                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
333                        if self.data.__class__.__name__ =="Data2D":
334                            cb.Enable()
335                        else:
336                            cb.Disable()
337                        ix = 1
338                        value= self.model.getParam(name1)
339                        ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
340                                            style=wx.TE_PROCESS_ENTER)
341                        ctl1.SetValue(str (format_number(value)))
342                        if self.data.__class__.__name__ =="Data2D":
343                            ctl1.Enable()
344                        else:
345                            ctl1.Disable()
346                        ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
347                        ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
348                        ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
349                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
350                        ## text to show error sign
351                        ix = 2
352                        text2=wx.StaticText(self, -1, '+/-')
353                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
354                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
355                        text2.Hide() 
356                        ## txtcrtl to add error from fit
357                        ix = 3
358                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
359                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
360                        ctl2.Hide()
361                        if self.data.__class__.__name__ =="Data2D":
362                            ctl2.Enable()
363                        else:
364                            ctl2.Disable()
365                        self.fittable_param.append([cb,name1,ctl1,text2,
366                                                    ctl2, None, None,None])
367                        self.orientation_params_disp.append([cb,name1,ctl1,text2,
368                                                    ctl2, None, None,None])
369                    elif p=="npts":
370                            ix = 4
371                            value= self.model.getParam(name2)
372                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
373                                                style=wx.TE_PROCESS_ENTER)
374                           
375                            Tctl.SetValue(str (format_number(value)))
376                            if self.data.__class__.__name__ =="Data2D":
377                                Tctl.Enable()
378                            else:
379                                Tctl.Disable()
380                            Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
381                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
382                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
383                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
384                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
385                            self.fixed_param.append([None,name2, Tctl,None,None,
386                                                      None, None,None])
387                            self.orientation_params_disp.append([None,name2, Tctl,None,None,
388                                                      None, None,None])
389                    elif p=="nsigmas":
390                            ix = 5
391                            value= self.model.getParam(name3)
392                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
393                                                style=wx.TE_PROCESS_ENTER)
394                            Tctl.SetValue(str (format_number(value)))
395                            if self.data.__class__.__name__ =="Data2D":
396                                Tctl.Enable()
397                            else:
398                                Tctl.Disable()
399                            Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
400                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
401                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
402                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
403                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
404                            ix +=1
405                            self.sizer4_4.Add((20,20), (iy,ix),(1,1),
406                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
407                            self.fixed_param.append([None,name3, Tctl
408                                                     ,None,None, None, None,None])   
409                            self.orientation_params_disp.append([None,name3, Tctl
410                                                     ,None,None, None, None,None]) 
411                                 
412        wx.PostEvent(self.parent, StatusEvent(status=\
413                        " Selected Distribution: Gaussian"))   
414        ix =0
415        iy +=1 
416        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
417        self.sizer4_4.Layout()
418        self.sizer4.Layout()
419        self.SetScrollbars(20,20,200,100)
420     
421       
422    def _onFit(self, event):     
423        """
424            Allow to fit
425        """
426        #self.btFit.SetLabel("Stop")
427        from sans.guiframe.utils import check_value
428        flag = check_value( self.qmin, self.qmax) 
429       
430        if not flag:
431            msg= "Fitting range invalid"
432            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
433            return 
434       
435        if len(self.param_toFit) <= 0:
436            msg= "Select at least one parameter to fit"
437            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
438            return 
439       
440        self.qmin_x=float(self.qmin.GetValue())
441        self.qmax_x =float( self.qmax.GetValue())
442        self.manager._reset_schedule_problem( value=0)
443        self.manager.schedule_for_fit( value=1,page=self,fitproblem =None) 
444        self.manager.set_fit_range(page= self,qmin= self.qmin_x, qmax= self.qmax_x)
445        #single fit
446        self.manager.onFit()
447           
448        self.sizer5.Layout()
449        self.SetScrollbars(20,20,55,40)
450       
451       
452    def _on_select_model(self, event): 
453        """
454             call back for model selection
455        """   
456        self._on_select_model_helper() 
457        self.set_model_param_sizer(self.model)
458        try:
459            temp_smear= None
460            if self.enable_smearer.GetValue():
461                temp_smear= self.smearer
462            self.compute_chisqr(temp_smear)
463        except:
464            ## error occured on chisqr computation
465            pass
466        self.enable_disp.SetValue(False)
467        self.disable_disp.SetValue(True)
468        self._set_dipers_Param(event=None)
469       
470        evt = ModelEventbox(model=self.model)
471        wx.PostEvent(self.event_owner, evt)   
472       
473   
474    def _onparamRangeEnter(self, event):
475        """
476            Check validity of value enter in the parameters range field
477        """
478        tcrtl= event.GetEventObject()
479        if tcrtl.GetValue().lstrip().rstrip()!="":
480            try:
481                value = float(tcrtl.GetValue())
482                tcrtl.SetBackgroundColour(wx.WHITE)
483                tcrtl.Refresh()
484            except:
485                tcrtl.SetBackgroundColour("pink")
486                tcrtl.Refresh()
487        else:
488           tcrtl.SetBackgroundColour(wx.WHITE)
489           tcrtl.Refresh() 
490        self._onparamEnter_helper()   
491       
492    def _onparamEnter(self,event):
493        """
494            when enter value on panel redraw model according to changed
495        """
496        tcrtl= event.GetEventObject()
497        if check_float(tcrtl):
498            self._onparamEnter_helper()
499            self.compute_chisqr()
500        else:
501            msg= "Cannot Plot :Must enter a number!!!  "
502            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
503            return 
504       
505    def reset_page(self, state):
506        """
507            reset the state
508        """
509        self.reset_page_helper(state)
510        evt = ModelEventbox(model=self.model)
511        wx.PostEvent(self.event_owner, evt)   
512           
513           
514    def get_range(self):
515        """
516            return the fitting range
517        """
518        return float(self.qmin_x) , float(self.qmax_x)
519       
520    def get_param_list(self):
521        """
522            @return self.param_toFit: list containing  references to TextCtrl
523            checked.Theses TextCtrl will allow reference to parameters to fit.
524            @raise: if return an empty list of parameter fit will nnote work
525            properly so raise ValueError,"missing parameter to fit"
526        """
527        if self.param_toFit !=[]:
528            return self.param_toFit
529        else:
530            raise ValueError,"missing parameter to fit"   
531     
532    def onsetValues(self,chisqr, out,cov):
533        """
534            Build the panel from the fit result
535            @param chisqr:Value of the goodness of fit metric
536            @param out:list of parameter with the best value found during fitting
537            @param cov:Covariance matrix
538       
539        """
540        self.tcChi.SetLabel(format_number(chisqr))
541        params = {}
542        is_modified = False
543        has_error = False
544        self.text2_3.Hide()
545        if self.text_disp_1 !=None:
546            self.text_disp_1.Hide()
547        #set the panel when fit result are float not list
548        if out.__class__==numpy.float64:
549            self.param_toFit[0][2].SetValue(format_number(out))
550            self.param_toFit[0][2].Refresh()
551           
552            self.param_toFit[0][4].Clear()
553            self.param_toFit[0][4].Hide()
554            if cov !=None :
555                self.text2_3.Show(True)
556                if self.text_disp_1 !=None:
557                    self.text_disp_1.Show(True)
558                if cov[0]==None: 
559                    self.param_toFit[0][3].Hide()
560                    self.param_toFit[0][4].Clear()
561                    self.param_toFit[0][4].Hide()
562                    self.param_toFit[0][4].Refresh()
563                else:
564                    self.param_toFit[0][3].Show(True)
565                    self.param_toFit[0][4].Clear()
566                    self.param_toFit[0][4].SetValue(format_number(cov[0]))
567                    self.param_toFit[0][4].Show(True)
568                    self.param_toFit[0][4].Refresh()
569        else:
570            i=0
571            j=0
572            #Set the panel when fit result are list
573            for item in self.param_toFit:
574                ## reset error value to initial state
575                item[4].Clear()
576                item[4].Hide()
577                item[4].Refresh()
578                if( out != None ) and len(out)<=len(self.param_toFit)and i < len(out):
579                    item[2].SetValue(format_number(self.model.getParam(item[1])))
580                    item[2].Refresh()
581                if(cov !=None)and len(cov)<=len(self.param_toFit)and i < len(cov):
582                    self.text2_3.Show(True) 
583                    if self.text_disp_1!=None:
584                        self.text_disp_1.Show(True)
585                    item[3].Show(True)
586                    item[4].Clear()
587                    for j in range(len(out)):
588                        if out[j]==self.model.getParam(item[1]):
589                            break
590                    ## unable to compare cov[j]==numpy.nan so switch to None
591                    if cov[j]==None:
592                        item[3].Hide()
593                        item[4].Refresh()
594                        item[4].Clear()
595                        item[4].Hide()
596                    else:
597                        item[4].SetValue(format_number(cov[j]))
598                        item[4].Refresh()
599                        item[4].Show(True)   
600                i+=1
601       
602        self.sizer3.Layout()
603        self.sizer4.Layout()
604        self.SetScrollbars(20,20,200,100)
605       
606       
607    def onSmear(self, event):
608        """
609            Create a smear object that will change the way residuals
610            are compute when fitting
611        """
612       
613        if self.enable_smearer.GetValue():
614            msg=""
615            temp_smearer= self.smearer
616            if hasattr(self.data,"dxl"):
617                msg= ": Resolution smearing parameters"
618            if hasattr(self.data,"dxw"):
619                msg= ": Slit smearing parameters"
620            if self.smearer ==None:
621                wx.PostEvent(self.manager.parent, StatusEvent(status=\
622                            "Data contains no smearing information"))
623            else:
624                wx.PostEvent(self.manager.parent, StatusEvent(status=\
625                            "Data contains smearing information %s"%msg))
626        else:
627            temp_smearer = None
628        ## set smearing value whether or not the data contain the smearing info
629        self.manager.set_smearer(temp_smearer, qmin= float(self.qmin_x),
630                                      qmax= float(self.qmax_x)) 
631        ##Calculate chi2
632        self.compute_chisqr(smearer= temp_smearer) 
633        ## save the state enable smearing
634        self.save_current_state()
635         
636   
637       
638 
639    def compute_chisqr2D(self):
640        """
641            compute chi square given a model and data 2D and set the value
642            to the tcChi txtcrl
643        """
644        from sans.guiframe.utils import check_value
645        flag = check_value( self.qmin, self.qmax)
646        err_image = self.data.err_data
647        if err_image==[] or err_image==None:
648            err_image= numpy.zeros(len(self.data.x_bins),len(self.data.y_bins))
649                       
650        err_image[err_image==0]=1
651        res=[]
652        if flag== True:
653            try:
654                self.qmin_x = float(self.qmin.GetValue())
655                self.qmax_x = float(self.qmax.GetValue())
656                for i in range(len(self.data.x_bins)):
657                    for j in range(len(self.data.y_bins)):
658                        #Check the range containing data between self.qmin_x and self.qmax_x
659                        value =  math.pow(self.data.x_bins[i],2)+ math.pow(self.data.y_bins[j],2)
660                        if value >= math.pow(self.qmin_x,2) and value <= math.pow(self.qmax_x,2):
661                           
662                            temp = [self.data.x_bins[i],self.data.y_bins[j]]
663                            error= err_image[j][i]
664                            chisqrji = (self.data.data[j][i]- self.model.runXY(temp ))/error
665                            #Vector containing residuals
666                            res.append( math.pow(chisqrji,2) )
667
668                # compute sum of residual
669                sum=0
670                for item in res:
671                    if numpy.isfinite(item):
672                        sum +=item
673                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
674            except:
675                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
676                            "Chisqr cannot be compute: %s"% sys.exc_value))
677                return
678   
679       
680    def compute_chisqr(self , smearer=None):
681        """
682            compute chi square given a model and data 1D and set the value
683            to the tcChi txtcrl
684        """
685        from sans.guiframe.utils import check_value
686        flag = check_value( self.qmin, self.qmax)
687       
688        if flag== True:
689            try:
690                if hasattr(self.data,"data"):
691                    self.compute_chisqr2D()
692                    return
693                else:
694                    self.qmin_x = float(self.qmin.GetValue())
695                    self.qmax_x = float(self.qmax.GetValue())
696                    # return residuals within self.qmin_x and self.qmax_x
697                    x,y = [numpy.asarray(v) for v in (self.data.x,self.data.y)]
698                   
699                    if self.data.dy==None:
700                        dy= numpy.zeros(len(y))
701                    else:
702                        dy= numpy.asarray(self.data.dy)
703                    dy[dy==0]=1
704                   
705                    if self.qmin_x==None and self.qmax_x==None: 
706                        fx =numpy.asarray([self.model.run(v) for v in x])
707                        if smearer!=None:
708                            fx= smearer(fx)
709                        temp=(y - fx)/dy
710                        res= temp*temp
711                    else:
712                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
713                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
714                        if smearer!=None:
715                            fx= smearer(fx)
716                        temp=(y[idx] - fx)/dy[idx]
717                        res= temp*temp
718                    #sum of residuals
719                    sum=0
720                    for item in res:
721                        if numpy.isfinite(item):
722                            sum +=item
723                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
724            except:
725                raise
726                #wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
727                #            "Chisqr cannot be compute: %s"% sys.exc_value))
728                #return
729           
730   
731    def select_all_param(self,event): 
732        """
733             set to true or false all checkBox given the main checkbox value cb1
734        """           
735
736        self.param_toFit=[]
737       
738        if  self.parameters !=[]:
739            if  self.cb1.GetValue():
740                for item in self.parameters:
741                    item[0].SetValue(True)
742                    self.param_toFit.append(item )
743                if len(self.fittable_param)>0:
744                    for item in self.fittable_param:
745                        item[0].SetValue(True)
746                        self.param_toFit.append(item )
747            else:
748                for item in self.parameters:
749                    item[0].SetValue(False)
750                for item in self.fittable_param:
751                    item[0].SetValue(False)
752                self.param_toFit=[]
753               
754        self.save_current_state() 
755       
756               
757               
758    def select_param(self,event):
759        """
760            Select TextCtrl  checked for fitting purpose and stores them
761            in  self.param_toFit=[] list
762        """
763        self.param_toFit=[]
764        for item in self.parameters:
765            #Select parameters to fit for list of primary parameters
766            if item[0].GetValue():
767                if not (item in self.param_toFit):
768                    self.param_toFit.append(item ) 
769            else:
770                #remove parameters from the fitting list
771                if item in self.param_toFit:
772                    self.param_toFit.remove(item)
773        #Select parameters to fit for list of fittable parameters with dispersion         
774        for item in self.fittable_param:
775            if item[0].GetValue():
776                if not (item in self.param_toFit):
777                    self.param_toFit.append(item) 
778            else:
779                #remove parameters from the fitting list
780                if item in self.param_toFit:
781                    self.param_toFit.remove(item)           
782        #Set the value of checkbox that selected every checkbox or not           
783        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
784            self.cb1.SetValue(True)
785        else:
786            self.cb1.SetValue(False)
787        ## save current state of the page
788        self.save_current_state()
789       
790   
791       
792    def set_model_param_sizer(self, model):
793        """
794            Build the panel from the model content
795            @param model: the model selected in combo box for fitting purpose
796        """
797        self.sizer3.Clear(True)
798        self.parameters = []
799        self.param_toFit=[]
800        self.fittable_param=[]
801        self.fixed_param=[]
802        self.orientation_params=[]
803        self.orientation_params_disp=[]
804       
805        if model ==None:
806            self.sizer3.Layout()
807            self.SetScrollbars(20,20,200,100)
808            return
809        ## the panel is drawn using the current value of the fit engine
810        if self.engine_type==None and self.manager !=None:
811            self.engine_type= self.manager._return_engine_type()
812           
813        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
814        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
815        sizer = wx.GridBagSizer(5,5)
816        ## save the current model
817        self.model = model
818           
819        keys = self.model.getParamList()
820        #list of dispersion paramaters
821        self.disp_list=self.model.getDispParamList()
822       
823        keys.sort()
824   
825        iy = 1
826        ix = 0
827        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
828        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
829        self.cb1.SetValue(False)
830       
831        sizer.Add(self.cb1,(iy, ix),(1,1),\
832                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
833        ix += 1
834        self.text2_4 = wx.StaticText(self, -1, '[Units]')
835        sizer.Add(self.text2_4,(iy, ix),(1,1),\
836                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
837        #self.text2_4.Hide()
838        ix +=1
839        self.text2_2 = wx.StaticText(self, -1, 'Values')
840        sizer.Add(self.text2_2,(iy, ix),(1,1),\
841                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
842        ix +=2 
843        self.text2_3 = wx.StaticText(self, -1, 'Errors')
844        sizer.Add(self.text2_3,(iy, ix),(1,1),\
845                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
846        self.text2_3.Hide()
847        ix +=1 
848        self.text2_min = wx.StaticText(self, -1, 'Min')
849        sizer.Add(self.text2_min,(iy, ix),(1,1),\
850                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
851        self.text2_min.Hide()
852        ix +=1 
853        self.text2_max = wx.StaticText(self, -1, 'Max')
854        sizer.Add(self.text2_max,(iy, ix),(1,1),\
855                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
856        self.text2_max.Hide()
857        if self.engine_type=="park":
858            self.text2_max.Show(True)
859            self.text2_min.Show(True)
860
861        for item in keys:
862            if not item in self.disp_list and not item in self.model.orientation_params:
863                iy += 1
864                ix = 0
865                ## add parameters name with checkbox for selecting to fit
866                cb = wx.CheckBox(self, -1, item )
867                cb.SetValue(False)
868                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
869                sizer.Add( cb,( iy, ix),(1,1),
870                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
871                ix +=1
872                # Units
873                try:
874                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
875                except:
876                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
877                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
878               
879                ## add parameter value
880                ix += 1
881                value= self.model.getParam(item)
882                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
883                                    style=wx.TE_PROCESS_ENTER)
884               
885                ctl1.SetValue(format_number(value))
886                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
887                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
888                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
889                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
890                ## text to show error sign
891                ix += 1
892                text2=wx.StaticText(self, -1, '+/-')
893                sizer.Add(text2,(iy, ix),(1,1),\
894                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
895                text2.Hide() 
896                ## txtcrtl to add error from fit
897                ix += 1
898                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
899                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
900                ctl2.Hide()
901               
902                param_min, param_max= self.model.details[item][1:]
903                ix += 1
904                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
905                if param_min ==None:
906                    ctl3.SetValue("")
907                else:
908                    ctl3.SetValue(str(param_min))
909                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
910                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
911                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
912                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
913                ctl3.Hide()
914       
915                ix += 1
916                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
917                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
918                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
919                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
920                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
921                if param_max==None:
922                    ctl4.SetValue("")
923                else:
924                    ctl4.SetValue(str(param_max))
925                ctl4.Hide()
926               
927                if self.engine_type=="park":
928                    ctl3.Show(True)
929                    ctl4.Show(True)
930                   
931                ##[cb state, name, value, "+/-", error of fit, min, max , units]
932                self.parameters.append([cb,item, ctl1,
933                                        text2,ctl2, ctl3, ctl4,None])
934             
935        iy+=1
936        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
937        for item in self.model.orientation_params:
938            if not item in self.disp_list :
939                iy += 1
940                ix = 0
941                ## add parameters name with checkbox for selecting to fit
942                cb = wx.CheckBox(self, -1, item )
943                cb.SetValue(False)
944                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
945                if self.data.__class__.__name__ =="Data2D":
946                    cb.Enable()
947                else:
948                    cb.Disable()
949                sizer.Add( cb,( iy, ix),(1,1),
950                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
951                ix +=1
952                # Units
953                try:
954                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
955                except:
956                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
957                if self.data.__class__.__name__ =="Data2D":
958                    units.Enable()
959                else:
960                    units.Disable()
961                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
962
963                ## add parameter value
964                ix += 1
965                value= self.model.getParam(item)
966                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
967                                    style=wx.TE_PROCESS_ENTER)
968               
969                ctl1.SetValue(format_number(value))
970                if self.data.__class__.__name__ =="Data2D":
971                    ctl1.Enable()
972                else:
973                    ctl1.Disable()
974                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
975                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
976                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
977                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
978                ## text to show error sign
979                ix += 1
980                text2=wx.StaticText(self, -1, '+/-')
981                sizer.Add(text2,(iy, ix),(1,1),\
982                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
983                text2.Hide() 
984                ## txtcrtl to add error from fit
985                ix += 1
986                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
987                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
988                ctl2.Hide()
989                if self.data.__class__.__name__ =="Data2D":
990                    ctl1.Enable()
991                else:
992                    ctl1.Disable()
993                param_min, param_max= self.model.details[item][1:]
994                ix += 1
995                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
996                if param_min ==None:
997                    ctl3.SetValue("")
998                else:
999                    ctl3.SetValue(str(param_min))
1000                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1001                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
1002                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
1003                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1004                ctl3.Hide()
1005                if self.data.__class__.__name__ =="Data2D":
1006                    ctl3.Enable()
1007                else:
1008                    ctl3.Disable()
1009                ix += 1
1010                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
1011                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1012                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
1013                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
1014                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1015                ctl4.SetValue(str(param_max))
1016                ctl4.Hide()
1017                if self.data.__class__.__name__ =="Data2D":
1018                    ctl4.Enable()
1019                else:
1020                    ctl4.Disable()
1021                if self.engine_type=="park":
1022                    ctl3.Show(True)
1023                    ctl4.Show(True)
1024                   
1025               
1026                ##[cb state, name, value, "+/-", error of fit, min, max , units]
1027                self.parameters.append([cb,item, ctl1,
1028                                        text2,ctl2, ctl3, ctl4,None])
1029                self.orientation_params.append([cb,item, ctl1,
1030                                        text2,ctl2, ctl3, ctl4,None])
1031             
1032        iy+=1
1033        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1034       
1035        #Display units text on panel
1036        for item in keys:   
1037            if self.model.details[item][0]!='':
1038                self.text2_4.Show()
1039                break
1040            else:
1041                self.text2_4.Hide()
1042   
1043        boxsizer1.Add(sizer)
1044       
1045        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1046        self.sizer3.Layout()
1047        self.SetScrollbars(20,20,200,100)
1048       
1049   
1050           
1051       
1052class HelpWindow(wx.Frame):
1053    def __init__(self, parent, id, title):
1054        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
1055       
1056        from sans.models.CylinderModel import CylinderModel
1057        model = CylinderModel()
1058       
1059        from danse.common.plottools.plottables import Data1D
1060        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
1061   
1062        from fitpanel import PageInfo
1063        myinfo = PageInfo(self,  model, data=data )
1064       
1065        ## add data
1066       
1067        from models import ModelList
1068        mylist= ModelList()
1069
1070        from sans.models.SphereModel import SphereModel
1071        from sans.models.SquareWellStructure import SquareWellStructure
1072        from sans.models.DebyeModel import DebyeModel
1073        from sans.models.LineModel import LineModel
1074        name= "shapes"
1075        list1= [SphereModel]
1076        mylist.set_list( name, list1)
1077       
1078        name= "Shape-independent"
1079        list1= [DebyeModel]
1080        mylist.set_list( name, list1)
1081       
1082        name= "Structure Factors"
1083        list1= [SquareWellStructure]
1084        mylist.set_list( name, list1)
1085       
1086        name= "Added models"
1087        list1= [LineModel]
1088        mylist.set_list( name, list1)
1089       
1090        myinfo.model_list_box = mylist.get_list()
1091       
1092        self.page = FitPage(self, myinfo) 
1093       
1094       
1095       
1096        self.Centre()
1097        self.Show(True)
1098
1099
1100   
1101if __name__=="__main__":
1102    app = wx.App()
1103    HelpWindow(None, -1, 'HelpWindow')
1104    app.MainLoop()
1105               
Note: See TracBrowser for help on using the repository browser.