source: sasview/sansview/perspectives/fitting/fitpage.py @ 77e23a2

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

add fit with parameter range when selecting park only

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