source: sasview/sansview/perspectives/fitting/fitpage.py @ a8088d7

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

plotting all 1D data as Data1D

  • Property mode set to 100644
File size: 46.8 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        temp_smearer = None
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       
627        ## set smearing value whether or not the data contain the smearing info
628        self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
629                                      qmax= float(self.qmax_x)) 
630        ##Calculate chi2
631        self.compute_chisqr(smearer= temp_smearer) 
632        ## save the state enable smearing
633        self.save_current_state()
634       
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       
647        err_image = copy.deepcopy(self.data.err_data)
648        if err_image==[] or err_image==None:
649            err_image= numpy.zeros(len(self.data.x_bins),len(self.data.y_bins))
650                       
651        err_image[err_image==0]=1
652       
653        res=[]
654        if flag== True:
655            try:
656                self.qmin_x = float(self.qmin.GetValue())
657                self.qmax_x = float(self.qmax.GetValue())
658                for i in range(len(self.data.x_bins)):
659                    for j in range(len(self.data.y_bins)):
660                        #Check the range containing data between self.qmin_x and self.qmax_x
661                        value =  math.pow(self.data.x_bins[i],2)+ math.pow(self.data.y_bins[j],2)
662                        if value >= math.pow(self.qmin_x,2) and value <= math.pow(self.qmax_x,2):
663                           
664                            temp = [self.data.x_bins[i],self.data.y_bins[j]]
665                            error= err_image[j][i]
666                            chisqrji = (self.data.data[j][i]- self.model.runXY(temp ))/error
667                            #Vector containing residuals
668                            res.append( math.pow(chisqrji,2) )
669
670                # compute sum of residual
671                sum=0
672                for item in res:
673                    if numpy.isfinite(item):
674                        sum +=item
675                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
676            except:
677                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
678                            "Chisqr cannot be compute: %s"% sys.exc_value))
679                return
680   
681       
682    def compute_chisqr(self , smearer=None):
683        """
684            compute chi square given a model and data 1D and set the value
685            to the tcChi txtcrl
686        """
687        from sans.guiframe.utils import check_value
688        flag = check_value( self.qmin, self.qmax)
689       
690        if flag== True:
691            try:
692                if hasattr(self.data,"data"):
693                    self.compute_chisqr2D()
694                    return
695                else:
696                    self.qmin_x = float(self.qmin.GetValue())
697                    self.qmax_x = float(self.qmax.GetValue())
698                    # return residuals within self.qmin_x and self.qmax_x
699                    x,y = [numpy.asarray(v) for v in (self.data.x,self.data.y)]
700                   
701                    if self.data.dy==None:
702                        dy= numpy.zeros(len(y))
703                    else:
704                        dy= copy.deepcopy(self.data.dy)
705                        dy= numpy.asarray(dy)
706                    dy[dy==0]=1
707                   
708                    if self.qmin_x==None and self.qmax_x==None: 
709                        fx =numpy.asarray([self.model.run(v) for v in x])
710                        if smearer!=None:
711                            fx= smearer(fx)
712                        temp=(y - fx)/dy
713                        res= temp*temp
714                    else:
715                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
716                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
717                        if smearer!=None:
718                            fx= smearer(fx)
719                        temp=(y[idx] - fx)/dy[idx]
720                        res= temp*temp
721                    #sum of residuals
722                    sum=0
723                    for item in res:
724                        if numpy.isfinite(item):
725                            sum +=item
726                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
727            except:
728                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
729                            "Chisqr cannot be compute: %s"% sys.exc_value))
730                return 
731           
732   
733    def select_all_param(self,event): 
734        """
735             set to true or false all checkBox given the main checkbox value cb1
736        """           
737
738        self.param_toFit=[]
739       
740        if  self.parameters !=[]:
741            if  self.cb1.GetValue():
742                for item in self.parameters:
743                    item[0].SetValue(True)
744                    self.param_toFit.append(item )
745                if len(self.fittable_param)>0:
746                    for item in self.fittable_param:
747                        item[0].SetValue(True)
748                        self.param_toFit.append(item )
749            else:
750                for item in self.parameters:
751                    item[0].SetValue(False)
752                for item in self.fittable_param:
753                    item[0].SetValue(False)
754                self.param_toFit=[]
755               
756        self.save_current_state() 
757       
758               
759               
760    def select_param(self,event):
761        """
762            Select TextCtrl  checked for fitting purpose and stores them
763            in  self.param_toFit=[] list
764        """
765        self.param_toFit=[]
766        for item in self.parameters:
767            #Select parameters to fit for list of primary parameters
768            if item[0].GetValue():
769                if not (item in self.param_toFit):
770                    self.param_toFit.append(item ) 
771            else:
772                #remove parameters from the fitting list
773                if item in self.param_toFit:
774                    self.param_toFit.remove(item)
775        #Select parameters to fit for list of fittable parameters with dispersion         
776        for item in self.fittable_param:
777            if item[0].GetValue():
778                if not (item in self.param_toFit):
779                    self.param_toFit.append(item) 
780            else:
781                #remove parameters from the fitting list
782                if item in self.param_toFit:
783                    self.param_toFit.remove(item)           
784        #Set the value of checkbox that selected every checkbox or not           
785        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
786            self.cb1.SetValue(True)
787        else:
788            self.cb1.SetValue(False)
789        ## save current state of the page
790        self.save_current_state()
791       
792   
793       
794    def set_model_param_sizer(self, model):
795        """
796            Build the panel from the model content
797            @param model: the model selected in combo box for fitting purpose
798        """
799        self.sizer3.Clear(True)
800        self.parameters = []
801        self.param_toFit=[]
802        self.fittable_param=[]
803        self.fixed_param=[]
804        self.orientation_params=[]
805        self.orientation_params_disp=[]
806       
807        if model ==None:
808            self.sizer3.Layout()
809            self.SetScrollbars(20,20,200,100)
810            return
811        ## the panel is drawn using the current value of the fit engine
812        if self.engine_type==None and self.manager !=None:
813            self.engine_type= self.manager._return_engine_type()
814           
815        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
816        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
817        sizer = wx.GridBagSizer(5,5)
818        ## save the current model
819        self.model = model
820           
821        keys = self.model.getParamList()
822        #list of dispersion paramaters
823        self.disp_list=self.model.getDispParamList()
824       
825        keys.sort()
826   
827        iy = 1
828        ix = 0
829        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
830        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
831        self.cb1.SetValue(False)
832       
833        sizer.Add(self.cb1,(iy, ix),(1,1),\
834                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
835        ix += 1
836        self.text2_4 = wx.StaticText(self, -1, '[Units]')
837        sizer.Add(self.text2_4,(iy, ix),(1,1),\
838                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
839        #self.text2_4.Hide()
840        ix +=1
841        self.text2_2 = wx.StaticText(self, -1, 'Values')
842        sizer.Add(self.text2_2,(iy, ix),(1,1),\
843                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
844        ix +=2 
845        self.text2_3 = wx.StaticText(self, -1, 'Errors')
846        sizer.Add(self.text2_3,(iy, ix),(1,1),\
847                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
848        self.text2_3.Hide()
849        ix +=1 
850        self.text2_min = wx.StaticText(self, -1, 'Min')
851        sizer.Add(self.text2_min,(iy, ix),(1,1),\
852                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
853        self.text2_min.Hide()
854        ix +=1 
855        self.text2_max = wx.StaticText(self, -1, 'Max')
856        sizer.Add(self.text2_max,(iy, ix),(1,1),\
857                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
858        self.text2_max.Hide()
859        if self.engine_type=="park":
860            self.text2_max.Show(True)
861            self.text2_min.Show(True)
862
863        for item in keys:
864            if not item in self.disp_list and not item in self.model.orientation_params:
865                iy += 1
866                ix = 0
867                ## add parameters name with checkbox for selecting to fit
868                cb = wx.CheckBox(self, -1, item )
869                cb.SetValue(False)
870                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
871                sizer.Add( cb,( iy, ix),(1,1),
872                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
873                ix +=1
874                # Units
875                try:
876                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
877                except:
878                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
879                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
880               
881                ## add parameter value
882                ix += 1
883                value= self.model.getParam(item)
884                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
885                                    style=wx.TE_PROCESS_ENTER)
886               
887                ctl1.SetValue(format_number(value))
888                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
889                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
890                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
891                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
892                ## text to show error sign
893                ix += 1
894                text2=wx.StaticText(self, -1, '+/-')
895                sizer.Add(text2,(iy, ix),(1,1),\
896                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
897                text2.Hide() 
898                ## txtcrtl to add error from fit
899                ix += 1
900                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
901                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
902                ctl2.Hide()
903               
904                param_min, param_max= self.model.details[item][1:]
905                ix += 1
906                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
907                if param_min ==None:
908                    ctl3.SetValue("")
909                else:
910                    ctl3.SetValue(str(param_min))
911                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
912                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
913                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
914                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
915                ctl3.Hide()
916       
917                ix += 1
918                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
919                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
920                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
921                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
922                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
923                if param_max==None:
924                    ctl4.SetValue("")
925                else:
926                    ctl4.SetValue(str(param_max))
927                ctl4.Hide()
928               
929                if self.engine_type=="park":
930                    ctl3.Show(True)
931                    ctl4.Show(True)
932                   
933                ##[cb state, name, value, "+/-", error of fit, min, max , units]
934                self.parameters.append([cb,item, ctl1,
935                                        text2,ctl2, ctl3, ctl4,None])
936             
937        iy+=1
938        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
939        for item in self.model.orientation_params:
940            if not item in self.disp_list :
941                iy += 1
942                ix = 0
943                ## add parameters name with checkbox for selecting to fit
944                cb = wx.CheckBox(self, -1, item )
945                cb.SetValue(False)
946                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
947                if self.data.__class__.__name__ =="Data2D":
948                    cb.Enable()
949                else:
950                    cb.Disable()
951                sizer.Add( cb,( iy, ix),(1,1),
952                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
953                ix +=1
954                # Units
955                try:
956                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
957                except:
958                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
959                if self.data.__class__.__name__ =="Data2D":
960                    units.Enable()
961                else:
962                    units.Disable()
963                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
964
965                ## add parameter value
966                ix += 1
967                value= self.model.getParam(item)
968                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
969                                    style=wx.TE_PROCESS_ENTER)
970               
971                ctl1.SetValue(format_number(value))
972                if self.data.__class__.__name__ =="Data2D":
973                    ctl1.Enable()
974                else:
975                    ctl1.Disable()
976                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
977                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
978                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
979                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
980                ## text to show error sign
981                ix += 1
982                text2=wx.StaticText(self, -1, '+/-')
983                sizer.Add(text2,(iy, ix),(1,1),\
984                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
985                text2.Hide() 
986                ## txtcrtl to add error from fit
987                ix += 1
988                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
989                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
990                ctl2.Hide()
991                if self.data.__class__.__name__ =="Data2D":
992                    ctl1.Enable()
993                else:
994                    ctl1.Disable()
995                param_min, param_max= self.model.details[item][1:]
996                ix += 1
997                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
998                if param_min ==None:
999                    ctl3.SetValue("")
1000                else:
1001                    ctl3.SetValue(str(param_min))
1002                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1003                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
1004                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
1005                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1006                ctl3.Hide()
1007                if self.data.__class__.__name__ =="Data2D":
1008                    ctl3.Enable()
1009                else:
1010                    ctl3.Disable()
1011                ix += 1
1012                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
1013                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1014                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamRangeEnter)
1015                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamRangeEnter)
1016                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1017                ctl4.SetValue(str(param_max))
1018                ctl4.Hide()
1019                if self.data.__class__.__name__ =="Data2D":
1020                    ctl4.Enable()
1021                else:
1022                    ctl4.Disable()
1023                if self.engine_type=="park":
1024                    ctl3.Show(True)
1025                    ctl4.Show(True)
1026                   
1027               
1028                ##[cb state, name, value, "+/-", error of fit, min, max , units]
1029                self.parameters.append([cb,item, ctl1,
1030                                        text2,ctl2, ctl3, ctl4,None])
1031                self.orientation_params.append([cb,item, ctl1,
1032                                        text2,ctl2, ctl3, ctl4,None])
1033             
1034        iy+=1
1035        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1036       
1037        #Display units text on panel
1038        for item in keys:   
1039            if self.model.details[item][0]!='':
1040                self.text2_4.Show()
1041                break
1042            else:
1043                self.text2_4.Hide()
1044   
1045        boxsizer1.Add(sizer)
1046       
1047        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1048        self.sizer3.Layout()
1049        self.SetScrollbars(20,20,200,100)
1050       
1051   
1052           
1053       
1054class HelpWindow(wx.Frame):
1055    def __init__(self, parent, id, title):
1056        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
1057       
1058        from sans.models.CylinderModel import CylinderModel
1059        model = CylinderModel()
1060       
1061        from danse.common.plottools.plottables import Data1D
1062        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
1063   
1064        from fitpanel import PageInfo
1065        myinfo = PageInfo(self,  model, data=data )
1066       
1067        ## add data
1068       
1069        from models import ModelList
1070        mylist= ModelList()
1071
1072        from sans.models.SphereModel import SphereModel
1073        from sans.models.SquareWellStructure import SquareWellStructure
1074        from sans.models.DebyeModel import DebyeModel
1075        from sans.models.LineModel import LineModel
1076        name= "shapes"
1077        list1= [SphereModel]
1078        mylist.set_list( name, list1)
1079       
1080        name= "Shape-independent"
1081        list1= [DebyeModel]
1082        mylist.set_list( name, list1)
1083       
1084        name= "Structure Factors"
1085        list1= [SquareWellStructure]
1086        mylist.set_list( name, list1)
1087       
1088        name= "Added models"
1089        list1= [LineModel]
1090        mylist.set_list( name, list1)
1091       
1092        myinfo.model_list_box = mylist.get_list()
1093       
1094        self.page = FitPage(self, myinfo) 
1095       
1096       
1097       
1098        self.Centre()
1099        self.Show(True)
1100
1101
1102   
1103if __name__=="__main__":
1104    app = wx.App()
1105    HelpWindow(None, -1, 'HelpWindow')
1106    app.MainLoop()
1107               
Note: See TracBrowser for help on using the repository browser.