source: sasview/sansview/perspectives/fitting/fitpage.py @ 27c5c26

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 27c5c26 was 27c5c26, checked in by Jae Cho <jhjcho@…>, 15 years ago

changed notation of units

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