source: sasview/sansview/perspectives/fitting/fitpage.py @ 780d095

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

add disabling parameter for 1D and 2D orientation

  • Property mode set to 100644
File size: 43.7 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
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        self._onparamEnter_helper()
462        self.compute_chisqr()
463       
464       
465    def reset_page(self, state):
466        """
467            reset the state
468        """
469        self.reset_page_helper(state)
470        evt = ModelEventbox(model=self.model)
471        wx.PostEvent(self.event_owner, evt)   
472           
473           
474    def get_range(self):
475        """
476            return the fitting range
477        """
478        return float(self.qmin_x) , float(self.qmax_x)
479       
480    def get_param_list(self):
481        """
482            @return self.param_toFit: list containing  references to TextCtrl
483            checked.Theses TextCtrl will allow reference to parameters to fit.
484            @raise: if return an empty list of parameter fit will nnote work
485            properly so raise ValueError,"missing parameter to fit"
486        """
487        if self.param_toFit !=[]:
488            return self.param_toFit
489        else:
490            raise ValueError,"missing parameter to fit"   
491     
492    def onsetValues(self,chisqr, out,cov):
493        """
494            Build the panel from the fit result
495            @param chisqr:Value of the goodness of fit metric
496            @param out:list of parameter with the best value found during fitting
497            @param cov:Covariance matrix
498       
499        """
500        self.tcChi.SetLabel(format_number(chisqr))
501        params = {}
502        is_modified = False
503        has_error = False
504        self.text2_3.Hide()
505        if self.text_disp_1 !=None:
506            self.text_disp_1.Hide()
507        #set the panel when fit result are float not list
508        if out.__class__==numpy.float64:
509            self.param_toFit[0][2].SetValue(format_number(out))
510            self.param_toFit[0][2].Refresh()
511           
512            self.param_toFit[0][4].Clear()
513            self.param_toFit[0][4].Hide()
514            if cov !=None :
515                self.text2_3.Show(True)
516                if self.text_disp_1 !=None:
517                    self.text_disp_1.Show(True)
518                   
519                self.param_toFit[0][3].Show(True)
520                self.param_toFit[0][4].Clear()
521                self.param_toFit[0][4].SetValue(format_number(cov[0]))
522                self.param_toFit[0][4].Show(True)
523        else:
524            i=0
525            j=0
526            #Set the panel when fit result are list
527            for item in self.param_toFit:
528                ## reset error value to initial state
529                item[4].Clear()
530                item[4].Hide()
531                item[4].Refresh()
532                if( out != None ) and len(out)<=len(self.param_toFit)and i < len(out):
533                    item[2].SetValue(format_number(self.model.getParam(item[1])))
534                    item[2].Refresh()
535                if(cov !=None)and len(cov)<=len(self.param_toFit)and i < len(cov):
536                    self.text2_3.Show(True) 
537                    if self.text_disp_1!=None:
538                        self.text_disp_1.Show(True)
539                    item[3].Show(True)
540                    item[4].Clear()
541                    for j in range(len(out)):
542                        if out[j]==self.model.getParam(item[1]):
543                            break
544                    item[4].SetValue(format_number(cov[j]))
545                    item[4].Refresh()
546                    item[4].Show(True)   
547                i+=1
548       
549        self.sizer3.Layout()
550        self.sizer4.Layout()
551        self.SetScrollbars(20,20,200,100)
552       
553       
554     
555    def onSmear(self, event):
556        """
557            Create a smear object that will change the way residuals
558            are compute when fitting
559        """
560        smear =None
561        msg=""
562        if self.enable_smearer.GetValue():
563            from DataLoader.qsmearing import smear_selection
564            smear = smear_selection( self.data )
565            if hasattr(self.data,"dxl"):
566                msg= ": Resolution smearing parameters"
567            if hasattr(self.data,"dxw"):
568                msg= ": Slit smearing parameters"
569            if smear ==None:
570                wx.PostEvent(self.manager.parent, StatusEvent(status=\
571                            "Data contains no smearing information"))
572            else:
573                wx.PostEvent(self.manager.parent, StatusEvent(status=\
574                            "Data contains smearing information %s"%msg))
575        ## set smearing value whether or not the data contain the smearing info
576        self.manager.set_smearer(smear, qmin= float(self.qmin_x),
577                                      qmax= float(self.qmax_x))   
578        ## save the state enable smearing
579        self.save_current_state()
580       
581 
582    def compute_chisqr2D(self):
583        """
584            compute chi square given a model and data 2D and set the value
585            to the tcChi txtcrl
586        """
587        from sans.guiframe.utils import check_value
588        flag = check_value( self.qmin, self.qmax)
589        err_image = self.data.err_data
590        if err_image==[] or err_image==None:
591            err_image= numpy.zeros(len(self.data.x_bins),len(self.data.y_bins))
592                       
593        err_image[err_image==0]=1
594        res=[]
595        if flag== True:
596            try:
597                self.qmin_x = float(self.qmin.GetValue())
598                self.qmax_x = float(self.qmax.GetValue())
599                for i in range(len(self.data.x_bins)):
600                    for j in range(len(self.data.y_bins)):
601                        #Check the range containing data between self.qmin_x and self.qmax_x
602                        value =  math.pow(self.data.x_bins[i],2)+ math.pow(self.data.y_bins[j],2)
603                        if value >= math.pow(self.qmin_x,2) and value <= math.pow(self.qmax_x,2):
604                           
605                            temp = [self.data.x_bins[i],self.data.y_bins[j]]
606                            error= err_image[j][i]
607                            chisqrji = (self.data.data[j][i]- self.model.runXY(temp ))/error
608                            #Vector containing residuals
609                            res.append( math.pow(chisqrji,2) )
610
611                # compute sum of residual
612                sum=0
613                for item in res:
614                    if numpy.isfinite(item):
615                        sum +=item
616                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
617            except:
618                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
619                            "Chisqr cannot be compute: %s"% sys.exc_value))
620                return
621   
622       
623    def compute_chisqr(self):
624        """
625            compute chi square given a model and data 1D and set the value
626            to the tcChi txtcrl
627        """
628        from sans.guiframe.utils import check_value
629        flag = check_value( self.qmin, self.qmax)
630       
631        if flag== True:
632            try:
633                if hasattr(self.data,"data"):
634                    self.compute_chisqr2D()
635                    return
636                else:
637                    self.qmin_x = float(self.qmin.GetValue())
638                    self.qmax_x = float(self.qmax.GetValue())
639                    # return residuals within self.qmin_x and self.qmax_x
640                    x,y = [numpy.asarray(v) for v in (self.data.x,self.data.y)]
641                   
642                    if self.data.dy==None:
643                        dy= numpy.zeros(len(y))
644                    else:
645                        dy= numpy.asarray(self.data.dy)
646                    dy[dy==0]=1
647                    if self.qmin_x==None and self.qmax_x==None: 
648                        fx =numpy.asarray([self.model.run(v) for v in x])
649                        temp=(y - fx)/dy
650                        res= temp*temp
651                    else:
652                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
653                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
654                        temp=(y[idx] - fx)/dy[idx]
655                        res= temp*temp
656                    #sum of residuals
657                    sum=0
658                    for item in res:
659                        if numpy.isfinite(item):
660                            sum +=item
661                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
662            except:
663                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
664                            "Chisqr cannot be compute: %s"% sys.exc_value))
665                return 
666           
667   
668    def select_all_param(self,event): 
669        """
670             set to true or false all checkBox given the main checkbox value cb1
671        """
672        self.param_toFit=[]
673       
674        if  self.parameters !=[]:
675            if  self.cb1.GetValue()==True:
676                for item in self.parameters:
677                    item[0].SetValue(True)
678                    self.param_toFit.append(item )
679                if len(self.fittable_param)>0:
680                    for item in self.fittable_param:
681                        item[0].SetValue(True)
682                        self.param_toFit.append(item )
683            else:
684                for item in self.parameters:
685                    item[0].SetValue(False)
686                for item in self.fittable_param:
687                    item[0].SetValue(False)
688                self.param_toFit=[]
689        self.save_current_state() 
690       
691               
692               
693    def select_param(self,event):
694        """
695            Select TextCtrl  checked for fitting purpose and stores them
696            in  self.param_toFit=[] list
697        """
698        self.param_toFit=[]
699        for item in self.parameters:
700            #Select parameters to fit for list of primary parameters
701            if item[0].GetValue()==True:
702                if not (item in self.param_toFit):
703                    self.param_toFit.append(item ) 
704            else:
705                #remove parameters from the fitting list
706                if item in self.param_toFit:
707                    self.param_toFit.remove(item)
708        #Select parameters to fit for list of fittable parameters with dispersion         
709        for item in self.fittable_param:
710            if item[0].GetValue()==True:
711                if not (item in self.param_toFit):
712                    self.param_toFit.append(item) 
713            else:
714                #remove parameters from the fitting list
715                if item in self.param_toFit:
716                    self.param_toFit.remove(item)           
717        #Set the value of checkbox that selected every checkbox or not           
718        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
719            self.cb1.SetValue(True)
720        else:
721            self.cb1.SetValue(False)
722        ## save current state of the page
723        self.save_current_state()
724       
725   
726       
727    def set_model_param_sizer(self, model):
728        """
729            Build the panel from the model content
730            @param model: the model selected in combo box for fitting purpose
731        """
732        self.sizer3.Clear(True)
733        self.parameters = []
734        self.param_toFit=[]
735        self.fittable_param=[]
736        self.fixed_param=[]
737        self.orientation_params=[]
738       
739        if model ==None:
740            self.sizer3.Layout()
741            self.SetScrollbars(20,20,200,100)
742            return
743        ## the panel is drawn using the current value of the fit engine
744        if self.engine_type==None and self.manager !=None:
745            self.engine_type= self.manager._return_engine_type()
746           
747        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
748        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
749        sizer = wx.GridBagSizer(5,5)
750        ## save the current model
751        self.model = model
752           
753        keys = self.model.getParamList()
754        #list of dispersion paramaters
755        self.disp_list=self.model.getDispParamList()
756       
757        keys.sort()
758   
759        iy = 1
760        ix = 0
761        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
762        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
763        self.cb1.SetValue(False)
764       
765        sizer.Add(self.cb1,(iy, ix),(1,1),\
766                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
767        ix +=1
768        self.text2_2 = wx.StaticText(self, -1, 'Values')
769        sizer.Add(self.text2_2,(iy, ix),(1,1),\
770                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
771        ix +=2 
772        self.text2_3 = wx.StaticText(self, -1, 'Errors')
773        sizer.Add(self.text2_3,(iy, ix),(1,1),\
774                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
775        self.text2_3.Hide()
776        ix +=1 
777        self.text2_min = wx.StaticText(self, -1, 'Min')
778        sizer.Add(self.text2_min,(iy, ix),(1,1),\
779                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
780        self.text2_min.Hide()
781        ix +=1 
782        self.text2_max = wx.StaticText(self, -1, 'Max')
783        sizer.Add(self.text2_max,(iy, ix),(1,1),\
784                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
785        self.text2_max.Hide()
786        ix += 1
787        self.text2_4 = wx.StaticText(self, -1, 'Units')
788        sizer.Add(self.text2_4,(iy, ix),(1,1),\
789                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
790        self.text2_4.Hide()
791        if self.engine_type=="park":
792            self.text2_max.Show(True)
793            self.text2_min.Show(True)
794
795        for item in keys:
796            if not item in self.disp_list and not item in self.model.orientation_params:
797                iy += 1
798                ix = 0
799                ## add parameters name with checkbox for selecting to fit
800                cb = wx.CheckBox(self, -1, item )
801                cb.SetValue(False)
802                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
803                sizer.Add( cb,( iy, ix),(1,1),
804                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
805                ## add parameter value
806                ix += 1
807                value= self.model.getParam(item)
808                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
809                                    style=wx.TE_PROCESS_ENTER)
810               
811                ctl1.SetValue(format_number(value))
812                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
813                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
814                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
815                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
816                ## text to show error sign
817                ix += 1
818                text2=wx.StaticText(self, -1, '+/-')
819                sizer.Add(text2,(iy, ix),(1,1),\
820                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
821                text2.Hide() 
822                ## txtcrtl to add error from fit
823                ix += 1
824                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
825                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
826                ctl2.Hide()
827               
828                param_min, param_max= self.model.details[item][1:]
829                ix += 1
830                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
831                ctl3.SetValue(format_number(param_min))
832                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
833                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
834                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
835                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
836                ctl3.Hide()
837       
838                ix += 1
839                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
840                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
841                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
842                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
843                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
844                ctl4.SetValue(format_number(param_max))
845                ctl4.Hide()
846               
847                if self.engine_type=="park":
848                    ctl3.Show(True)
849                    ctl4.Show(True)
850                   
851                ix +=1
852                # Units
853                try:
854                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
855                except:
856                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
857                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
858               
859                ##[cb state, name, value, "+/-", error of fit, min, max , units]
860                self.parameters.append([cb,item, ctl1,
861                                        text2,ctl2, ctl3, ctl4,None])
862             
863        iy+=1
864        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
865        for item in self.model.orientation_params:
866            if not item in self.disp_list :
867                iy += 1
868                ix = 0
869                ## add parameters name with checkbox for selecting to fit
870                cb = wx.CheckBox(self, -1, item )
871                cb.SetValue(False)
872                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
873                if self.data.__class__.__name__ =="Data2D":
874                    cb.Enable()
875                else:
876                    cb.Disable()
877                sizer.Add( cb,( iy, ix),(1,1),
878                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
879                ## add parameter value
880                ix += 1
881                value= self.model.getParam(item)
882                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
883                                    style=wx.TE_PROCESS_ENTER)
884               
885                ctl1.SetValue(format_number(value))
886                if self.data.__class__.__name__ =="Data2D":
887                    ctl1.Enable()
888                else:
889                    ctl1.Disable()
890                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
891                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
892                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
893                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
894                ## text to show error sign
895                ix += 1
896                text2=wx.StaticText(self, -1, '+/-')
897                sizer.Add(text2,(iy, ix),(1,1),\
898                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
899                text2.Hide() 
900                ## txtcrtl to add error from fit
901                ix += 1
902                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
903                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
904                ctl2.Hide()
905                if self.data.__class__.__name__ =="Data2D":
906                    ctl1.Enable()
907                else:
908                    ctl1.Disable()
909                param_min, param_max= self.model.details[item][1:]
910                ix += 1
911                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
912                ctl3.SetValue(format_number(param_min))
913                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
914                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
915                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
916                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
917                ctl3.Hide()
918                if self.data.__class__.__name__ =="Data2D":
919                    ctl3.Enable()
920                else:
921                    ctl3.Disable()
922       
923                ix += 1
924                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
925                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
926                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
927                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
928                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
929                ctl4.SetValue(format_number(param_max))
930                ctl4.Hide()
931                if self.data.__class__.__name__ =="Data2D":
932                    ctl4.Enable()
933                else:
934                    ctl4.Disable()
935                if self.engine_type=="park":
936                    ctl3.Show(True)
937                    ctl4.Show(True)
938                   
939                ix +=1
940                # Units
941                try:
942                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
943                except:
944                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
945                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
946               
947                ##[cb state, name, value, "+/-", error of fit, min, max , units]
948                self.parameters.append([cb,item, ctl1,
949                                        text2,ctl2, ctl3, ctl4,None])
950                self.orientation_params.append([cb,item, ctl1,
951                                        text2,ctl2, ctl3, ctl4,None])
952             
953        iy+=1
954        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
955       
956        #Display units text on panel
957        for item in keys:   
958            if self.model.details[item][0]!='':
959                self.text2_4.Show()
960                break
961            else:
962                self.text2_4.Hide()
963   
964        boxsizer1.Add(sizer)
965       
966        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
967        self.sizer3.Layout()
968        self.SetScrollbars(20,20,200,100)
969       
970   
971           
972       
973class HelpWindow(wx.Frame):
974    def __init__(self, parent, id, title):
975        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
976       
977        from sans.models.CylinderModel import CylinderModel
978        model = CylinderModel()
979       
980        from danse.common.plottools.plottables import Data1D
981        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
982   
983        from fitpanel import PageInfo
984        myinfo = PageInfo(self,  model, data=data )
985       
986        ## add data
987       
988        from models import ModelList
989        mylist= ModelList()
990
991        from sans.models.SphereModel import SphereModel
992        from sans.models.SquareWellStructure import SquareWellStructure
993        from sans.models.DebyeModel import DebyeModel
994        from sans.models.LineModel import LineModel
995        name= "shapes"
996        list1= [SphereModel]
997        mylist.set_list( name, list1)
998       
999        name= "Shape-independent"
1000        list1= [DebyeModel]
1001        mylist.set_list( name, list1)
1002       
1003        name= "Structure Factors"
1004        list1= [SquareWellStructure]
1005        mylist.set_list( name, list1)
1006       
1007        name= "Added models"
1008        list1= [LineModel]
1009        mylist.set_list( name, list1)
1010       
1011        myinfo.model_list_box = mylist.get_list()
1012       
1013        self.page = FitPage(self, myinfo) 
1014       
1015       
1016       
1017        self.Centre()
1018        self.Show(True)
1019
1020
1021   
1022if __name__=="__main__":
1023    app = wx.App()
1024    HelpWindow(None, -1, 'HelpWindow')
1025    app.MainLoop()
1026               
Note: See TracBrowser for help on using the repository browser.