source: sasview/sansview/perspectives/fitting/fitpage.py @ 2a5bba7

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

minor interface change

  • Property mode set to 100644
File size: 33.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
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   
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            self.disp_cb_dict[item]= None
235            name1=item+".width"
236            name2=item+".npts"
237            name3=item+".nsigmas"
238            iy += 1
239            for p in self.model.dispersion[item].keys():
240   
241                if p=="width":
242                    ix = 0
243                    cb = wx.CheckBox(self, -1, name1, (10, 10))
244                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
245                   
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                   
253                    ctl1.SetValue(str (format_number(value)))
254                    ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
255                    ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
256                    ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
257                    self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
258                   
259                    ## text to show error sign
260                    ix = 2
261                    text2=wx.StaticText(self, -1, '+/-')
262                    self.sizer4_4.Add(text2,(iy, ix),(1,1),
263                                      wx.EXPAND|wx.ADJUST_MINSIZE, 0)
264                    text2.Hide() 
265                    ## txtcrtl to add error from fit
266                    ix = 3
267                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
268                    self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
269                    ctl2.Hide()
270                   
271                    self.fittable_param.append([cb,name1,ctl1,text2,
272                                                ctl2, None, None,None])
273                elif p=="npts":
274                        ix = 4
275                        value= self.model.getParam(name2)
276                        Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
277                                            style=wx.TE_PROCESS_ENTER)
278                       
279                        Tctl.SetValue(str (format_number(value)))
280                        Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
281                        Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
282                        Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
283                        self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
284                                           wx.EXPAND|wx.ADJUST_MINSIZE, 0)
285                       
286                        self.fixed_param.append([None,name2, Tctl,None,None,
287                                                  None, None,None])
288               
289                elif p=="nsigmas":
290                        ix = 5
291                        value= self.model.getParam(name3)
292                        Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
293                                            style=wx.TE_PROCESS_ENTER)
294                        Tctl.SetValue(str (format_number(value)))
295                        Tctl.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
296                        Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
297                        Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
298                        self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
299                                           wx.EXPAND|wx.ADJUST_MINSIZE, 0)
300                        ix +=1
301                        self.sizer4_4.Add((20,20), (iy,ix),(1,1),
302                                           wx.EXPAND|wx.ADJUST_MINSIZE, 0)
303                       
304                        self.fixed_param.append([None,name3, Tctl
305                                                 ,None,None, None, None,None])
306               
307        wx.PostEvent(self.parent, StatusEvent(status=\
308                        " Selected Distribution: Gaussian"))   
309        ix =0
310        iy +=1 
311        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
312        self.sizer4_4.Layout()
313        self.sizer4.Layout()
314        self.SetScrollbars(20,20,200,100)
315     
316       
317    def _onFit(self, event):     
318        """
319            Allow to fit
320        """
321        #self.btFit.SetLabel("Stop")
322        from sans.guiframe.utils import check_value
323        flag = check_value( self.qmin, self.qmax) 
324       
325        if not flag:
326            msg= "Fitting range invalid"
327            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
328            return 
329       
330        if len(self.param_toFit) <= 0:
331            msg= "Select at least one parameter to fit"
332            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
333            return 
334       
335        self.qmin_x=float(self.qmin.GetValue())
336        self.qmax_x =float( self.qmax.GetValue())
337        self.manager._reset_schedule_problem( value=0)
338        self.manager.schedule_for_fit( value=1,page=self,fitproblem =None) 
339        self.manager.set_fit_range(page= self,qmin= self.qmin_x, qmax= self.qmax_x)
340        #single fit
341        self.manager.onFit()
342           
343        self.sizer5.Layout()
344        self.SetScrollbars(20,20,55,40)
345       
346       
347    def _on_select_model(self, event): 
348        """
349             call back for model selection
350        """   
351        self._on_select_model_helper() 
352        self.set_model_param_sizer(self.model)
353        try:
354            self.compute_chisqr()
355        except:
356            ## error occured on chisqr computation
357            pass
358        self.enable_disp.SetValue(False)
359        self.disable_disp.SetValue(True)
360        self._set_dipers_Param(event=None)
361       
362        evt = ModelEventbox(model=self.model)
363        wx.PostEvent(self.event_owner, evt)   
364       
365
366    def _onparamEnter(self,event):
367        """
368            when enter value on panel redraw model according to changed
369        """
370        self._onparamEnter_helper()
371        self.compute_chisqr()
372       
373       
374    def reset_page(self, state):
375        """
376            reset the state
377        """
378        self.reset_page_helper(state)
379        evt = ModelEventbox(model=self.model)
380        wx.PostEvent(self.event_owner, evt)   
381           
382           
383    def get_range(self):
384        """
385            return the fitting range
386        """
387        return float(self.qmin_x) , float(self.qmax_x)
388       
389    def get_param_list(self):
390        """
391            @return self.param_toFit: list containing  references to TextCtrl
392            checked.Theses TextCtrl will allow reference to parameters to fit.
393            @raise: if return an empty list of parameter fit will nnote work
394            properly so raise ValueError,"missing parameter to fit"
395        """
396        if self.param_toFit !=[]:
397            return self.param_toFit
398        else:
399            raise ValueError,"missing parameter to fit"   
400     
401    def onsetValues(self,chisqr, out,cov):
402        """
403            Build the panel from the fit result
404            @param chisqr:Value of the goodness of fit metric
405            @param out:list of parameter with the best value found during fitting
406            @param cov:Covariance matrix
407       
408        """
409        self.tcChi.SetLabel(format_number(chisqr))
410        params = {}
411        is_modified = False
412        has_error = False
413        self.text2_3.Hide()
414        if self.text_disp_1 !=None:
415            self.text_disp_1.Hide()
416        #set the panel when fit result are float not list
417        if out.__class__==numpy.float64:
418            self.param_toFit[0][2].SetValue(format_number(out))
419            self.param_toFit[0][2].Refresh()
420           
421            self.param_toFit[0][4].Clear()
422            self.param_toFit[0][4].Hide()
423            if cov !=None :
424                self.text2_3.Show(True)
425                if self.text_disp_1 !=None:
426                    self.text_disp_1.Show(True)
427                   
428                self.param_toFit[0][3].Show(True)
429                self.param_toFit[0][4].Clear()
430                self.param_toFit[0][4].SetValue(format_number(cov[0]))
431                self.param_toFit[0][4].Show(True)
432        else:
433            i=0
434            j=0
435            #Set the panel when fit result are list
436            for item in self.param_toFit:
437                ## reset error value to initial state
438                item[4].Clear()
439                item[4].Hide()
440                item[4].Refresh()
441                if( out != None ) and len(out)<=len(self.param_toFit)and i < len(out):
442                    item[2].SetValue(format_number(self.model.getParam(item[1])))
443                    item[2].Refresh()
444                if(cov !=None)and len(cov)<=len(self.param_toFit)and i < len(cov):
445                    self.text2_3.Show(True) 
446                    if self.text_disp_1!=None:
447                        self.text_disp_1.Show(True)
448                    item[3].Show(True)
449                    item[4].Clear()
450                    for j in range(len(out)):
451                        if out[j]==self.model.getParam(item[1]):
452                            break
453                    item[4].SetValue(format_number(cov[j]))
454                    item[4].Refresh()
455                    item[4].Show(True)   
456                i+=1
457       
458        self.sizer3.Layout()
459        self.sizer4.Layout()
460        self.SetScrollbars(20,20,200,100)
461       
462       
463     
464    def onSmear(self, event):
465        """
466            Create a smear object that will change the way residuals
467            are compute when fitting
468        """
469        smear =None
470        msg=""
471        if self.enable_smearer.GetValue():
472            from DataLoader.qsmearing import smear_selection
473            smear = smear_selection( self.data )
474            if hasattr(self.data,"dxl"):
475                msg= ": Resolution smearing parameters"
476            if hasattr(self.data,"dxw"):
477                msg= ": Slit smearing parameters"
478            if smear ==None:
479                wx.PostEvent(self.manager.parent, StatusEvent(status=\
480                            "Data contains no smearing information"))
481            else:
482                wx.PostEvent(self.manager.parent, StatusEvent(status=\
483                            "Data contains smearing information %s"%msg))
484        ## set smearing value whether or not the data contain the smearing info
485        self.manager.set_smearer(smear, qmin= float(self.qmin_x),
486                                      qmax= float(self.qmax_x))   
487        ## save the state enable smearing
488        self.save_current_state()
489       
490 
491    def compute_chisqr2D(self):
492        """
493            compute chi square given a model and data 2D and set the value
494            to the tcChi txtcrl
495        """
496        from sans.guiframe.utils import check_value
497        flag = check_value( self.qmin, self.qmax)
498        err_image = self.data.err_data
499        if err_image==[] or err_image==None:
500            err_image= numpy.zeros(len(self.data.x_bins),len(self.data.y_bins))
501                       
502        err_image[err_image==0]=1
503        res=[]
504        if flag== True:
505            try:
506                self.qmin_x = float(self.qmin.GetValue())
507                self.qmax_x = float(self.qmax.GetValue())
508                for i in range(len(self.data.x_bins)):
509                    for j in range(len(self.data.y_bins)):
510                        #Check the range containing data between self.qmin_x and self.qmax_x
511                        value =  math.pow(self.data.x_bins[i],2)+ math.pow(self.data.y_bins[j],2)
512                        if value >= math.pow(self.qmin_x,2) and value <= math.pow(self.qmax_x,2):
513                           
514                            temp = [self.data.x_bins[i],self.data.y_bins[j]]
515                            error= err_image[j][i]
516                            chisqrji = (self.data.data[j][i]- self.model.runXY(temp ))/error
517                            #Vector containing residuals
518                            res.append( math.pow(chisqrji,2) )
519
520                # compute sum of residual
521                sum=0
522                for item in res:
523                    if numpy.isfinite(item):
524                        sum +=item
525                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
526            except:
527                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
528                            "Chisqr cannot be compute: %s"% sys.exc_value))
529                return
530   
531       
532    def compute_chisqr(self):
533        """
534            compute chi square given a model and data 1D and set the value
535            to the tcChi txtcrl
536        """
537        from sans.guiframe.utils import check_value
538        flag = check_value( self.qmin, self.qmax)
539       
540        if flag== True:
541            try:
542                if hasattr(self.data,"data"):
543                    self.compute_chisqr2D()
544                    return
545                else:
546                    self.qmin_x = float(self.qmin.GetValue())
547                    self.qmax_x = float(self.qmax.GetValue())
548                    # return residuals within self.qmin_x and self.qmax_x
549                    x,y = [numpy.asarray(v) for v in (self.data.x,self.data.y)]
550                   
551                    if self.data.dy==None:
552                        dy= numpy.zeros(len(y))
553                    else:
554                        dy= numpy.asarray(self.data.dy)
555                    dy[dy==0]=1
556                    if self.qmin_x==None and self.qmax_x==None: 
557                        fx =numpy.asarray([self.model.run(v) for v in x])
558                        temp=(y - fx)/dy
559                        res= temp*temp
560                    else:
561                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
562                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
563                        temp=(y[idx] - fx)/dy[idx]
564                        res= temp*temp
565                    #sum of residuals
566                    sum=0
567                    for item in res:
568                        if numpy.isfinite(item):
569                            sum +=item
570                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
571            except:
572                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
573                            "Chisqr cannot be compute: %s"% sys.exc_value))
574                return 
575           
576   
577    def select_all_param(self,event): 
578        """
579             set to true or false all checkBox given the main checkbox value cb1
580        """
581        self.param_toFit=[]
582       
583        if  self.parameters !=[]:
584            if  self.cb1.GetValue()==True:
585                for item in self.parameters:
586                    item[0].SetValue(True)
587                    self.param_toFit.append(item )
588                if len(self.fittable_param)>0:
589                    for item in self.fittable_param:
590                        item[0].SetValue(True)
591                        self.param_toFit.append(item )
592            else:
593                for item in self.parameters:
594                    item[0].SetValue(False)
595                for item in self.fittable_param:
596                    item[0].SetValue(False)
597                self.param_toFit=[]
598        self.save_current_state() 
599       
600               
601               
602    def select_param(self,event):
603        """
604            Select TextCtrl  checked for fitting purpose and stores them
605            in  self.param_toFit=[] list
606        """
607        self.param_toFit=[]
608        for item in self.parameters:
609            #Select parameters to fit for list of primary parameters
610            if item[0].GetValue()==True:
611                if not (item in self.param_toFit):
612                    self.param_toFit.append(item ) 
613            else:
614                #remove parameters from the fitting list
615                if item in self.param_toFit:
616                    self.param_toFit.remove(item)
617        #Select parameters to fit for list of fittable parameters with dispersion         
618        for item in self.fittable_param:
619            if item[0].GetValue()==True:
620                if not (item in self.param_toFit):
621                    self.param_toFit.append(item) 
622            else:
623                #remove parameters from the fitting list
624                if item in self.param_toFit:
625                    self.param_toFit.remove(item)           
626        #Set the value of checkbox that selected every checkbox or not           
627        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
628            self.cb1.SetValue(True)
629        else:
630            self.cb1.SetValue(False)
631        ## save current state of the page
632        self.save_current_state()
633       
634   
635       
636    def set_model_param_sizer(self, model):
637        """
638            Build the panel from the model content
639            @param model: the model selected in combo box for fitting purpose
640        """
641        self.sizer3.Clear(True)
642        self.parameters = []
643        self.param_toFit=[]
644        self.fittable_param=[]
645        self.fixed_param=[]
646       
647        if model ==None:
648            self.sizer3.Layout()
649            self.SetScrollbars(20,20,200,100)
650            return
651        ## the panel is drawn using the current value of the fit engine
652        if self.engine_type==None and self.manager !=None:
653            self.engine_type= self.manager._return_engine_type()
654           
655        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
656        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
657        sizer = wx.GridBagSizer(5,5)
658        ## save the current model
659        self.model = model
660           
661        keys = self.model.getParamList()
662        #list of dispersion paramaters
663        self.disp_list=self.model.getDispParamList()
664       
665        keys.sort()
666   
667        iy = 1
668        ix = 0
669        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
670        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
671        self.cb1.SetValue(False)
672       
673        sizer.Add(self.cb1,(iy, ix),(1,1),\
674                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
675        ix +=1
676        self.text2_2 = wx.StaticText(self, -1, 'Values')
677        sizer.Add(self.text2_2,(iy, ix),(1,1),\
678                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
679        ix +=2 
680        self.text2_3 = wx.StaticText(self, -1, 'Errors')
681        sizer.Add(self.text2_3,(iy, ix),(1,1),\
682                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
683        self.text2_3.Hide()
684        ix +=1 
685        self.text2_min = wx.StaticText(self, -1, 'Min')
686        sizer.Add(self.text2_min,(iy, ix),(1,1),\
687                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
688        self.text2_min.Hide()
689        ix +=1 
690        self.text2_max = wx.StaticText(self, -1, 'Max')
691        sizer.Add(self.text2_max,(iy, ix),(1,1),\
692                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
693        self.text2_max.Hide()
694        ix += 1
695        self.text2_4 = wx.StaticText(self, -1, 'Units')
696        sizer.Add(self.text2_4,(iy, ix),(1,1),\
697                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
698        self.text2_4.Hide()
699        if self.engine_type=="park":
700            self.text2_max.Show(True)
701            self.text2_min.Show(True)
702
703        for item in keys:
704            if not item in self.disp_list:
705                iy += 1
706                ix = 0
707                ## add parameters name with checkbox for selecting to fit
708                cb = wx.CheckBox(self, -1, item )
709                cb.SetValue(False)
710                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
711                sizer.Add( cb,( iy, ix),(1,1),
712                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
713                ## add parameter value
714                ix += 1
715                value= self.model.getParam(item)
716                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
717                                    style=wx.TE_PROCESS_ENTER)
718               
719                ctl1.SetValue(format_number(value))
720                ctl1.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
721                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
722                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
723                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
724                ## text to show error sign
725                ix += 1
726                text2=wx.StaticText(self, -1, '+/-')
727                sizer.Add(text2,(iy, ix),(1,1),\
728                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
729                text2.Hide() 
730                ## txtcrtl to add error from fit
731                ix += 1
732                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
733                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
734                ctl2.Hide()
735               
736                param_min, param_max= self.model.details[item][1:]
737                ix += 1
738                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
739                ctl3.SetValue(format_number(param_min))
740                ctl3.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
741                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
742                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
743                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
744                ctl3.Hide()
745       
746                ix += 1
747                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
748                ctl4.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
749                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
750                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
751                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
752                ctl4.SetValue(format_number(param_max))
753                ctl4.Hide()
754               
755                if self.engine_type=="park":
756                    ctl3.Show(True)
757                    ctl4.Show(True)
758                   
759                ix +=1
760                # Units
761                try:
762                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
763                except:
764                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
765                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
766               
767                ##[cb state, name, value, "+/-", error of fit, min, max , units]
768                self.parameters.append([cb,item, ctl1,
769                                        text2,ctl2, ctl3, ctl4,None])
770             
771        iy+=1
772        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
773       
774        #Display units text on panel
775        for item in keys:   
776            if self.model.details[item][0]!='':
777                self.text2_4.Show()
778                break
779            else:
780                self.text2_4.Hide()
781   
782        boxsizer1.Add(sizer)
783       
784        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
785        self.sizer3.Layout()
786        self.SetScrollbars(20,20,200,100)
787       
788   
789           
790       
791class HelpWindow(wx.Frame):
792    def __init__(self, parent, id, title):
793        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
794       
795        from sans.models.CylinderModel import CylinderModel
796        model = CylinderModel()
797       
798        from danse.common.plottools.plottables import Data1D
799        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
800   
801        from fitpanel import PageInfo
802        myinfo = PageInfo(self,  model, data=data )
803       
804        ## add data
805       
806        from models import ModelList
807        mylist= ModelList()
808
809        from sans.models.SphereModel import SphereModel
810        from sans.models.SquareWellStructure import SquareWellStructure
811        from sans.models.DebyeModel import DebyeModel
812        from sans.models.LineModel import LineModel
813        name= "shapes"
814        list1= [SphereModel]
815        mylist.set_list( name, list1)
816       
817        name= "Shape-independent"
818        list1= [DebyeModel]
819        mylist.set_list( name, list1)
820       
821        name= "Structure Factors"
822        list1= [SquareWellStructure]
823        mylist.set_list( name, list1)
824       
825        name= "Added models"
826        list1= [LineModel]
827        mylist.set_list( name, list1)
828       
829        myinfo.model_list_box = mylist.get_list()
830       
831        self.page = FitPage(self, myinfo) 
832       
833       
834       
835        self.Centre()
836        self.Show(True)
837
838
839   
840if __name__=="__main__":
841    app = wx.App()
842    HelpWindow(None, -1, 'HelpWindow')
843    app.MainLoop()
844               
Note: See TracBrowser for help on using the repository browser.