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

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

remove invariant

  • Property mode set to 100644
File size: 66.6 KB
Line 
1
2
3import sys
4import wx
5import wx.lib.newevent
6import numpy
7import copy
8import math
9import time
10from sans.models.dispersion_models import ArrayDispersion, GaussianDispersion
11
12from sans.guicomm.events import StatusEvent   
13from sans.guiframe.utils import format_number,check_float
14 
15## event to post model to fit to fitting plugins
16(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
17
18## event to know the selected fit engine
19(FitterTypeEvent, EVT_FITTER_TYPE)   = wx.lib.newevent.NewEvent()
20(FitStopEvent, EVT_FIT_STOP)   = wx.lib.newevent.NewEvent()
21_BOX_WIDTH = 76
22_DATA_BOX_WIDTH = 300
23import basepage
24from basepage import BasicPage
25from basepage import PageInfoEvent
26from DataLoader.qsmearing import smear_selection
27
28class FitPage(BasicPage):
29    """
30        FitPanel class contains fields allowing to display results when
31        fitting  a model and one data
32        @note: For Fit to be performed the user should check at least one parameter
33        on fit Panel window.
34 
35    """
36   
37    def __init__(self,parent, page_info):
38        BasicPage.__init__(self, parent, page_info)
39
40        """
41            Initialization of the Panel
42        """
43        ## fit page does not content npts txtcrtl
44        self.npts=None
45        ## thread for compute Chisqr
46        self.calc_Chisqr=None
47        ## default fitengine type
48        self.engine_type = None
49       
50        ## draw sizer
51        self._fill_datainfo_sizer()
52       
53        self._fill_model_sizer( self.sizer1)
54 
55        self._fill_range_sizer() 
56        #self._on_select_model(event=None)
57        if self.data is None:
58            self.formfactorbox.Disable()
59            self.structurebox.Disable()
60        else:
61            self.smearer = smear_selection( self.data )
62            if self.smearer ==None:
63                self.enable_smearer.Disable()
64                self.disable_smearer.Disable()
65        self.disp_cb_dict = {}
66        ## to update the panel according to the fit engine type selected
67        self.Bind(EVT_FITTER_TYPE,self._on_engine_change)
68        self.Bind(EVT_FIT_STOP,self._on_fit_complete)
69       
70
71    def _on_fit_complete(self, event):
72        """
73            When fit is complete ,reset the fit button label.
74        """
75        #self.btFit.SetLabel("Fit")
76        #self.btFit.Unbind(event=wx.EVT_BUTTON, id=self.btFit.GetId())
77        #self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._onFit,id=self.btFit.GetId())
78        pass
79       
80       
81    def _on_engine_change(self, event):
82        """
83            get an event containing the current name of the fit engine type
84            @param event: FitterTypeEvent containing  the name of the current engine
85        """
86        self.engine_type = event.type
87        if len(self.parameters)==0:
88            self.Layout()
89            return
90        if event.type =="park":
91            self.btFit.SetLabel("Fit")
92
93        for item in self.parameters:
94            if event.type =="scipy" :
95                item[5].SetValue("")
96                item[5].Hide()
97                item[6].SetValue("")
98                item[6].Hide()
99                self.text2_min.Hide()
100                self.text2_max.Hide()
101
102            else:
103                item[5].Show(True)
104                item[6].Show(True)
105                self.text2_min.Show(True)
106                self.text2_max.Show(True)
107        for item in self.fittable_param:
108            if item[5]!=None and item[6]!=None and not item in self.orientation_params_disp:
109                if event.type =="scipy" and not item in self.orientation_params:
110                    item[5].SetValue("")
111                    item[5].Hide()
112                    item[6].SetValue("")
113                    item[6].Hide()
114                    self.text2_min.Hide()
115                    self.text2_max.Hide()
116                    self.text_disp_min.Hide()
117                    self.text_disp_max.Hide()
118                else:
119                    item[5].Show(True)
120                    item[6].Show(True)
121                    self.text2_min.Show(True)
122                    self.text2_max.Show(True)
123                    self.text_disp_min.Show(True)
124                    self.text_disp_max.Show(True)
125           
126        for item in self.orientation_params:
127            if item[5]!=None and item[6]!=None:
128                if event.type =="scipy" or self.data.__class__.__name__ !="Data2D":
129                    item[5].SetValue("")
130                    item[5].Hide()
131                    item[6].SetValue("")
132                    item[6].Hide()
133                else:
134                    item[5].Show(True)
135                    item[6].Show(True)
136                   
137        for item in self.orientation_params_disp:         
138            if item[5]!=None and item[6]!=None:
139                if event.type =="scipy" or self.data.__class__.__name__ !="Data2D":
140                    item[5].SetValue("")
141                    item[5].Hide()
142                    item[6].SetValue("")
143                    item[6].Hide()
144                else:
145                    item[5].Show(True)
146                    item[6].Show(True)
147        self.Layout()
148        self.Refresh()
149
150    def _fill_range_sizer(self):
151        """
152            Fill the sizer containing the plotting range
153            add  access to npts
154        """
155        title = "Fitting"
156        box_description_range = wx.StaticBox(self, -1,str(title))
157        boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL)
158
159        sizer_fit = wx.GridSizer(1, 1,0, 0)
160   
161        self.btFit = wx.Button(self,wx.NewId(),'Fit', size=(80,23))
162        self.btFit.Bind(wx.EVT_BUTTON, self._onFit,id= self.btFit.GetId())
163        self.btFit.SetToolTipString("Perform fit.")
164     
165       
166        sizer_fit.Add((5,5),1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)       
167        sizer_fit.Add(self.btFit,0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 35) 
168        sizer_fit.Layout()
169        sizer_smearer = wx.BoxSizer(wx.HORIZONTAL)
170        #Filling the sizer containing instruments smearing info.
171        self.disable_smearer = wx.RadioButton(self, -1, 'No', style=wx.RB_GROUP)
172        self.enable_smearer = wx.RadioButton(self, -1, 'Yes')
173        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId())
174        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId())
175        self.disable_smearer.SetValue(True)
176       
177        sizer_smearer.Add(wx.StaticText(self,-1,'Instrument Smearing? '))
178        sizer_smearer.Add((10, 10))
179        sizer_smearer.Add( self.enable_smearer )
180        sizer_smearer.Add((10,10))
181        sizer_smearer.Add( self.disable_smearer )
182        #Display Chi^2/dof
183        sizer_smearer.Add((78,10))
184        box_description= wx.StaticBox(self, -1,'Chi2/dof')
185        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
186        boxsizer1.SetMinSize((80,-1))
187        temp_smearer = None
188        if self.enable_smearer.GetValue():
189            temp_smearer= self.smearer
190       
191        self.tcChi    =  wx.StaticText(self, -1, "-", style=wx.ALIGN_LEFT)
192         
193        boxsizer1.Add( self.tcChi )   
194        sizer_smearer.Add( boxsizer1 )
195               
196        #Set sizer for Fitting section
197        self._set_range_sizer( title=title,box_sizer=boxsizer_range, object1=sizer_smearer, object= sizer_fit)
198
199    def _fill_datainfo_sizer(self):
200        """
201            fill sizer 0 with data info
202        """
203        ## no loaded data , don't fill the sizer
204        if self.data is None:
205            data_min = ""
206            data_max = ""
207            data_name = ""
208        else:
209            data_name = self.data.name
210            #set maximum range for x in linear scale
211            if not hasattr(self.data,"data"): #Display only for 1D data fit
212                # Minimum value of data   
213                data_min = min(self.data.x)
214                # Maximum value of data 
215                data_max = max(self.data.x)
216            else:
217                ## Minimum value of data
218                data_min = 0
219                x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
220                y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
221                ## Maximum value of data 
222                data_max = math.sqrt(x*x + y*y)
223       
224        box_description= wx.StaticBox(self, -1, 'Data')
225        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
226        #----------------------------------------------------------
227        sizer_data = wx.BoxSizer(wx.HORIZONTAL)
228        #Filling the sizer containing data related fields
229        #self.dataSource = wx.StaticText(self, -1,str(self.data.name))
230        self.dataSource = wx.TextCtrl(self, -1)
231        self.dataSource.SetValue(str(data_name))
232        self.dataSource.SetEditable(False)
233        self.dataSource.SetMinSize((_DATA_BOX_WIDTH, -1))
234        sizer_data.Add(wx.StaticText(self, -1, 'Source Name : '))
235        sizer_data.Add(self.dataSource )
236        sizer_data.Add( (0,5) )
237       
238        #---------sizer 2 draw--------------------------------
239        text4_3 = wx.StaticText(self, -1, 'Total Q Range (1/A)',
240                                 style=wx.ALIGN_LEFT)
241        sizer_range = wx.BoxSizer(wx.HORIZONTAL)
242        sizer_range.Add( text4_3 ,0, wx.RIGHT, 10)
243        self.minimum_q = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20))
244        self.minimum_q.SetValue(str(data_min))
245        self.minimum_q.SetEditable(False)
246        self.maximum_q = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
247        self.maximum_q.SetValue(str(data_max))
248        self.maximum_q.SetEditable(False)
249        sizer_range.Add(wx.StaticText(self, -1, "Min: "),0, wx.LEFT, 10)
250        sizer_range.Add(self.minimum_q,0, wx.LEFT, 10)
251        sizer_range.Add(wx.StaticText(self, -1, "Max: "),0, wx.LEFT, 10)
252        sizer_range.Add(self.maximum_q,0, wx.LEFT, 10)
253
254        ## set q range to plot
255        self.qmin_x = data_min
256        self.qmax_x = data_max
257
258        boxsizer1.Add(sizer_data,0, wx.ALL, 10)
259        boxsizer1.Add(sizer_range, 0 , wx.LEFT, 10)
260        #------------------------------------------------------------
261        self.sizer0.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
262        self.sizer0.Layout()
263       
264    def _fill_model_sizer(self, sizer):
265        """
266            fill sizer containing model info
267        """
268        ##Add model function Details button in fitpanel.
269        ##The following 3 lines are for Mac. Let JHC know before modifying...
270        title = "Model"
271        box_description= wx.StaticBox(self, -1,str(title))
272        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
273         
274        id = wx.NewId()
275        self.model_help =wx.Button(self,id,'Details', size=(80,23))
276        self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked,id=id)
277        self.model_help.SetToolTipString("Model Function Help")
278       
279        ## class base method  to add view 2d button   
280        self._set_model_sizer(sizer=sizer, box_sizer=boxsizer1, title="Model",object=self.model_help )   
281
282   
283    def _set_sizer_dispersion(self, dispersity):
284        """
285            draw sizer with gaussian dispersity parameters
286        """
287        self.fittable_param=[]
288        self.fixed_param=[]
289        self.orientation_params_disp=[]
290
291        self.sizer4_4.Clear(True)
292        if self.model==None:
293            ##no model is selected
294            return
295        if not self.enable_disp.GetValue():
296            ## the user didn't select dispersity display
297            return 
298           
299        self._reset_dispersity()
300       
301        # Create the dispersion objects
302        for item in self.model.dispersion.keys():
303            #disp_model =  GaussianDispersion()
304            disp_model = dispersity()
305            self._disp_obj_dict[item] = disp_model
306            self.model.set_dispersion(item, disp_model)
307            self.state._disp_obj_dict[item]= disp_model
308
309
310        ix=0
311        iy=1
312        disp = wx.StaticText(self, -1, 'Names')
313        self.sizer4_4.Add(disp,( iy, ix),(1,1), 
314                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
315        ix += 1 
316        values = wx.StaticText(self, -1, 'Sigmas (STD)')
317        self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
318        ix +=2 
319        self.text_disp_1 = wx.StaticText(self, -1, '')
320        self.sizer4_4.Add( self.text_disp_1,(iy, ix),(1,1),\
321                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
322        self.text_disp_1.Hide()
323       
324       
325        ix +=1 
326        self.text_disp_min = wx.StaticText(self, -1, 'Min')
327        self.sizer4_4.Add(self.text_disp_min,(iy, ix),(1,1),\
328                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
329        self.text_disp_min.Hide()
330        ix +=1 
331        self.text_disp_max = wx.StaticText(self, -1, 'Max')
332        self.sizer4_4.Add(self.text_disp_max,(iy, ix),(1,1),\
333                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
334        self.text_disp_max.Hide()
335                       
336       
337        ix += 1 
338        npts = wx.StaticText(self, -1, 'Npts')
339        self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
340        ix += 1 
341        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
342        self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
343       
344        if self.engine_type=="park":
345            self.text_disp_max.Show(True)
346            self.text_disp_min.Show(True)
347
348        for item in self.model.dispersion.keys():
349            if not item in self.model.orientation_params:
350                if not self.disp_cb_dict.has_key(item):
351                    self.disp_cb_dict[item]= None
352                name1=item+".width"
353                name2=item+".npts"
354                name3=item+".nsigmas"
355                if not self.model.details.has_key(name1):
356                    self.model.details [name1] = ["",None,None] 
357
358                iy += 1
359                for p in self.model.dispersion[item].keys(): 
360       
361                    if p=="width":
362                        ix = 0
363                        cb = wx.CheckBox(self, -1, name1, (10, 10))
364                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
365                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
366                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
367                        ix = 1
368                        value= self.model.getParam(name1)
369                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
370                                            style=wx.TE_PROCESS_ENTER)
371                        ctl1.SetValue(str (format_number(value)))
372                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
373                        ## text to show error sign
374                        ix = 2
375                        text2=wx.StaticText(self, -1, '+/-')
376                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
377                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
378                        text2.Hide() 
379
380                        ix = 3
381                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
382                 
383                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
384                     
385                        ctl2.Hide()
386
387                        ix = 4
388                        ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
389                                                       kill_focus_callback = self._onparamRangeEnter,
390                                                       text_enter_callback = self._onparamRangeEnter)
391
392                        self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
393                        ctl3.Hide()
394               
395                        ix = 5
396                        ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
397                                                       kill_focus_callback = self._onparamRangeEnter,
398                                                       text_enter_callback = self._onparamRangeEnter)
399                        self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
400
401                        ctl4.Hide()
402                       
403                        if self.engine_type=="park":
404                            ctl3.Show(True)
405                            ctl4.Show(True)
406                                         
407                        self.fittable_param.append([cb,name1,ctl1,text2,
408                                                    ctl2, ctl3, ctl4,None])                   
409                   
410                    elif p=="npts":
411                            ix = 6
412                            value= self.model.getParam(name2)
413                            Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
414                                                style=wx.TE_PROCESS_ENTER)
415                           
416                            Tctl.SetValue(str (format_number(value)))
417                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
418                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
419                            self.fixed_param.append([None,name2, Tctl,None,None,
420                                                      None, None,None])
421                    elif p=="nsigmas":
422                            ix = 7
423                            value= self.model.getParam(name3)
424                            Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
425                                                style=wx.TE_PROCESS_ENTER)
426                            Tct2.SetValue(str (format_number(value)))
427                            self.sizer4_4.Add(Tct2, (iy,ix),(1,1),
428                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
429                            ix +=1
430                            self.sizer4_4.Add((20,20), (iy,ix),(1,1),
431                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
432                           
433                            self.fixed_param.append([None,name3, Tct2
434                                                     ,None,None,None, None,None])
435                           
436        ix =0
437        iy +=1 
438        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
439        for item in self.model.dispersion.keys():
440            if  item in self.model.orientation_params:
441                if not self.disp_cb_dict.has_key(item):
442                    self.disp_cb_dict[item]= None
443                name1=item+".width"
444                name2=item+".npts"
445                name3=item+".nsigmas"
446                if not self.model.details.has_key(name1):
447                    self.model.details [name1] = ["",None,None]                 
448 
449
450                iy += 1
451                for p in self.model.dispersion[item].keys(): 
452       
453                    if p=="width":
454                        ix = 0
455                        cb = wx.CheckBox(self, -1, name1, (10, 10))
456                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
457                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
458                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
459                        if self.data.__class__.__name__ =="Data2D":
460                            cb.Show(True)
461                        elif cb.IsShown():
462                            cb.Hide()
463                        ix = 1
464                        value= self.model.getParam(name1)
465                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
466                                            style=wx.TE_PROCESS_ENTER)
467                        ctl1.SetValue(str (format_number(value)))
468                        if self.data.__class__.__name__ =="Data2D":
469                            ctl1.Show(True)
470                        elif ctl1.IsShown():
471                            ctl1.Hide()
472                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
473                        ## text to show error sign
474                        ix = 2
475                        text2=wx.StaticText(self, -1, '+/-')
476                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
477                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
478                        text2.Hide() 
479
480                        ix = 3
481                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
482                   
483                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
484                        ctl2.Hide()
485                           
486                        ix = 4
487                        ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
488                                                       kill_focus_callback = self._onparamRangeEnter,
489                                                       text_enter_callback = self._onparamRangeEnter)
490
491                        self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
492
493                        ctl3.Hide()
494               
495                        ix = 5
496                        ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
497                                                       kill_focus_callback = self._onparamRangeEnter,
498                                                       text_enter_callback = self._onparamRangeEnter)
499                        self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
500                        ctl4.Hide()
501                        #if self.data.__class__.__name__ =="Data2D":
502                            #ctl4.Enable(True)
503                        #elif ctl4.Shown():
504                            #ctl4.Hide()
505                       
506                        if self.engine_type=="park" and self.data.__class__.__name__ =="Data2D":
507                            ctl3.Show(True)
508                            ctl4.Show(True) 
509                           
510                           
511                           
512                           
513                        self.fittable_param.append([cb,name1,ctl1,text2,
514                                                    ctl2, ctl3, ctl4,None])
515                        self.orientation_params_disp.append([cb,name1,ctl1,text2,
516                                                    ctl2, ctl3, ctl4,None])
517                    elif p=="npts":
518                            ix = 6
519                            value= self.model.getParam(name2)
520                            Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
521                                                style=wx.TE_PROCESS_ENTER)
522                           
523                            Tctl.SetValue(str (format_number(value)))
524                            if self.data.__class__.__name__ =="Data2D":
525                                Tctl.Show(True)
526                            else:
527                                Tctl.Hide()
528                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
529                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
530                            self.fixed_param.append([None,name2, Tctl,None,None,
531                                                      None, None,None])
532                            self.orientation_params_disp.append([None,name2, Tctl,None,None,
533                                                      None, None,None])
534                    elif p=="nsigmas":
535                            ix = 7
536                            value= self.model.getParam(name3)
537                            Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
538                                                style=wx.TE_PROCESS_ENTER)
539                            Tct2.SetValue(str (format_number(value)))
540                            if self.data.__class__.__name__ =="Data2D":
541                                Tct2.Show(True)
542                            else:
543                                Tct2.Hide()
544                            self.sizer4_4.Add(Tct2, (iy,ix),(1,1),
545                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
546                            ix +=1
547
548                            self.fixed_param.append([None,name3, Tct2
549                                                     ,None,None, None, None,None])   
550                                                       
551                            self.orientation_params_disp.append([None,name3, Tct2
552                                                     ,None,None, None, None,None])
553       
554
555        self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict) 
556         
557        self.state.model = self.model.clone() 
558         ## save state into
559        self.state.cb1 = self.cb1.GetValue()
560        self._copy_parameters_state(self.parameters, self.state.parameters)
561        self._copy_parameters_state(self.orientation_params_disp,
562                                     self.state.orientation_params_disp)
563        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
564        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
565
566
567        wx.PostEvent(self.parent, StatusEvent(status=\
568                        " Selected Distribution: Gaussian"))   
569        #Fill the list of fittable parameters
570        self.select_all_param(event=None)
571       
572        self.Layout()
573
574
575    def _onFit(self, event):     
576        """
577            Allow to fit
578        """
579        #make sure all parameter values are updated.
580        if self.check_invalid_panel():
581            return
582        flag = self._update_paramv_on_fit() 
583               
584        if not flag:
585            msg= "Fitting range invalid"
586            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
587            return 
588       
589        if len(self.param_toFit) <= 0:
590            msg= "Select at least one parameter to fit"
591            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
592            return 
593     
594
595        self.select_param(event =None)
596       
597        #Clear errors if exist from previous fitting
598        #self._clear_Err_on_Fit()
599
600        # Remove or do not allow fitting on the Q=0 point, especially when y(q=0)=None at x[0].         
601        self.qmin_x = float(self.qmin.GetValue())
602        self.qmax_x = float( self.qmax.GetValue())
603        self.manager._reset_schedule_problem( value=0)
604        self.manager.schedule_for_fit( value=1,page=self,fitproblem =None) 
605        self.manager.set_fit_range(page= self,qmin= self.qmin_x, qmax= self.qmax_x)
606       
607        #single fit
608        self.manager.onFit()
609        ## allow stopping the fit
610        #if self.engine_type=="scipy":
611        #    self.btFit.SetLabel("Stop")
612        #    self.btFit.Unbind(event=wx.EVT_BUTTON, id= self.btFit.GetId())
613        #    self.btFit.Bind(event= wx.EVT_BUTTON, handler=self._StopFit, id=self.btFit.GetId())
614        #else:
615        #    self.btFit.SetLabel("Fit")
616        #    self.btFit.Bind(event= wx.EVT_BUTTON, handler=self._onFit, id=self.btFit.GetId())
617           
618
619       
620    def _StopFit(self, event):
621        """
622            Stop fit
623        """
624        self.btFit.SetLabel("Fit")
625        if self.engine_type=="scipy":
626            self.manager.stop_fit()
627        self.btFit.Unbind(event=wx.EVT_BUTTON, id=self.btFit.GetId())
628        self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._onFit,id=self.btFit.GetId())
629       
630           
631    def _on_select_model(self, event): 
632        """
633             call back for model selection
634        """   
635        self._on_select_model_helper() 
636        self.set_model_param_sizer(self.model)                   
637       
638        self.enable_disp.SetValue(False)
639        self.disable_disp.SetValue(True)
640        try:
641            self.set_dispers_sizer()
642        except:
643            pass
644        if self.model != None:
645            try:
646                temp_smear= None
647                if self.enable_smearer.GetValue():
648                    temp_smear= self.smearer
649                self.compute_chisqr(temp_smear)
650            except:
651                ## error occured on chisqr computation
652                pass
653            if self.data is not None and self.data.__class__.__name__ !="Data2D":
654                ## set smearing value whether or not the data contain the smearing info
655                self.manager.set_smearer(smearer=temp_smear, qmin= float(self.qmin_x),
656                                     qmax= float(self.qmax_x)) 
657           
658            evt = ModelEventbox(model=self.model)
659            wx.PostEvent(self.event_owner, evt) 
660           
661        self.btFit.SetFocus() 
662        self.state.enable_disp = self.enable_disp.GetValue()
663        self.state.disable_disp = self.disable_disp.GetValue()
664   
665        self.state.structurecombobox = self.structurebox.GetCurrentSelection()
666        self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection()
667     
668       
669        if event !=None:
670            #self._undo.Enable(True)
671            ## post state to fit panel
672            event = PageInfoEvent(page = self)
673            wx.PostEvent(self.parent, event) 
674     
675               
676    def _onparamEnter(self,event):
677        """
678            when enter value on panel redraw model according to changed
679        """
680        flag = False
681        tcrtl= event.GetEventObject()
682
683        #Clear msg if previously shown.
684        msg= ""
685        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
686
687        if check_float(tcrtl):
688            flag = self._onparamEnter_helper()
689            if flag:
690                temp_smearer = None
691                if self.enable_smearer.GetValue():
692                    temp_smearer= self.smearer
693                self.compute_chisqr(smearer= temp_smearer)
694   
695                ## new state posted
696                if self.state_change:
697                    #self._undo.Enable(True)
698                    event = PageInfoEvent(page = self)
699                    wx.PostEvent(self.parent, event)
700                self.state_change= False
701            self.save_current_state()
702        else:
703            self.save_current_state()
704            msg= "Cannot Plot :Must enter a number!!!  "
705            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
706            return 
707       
708
709    def _onparamRangeEnter(self, event):
710        """
711            Check validity of value enter in the parameters range field
712        """
713        if self.check_invalid_panel():
714            return
715        tcrtl= event.GetEventObject()
716        #Clear msg if previously shown.
717        msg= ""
718        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
719        # Flag to register when a parameter has changed.
720        is_modified = False
721        if tcrtl.GetValue().lstrip().rstrip()!="":
722            try:
723                value = float(tcrtl.GetValue())
724                tcrtl.SetBackgroundColour(wx.WHITE)
725                self._check_value_enter(self.fittable_param ,is_modified)
726                self._check_value_enter(self.parameters ,is_modified) 
727            except:
728                tcrtl.SetBackgroundColour("pink")
729                msg= "Model Error:wrong value entered : %s"% sys.exc_value
730                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
731                return 
732        else:
733           tcrtl.SetBackgroundColour(wx.WHITE)
734           
735        #self._undo.Enable(True)
736        self.save_current_state()
737        event = PageInfoEvent(page = self)
738        wx.PostEvent(self.parent, event)
739        self.state_change= False
740
741                   
742    def _onQrangeEnter(self, event):
743        """
744            Check validity of value enter in the Q range field
745        """
746        if self.check_invalid_panel():
747            return
748        tcrtl= event.GetEventObject()
749        #Clear msg if previously shown.
750        msg= ""
751        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
752        # Flag to register when a parameter has changed.
753        is_modified = False
754        if tcrtl.GetValue().lstrip().rstrip()!="":
755            try:
756                value = float(tcrtl.GetValue())
757                tcrtl.SetBackgroundColour(wx.WHITE)
758
759                # If qmin and qmax have been modified, update qmin and qmax
760                if self._validate_qrange( self.qmin, self.qmax):
761                    tempmin = float(self.qmin.GetValue())
762                    if tempmin != self.qmin_x:
763                        self.qmin_x = tempmin
764                    tempmax = float(self.qmax.GetValue())
765                    if tempmax != self.qmax_x:
766                        self.qmax_x = tempmax
767                else:
768                    tcrtl.SetBackgroundColour("pink")
769                    msg= "Model Error:wrong value entered : %s"% sys.exc_value
770                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
771                    return 
772               
773            except:
774                tcrtl.SetBackgroundColour("pink")
775                msg= "Model Error:wrong value entered : %s"% sys.exc_value
776                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
777                return 
778            #Check if # of points for theory model are valid(>0).
779            if self.npts != None:
780                if check_float(self.npts):
781                    temp_npts = float(self.npts.GetValue())
782                    if temp_npts !=  self.num_points:
783                        self.num_points = temp_npts
784                        is_modified = True
785                else:
786                    msg= "Cannot Plot :No npts in that Qrange!!!  "
787                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
788           
789        else:
790           tcrtl.SetBackgroundColour("pink")
791           msg= "Model Error:wrong value entered!!!"
792           wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
793       
794        self.compute_chisqr()   
795        #self._undo.Enable(True)
796        self.save_current_state()
797        event = PageInfoEvent(page = self)
798        wx.PostEvent(self.parent, event)
799        self.state_change= False
800        self._draw_model()
801       
802    def _clear_Err_on_Fit(self):
803        """
804            hide the error text control shown
805            after fitting
806        """
807       
808        if hasattr(self,"text2_3"):
809            self.text2_3.Hide()
810
811        if len(self.parameters)>0:
812            for item in self.parameters:
813                #Skip t ifhe angle parameters if 1D data
814                if self.data.__class__.__name__ !="Data2D":
815                    if item in self.orientation_params:
816                        continue
817                if item in self.param_toFit:
818                    continue
819                ## hide statictext +/-   
820                if item[3]!=None and item[3].IsShown():
821                    item[3].Hide()
822                ## hide textcrtl  for error after fit
823                if item[4]!=None and item[4].IsShown():                   
824                    item[4].Hide()
825 
826        if len(self.fittable_param)>0:
827            for item in self.fittable_param:
828                #Skip t ifhe angle parameters if 1D data
829                if self.data.__class__.__name__ !="Data2D":
830                    if item in self.orientation_params:
831                        continue
832                if item in self.param_toFit:
833                    continue
834                ## hide statictext +/-   
835                if item[3]!=None and item[3].IsShown():
836                    item[3].Hide()
837                ## hide textcrtl  for error after fit
838                if item[4]!=None and item[4].IsShown():
839                    item[4].Hide()
840        return       
841               
842       
843    def set_data(self, data):
844        """
845            reset the current data
846        """
847        self.data = data
848        if self.data is None:
849            data_min = ""
850            data_max = ""
851            data_name = ""
852            self.formfactorbox.Disable()
853            self.structurebox.Disable()
854        else:
855            self.formfactorbox.Enable()
856            self.structurebox.Enable()
857            data_name = self.data.name
858            #set maximum range for x in linear scale
859            if not hasattr(self.data,"data"): #Display only for 1D data fit
860                # Minimum value of data   
861                data_min = min(self.data.x)
862                # Maximum value of data 
863                data_max = max(self.data.x)
864            else:
865                ## Minimum value of data
866                data_min = 0
867                x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
868                y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
869                ## Maximum value of data 
870                data_max = math.sqrt(x*x + y*y)
871       
872        self.dataSource.SetValue(data_name)
873        self.qmin_x = data_min
874        self.qmax_x = data_max
875        self.minimum_q.SetValue(str(data_min))
876        self.maximum_q.SetValue(str(data_max))
877        self.qmin.SetValue(str(data_min))
878        self.qmax.SetValue(str(data_max))
879        self.qmin.SetBackgroundColour("white")
880        self.qmax.SetBackgroundColour("white")
881        self.state.data = data
882        self.state.qmin = self.qmin_x
883        self.state.qmax = self.qmax_x
884       
885       
886    def reset_page(self, state,first=False):
887        """
888            reset the state
889        """
890        self.reset_page_helper(state)
891        import sans.guiframe.gui_manager
892        evt = ModelEventbox(model=state.model)
893        wx.PostEvent(self.event_owner, evt) 
894   
895        if self.engine_type != None:
896            self.manager._on_change_engine(engine=self.engine_type)
897
898        self.select_param(event = None) 
899        #Save state_fit
900        self.save_current_state_fit()
901        self._lay_out()
902        self.Refresh()
903       
904    def get_range(self):
905        """
906            return the fitting range
907        """
908        return float(self.qmin_x) , float(self.qmax_x)
909   
910    def get_npts2fit(self):
911        """
912            return numbers of data points within qrange
913            Note: This is for Park where chi2 is not normalized by Npts of fit
914        """
915        npts2fit = 0
916        qmin,qmax = self.get_range()
917        if self.data.__class__.__name__ =="Data2D":
918            for qx in self.data.x_bins:
919                for qy in self.data.y_bins:
920                   if math.sqrt((qx*qx)+(qy*qy)) >= qmin \
921                         and math.sqrt((qx*qx)+(qy*qy)) <= qmax:
922                       npts2fit += 1
923        else:
924            for qx in self.data.x:
925                   if qx >= qmin and qx <= qmax:
926                       npts2fit += 1
927        return npts2fit
928
929
930    def get_chi2(self):
931        """
932            return the current chi2
933        """
934        return self.tcChi.GetLabel()
935       
936    def get_param_list(self):
937        """
938            @return self.param_toFit: list containing  references to TextCtrl
939            checked.Theses TextCtrl will allow reference to parameters to fit.
940            @raise: if return an empty list of parameter fit will nnote work
941            properly so raise ValueError,"missing parameter to fit"
942        """
943        if self.param_toFit !=[]:
944            return self.param_toFit
945        else:
946            raise ValueError,"missing parameter to fit"   
947     
948    def onsetValues(self,chisqr,p_name, out,cov):
949        """
950            Build the panel from the fit result
951            @param chisqr:Value of the goodness of fit metric
952            @p_name: the name of parameters
953            @param out:list of parameter with the best value found during fitting
954            @param cov:Covariance matrix
955       
956        """
957        if out == None or not numpy.isfinite(chisqr):
958            raise ValueError,"Fit error occured..." 
959       
960        is_modified = False
961        has_error = False   
962       
963        #Hide textctrl boxes of errors.
964        self._clear_Err_on_Fit()   
965       
966        #Check if chi2 is finite
967        if chisqr != None or numpy.isfinite(chisqr):
968        #format chi2
969            npt_fit = float(self.get_npts2fit())   
970            if self.engine_type == "park" and npt_fit > 0:   
971                chisqr =chisqr/npt_fit   
972            chi2 = format_number(chisqr)   
973            self.tcChi.SetLabel(chi2)   
974            self.tcChi.Refresh()   
975        else:
976            self.tcChi.SetLabel("-")
977       
978        #Hide error title
979        if self.text2_3.IsShown():
980            self.text2_3.Hide()
981     
982        try:
983            n = self.disp_box.GetCurrentSelection()
984            dispersity= self.disp_box.GetClientData(n)
985            if dispersity !=None and self.enable_disp.GetValue():
986                name= dispersity.__name__
987                if name == "GaussianDispersion":
988                    if hasattr(self,"text_disp_1" ):
989                        if self.text_disp_1 !=None:
990                            self.text_disp_1.Hide()
991        except:
992            dispersty = None
993            pass
994        #set the panel when fit result are float not list
995        if out.__class__== numpy.float64:
996            self.param_toFit[0][2].SetValue(format_number(out))
997           
998            if self.param_toFit[0][4].IsShown:
999                self.param_toFit[0][4].Hide()
1000            if cov !=None :
1001                self.text2_3.Show(True)
1002                try:
1003                    if dispersity !=None:
1004                        name= dispersity.__name__
1005                        if name == "GaussianDispersion" and self.enable_disp.GetValue():
1006                            if hasattr(self,"text_disp_1" ):
1007                                if self.text_disp_1 !=None:
1008                                    self.text_disp_1.Show(True)
1009                except:
1010                    pass
1011
1012                if cov[0]==None or  not numpy.isfinite(cov[0]): 
1013                    if self.param_toFit[0][3].IsShown:
1014                        self.param_toFit[0][3].Hide()
1015                else:                   
1016                    self.param_toFit[0][3].Show(True)               
1017                    self.param_toFit[0][4].Show(True)
1018                    self.param_toFit[0][4].SetValue(format_number(cov[0]))
1019                    has_error = True
1020        else:
1021
1022            i = 0
1023            #Set the panel when fit result are list
1024            for item in self.param_toFit:     
1025                if len(item)>5 and item != None:     
1026                    ## reset error value to initial state
1027                    item[3].Hide()
1028                    item[4].Hide()
1029                   
1030                    for ind in range(len(out)):
1031                       
1032                        if item[1] == p_name[ind]:
1033                            break       
1034                    if len(out)<=len(self.param_toFit) and out[ind] !=None:   
1035                        val_out = format_number(out[ind])                 
1036                        item[2].SetValue(val_out)
1037
1038                    if(cov !=None):
1039                       
1040                        try:
1041                            if dispersity !=None:
1042                                name= dispersity.__name__
1043                                if name == "GaussianDispersion" and self.enable_disp.GetValue():
1044                                    if hasattr(self,"text_disp_1" ):
1045                                        if self.text_disp_1!=None:
1046                                            if not self.text_disp_1.IsShown():
1047                                                self.text_disp_1.Show(True)
1048                        except:
1049                            pass   
1050                   
1051                        if cov[ind]!=None :
1052                            if numpy.isfinite(float(cov[ind])):
1053                                val_err = format_number(cov[ind])
1054                                item[3].Show(True)
1055                                item[4].Show(True)
1056                                item[4].SetValue(val_err)
1057
1058                                has_error = True
1059                    i += 1         
1060        #Show error title when any errors displayed
1061        if has_error: 
1062            if not self.text2_3.IsShown():
1063                self.text2_3.Show(True) 
1064               
1065        ## save current state 
1066        self.save_current_state()         
1067        #plot model
1068        self._draw_model()   
1069        self._lay_out()     
1070        #PostStatusEvent     
1071        msg = "Fit completed! "
1072        wx.PostEvent(self.manager.parent, StatusEvent(status=msg))
1073     
1074
1075    def onSmear(self, event):
1076        """
1077            Create a smear object that will change the way residuals
1078            are compute when fitting
1079        """
1080        if self.check_invalid_panel():
1081            return
1082        if self.model ==None:
1083            msg="Need model and data to smear plot"
1084            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1085                            "Smear: %s"%msg))
1086            return
1087        temp_smearer = None
1088        if self.enable_smearer.GetValue():
1089            temp_smearer= self.smearer
1090            if hasattr(self.data,"dxl"):
1091                msg= ": Resolution smearing parameters"
1092            if hasattr(self.data,"dxw"):
1093                msg= ": Slit smearing parameters"
1094            if self.smearer ==None:
1095                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1096                            "Data contains no smearing information"))
1097            else:
1098                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1099                            "Data contains smearing information %s"%msg))
1100       
1101        ## set smearing value whether or not the data contain the smearing info
1102        self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
1103                                     qmax= float(self.qmax_x)) 
1104        ##Calculate chi2
1105        self.compute_chisqr(smearer= temp_smearer) 
1106       
1107        self.state.enable_smearer=  self.enable_smearer.GetValue()
1108        self.state.disable_smearer=self.disable_smearer.GetValue()
1109   
1110    def complete_chisqr(self, output, elapsed=None): 
1111        """
1112            print result chisqr
1113        """
1114        try:
1115            if output ==None:
1116                output= "-"
1117
1118            self.tcChi.SetLabel(str(format_number(output)))
1119
1120            self.state.tcChi =self.tcChi
1121         
1122        except:
1123            pass
1124       
1125       
1126    def compute_chisqr1D(self, smearer=None):
1127        """
1128            Compute chisqr for 1D
1129        """
1130        try:
1131            self.qmin_x = float(self.qmin.GetValue())
1132            self.qmax_x = float(self.qmax.GetValue())
1133            ##return residuals within self.qmin_x and self.qmax_x
1134            from gui_thread import CalcChisqr1D
1135            ## If a thread is already started, stop it
1136            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1137                self.calc_Chisqr.stop()
1138               
1139            self.calc_Chisqr= CalcChisqr1D( data1d= self.data,
1140                                            model= self.model,
1141                                            smearer=smearer,
1142                                            qmin=self.qmin_x,
1143                                            qmax=self.qmax_x,
1144                                            completefn = self.complete_chisqr,
1145                                            updatefn   = None)
1146   
1147            self.calc_Chisqr.queue()
1148           
1149        except:
1150            raise ValueError," Could not compute Chisqr for %s Model 2D: "%self.model.name
1151           
1152           
1153   
1154       
1155       
1156    def compute_chisqr2D(self):
1157        """
1158            compute chi square given a model and data 2D and set the value
1159            to the tcChi txtcrl
1160        """
1161        try:
1162            self.qmin_x = float(self.qmin.GetValue())
1163            self.qmax_x = float(self.qmax.GetValue())
1164           
1165            ##return residuals within self.qmin_x and self.qmax_x
1166            from gui_thread import CalcChisqr2D
1167            ## If a thread is already started, stop it
1168            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1169                self.calc_Chisqr.stop()
1170           
1171            self.calc_Chisqr= CalcChisqr2D( data2d= self.data,
1172                                            model= self.model,
1173                                            qmin= self.qmin_x,
1174                                            qmax = self.qmax_x,
1175                                            completefn = self.complete_chisqr,
1176                                            updatefn   = None)
1177   
1178            self.calc_Chisqr.queue()
1179         
1180        except:
1181           raise
1182
1183       
1184    def compute_chisqr(self , smearer=None):
1185        """
1186            compute chi square given a model and data 1D and set the value
1187            to the tcChi txtcrl
1188        """
1189        flag = self._validate_qrange( self.qmin, self.qmax)
1190        if flag== True:
1191            try:
1192                if hasattr(self.data,"data"):
1193                    self.compute_chisqr2D()
1194                    return
1195                else:
1196                    self.compute_chisqr1D(smearer=smearer)
1197                    return
1198            except:
1199                wx.PostEvent(self.parent.parent, StatusEvent(status=\
1200                            "Chisqr Error: %s"% sys.exc_value))
1201                return 
1202           
1203   
1204    def select_all_param(self,event): 
1205        """
1206             set to true or false all checkBox given the main checkbox value cb1
1207        """           
1208
1209        self.param_toFit=[]
1210        if  self.parameters !=[]:
1211            if  self.cb1.GetValue():
1212                for item in self.parameters:
1213                    ## for data2D select all to fit
1214                    if self.data.__class__.__name__=="Data2D":
1215                        item[0].SetValue(True)
1216                        self.param_toFit.append(item )
1217                    else:
1218                        ## for 1D all parameters except orientation
1219                        if not item in self.orientation_params:
1220                            item[0].SetValue(True)
1221                            self.param_toFit.append(item )
1222                #if len(self.fittable_param)>0:
1223                for item in self.fittable_param:
1224                    if self.data.__class__.__name__=="Data2D":
1225                        item[0].SetValue(True)
1226                        self.param_toFit.append(item )
1227                    else:
1228                        ## for 1D all parameters except orientation
1229                        if not item in self.orientation_params_disp:
1230                            item[0].SetValue(True)
1231                            self.param_toFit.append(item )
1232            else:
1233                for item in self.parameters:
1234                    item[0].SetValue(False)
1235                for item in self.fittable_param:
1236                    item[0].SetValue(False)
1237                self.param_toFit=[]
1238           
1239        self.save_current_state_fit() 
1240       
1241        if event !=None:
1242            #self._undo.Enable(True)
1243            ## post state to fit panel
1244            event = PageInfoEvent(page = self)
1245            wx.PostEvent(self.parent, event) 
1246     
1247               
1248               
1249    def select_param(self,event):
1250        """
1251            Select TextCtrl  checked for fitting purpose and stores them
1252            in  self.param_toFit=[] list
1253        """
1254        self.param_toFit=[]
1255        for item in self.parameters:
1256            #Skip t ifhe angle parameters if 1D data
1257            if self.data.__class__.__name__ !="Data2D":
1258                if item in self.orientation_params:
1259                    continue
1260            #Select parameters to fit for list of primary parameters
1261            if item[0].GetValue():
1262                if not (item in self.param_toFit):
1263                    self.param_toFit.append(item ) 
1264            else:
1265                #remove parameters from the fitting list
1266                if item in self.param_toFit:
1267                    self.param_toFit.remove(item)
1268
1269        #Select parameters to fit for list of fittable parameters with dispersion         
1270        for item in self.fittable_param:
1271            #Skip t ifhe angle parameters if 1D data
1272            if self.data.__class__.__name__ !="Data2D":
1273                if item in self.orientation_params:
1274                    continue
1275            if item[0].GetValue():
1276                if not (item in self.param_toFit):
1277                    self.param_toFit.append(item) 
1278            else:
1279                #remove parameters from the fitting list
1280                if item in self.param_toFit:
1281                    self.param_toFit.remove(item)
1282
1283        #Calculate num. of angle parameters
1284        if self.data.__class__.__name__ =="Data2D": 
1285            len_orient_para = 0
1286        else:
1287            len_orient_para = len(self.orientation_params)  #assume even len
1288        #Total num. of angle parameters
1289        if len(self.fittable_param) > 0:
1290            len_orient_para *= 2
1291        #Set the value of checkbox that selected every checkbox or not           
1292        if len(self.parameters)+len(self.fittable_param)-len_orient_para ==len(self.param_toFit):
1293            self.cb1.SetValue(True)
1294        else:
1295            self.cb1.SetValue(False)
1296        self.save_current_state_fit()
1297        if event !=None:
1298            #self._undo.Enable(True)
1299            ## post state to fit panel
1300            event = PageInfoEvent(page = self)
1301            wx.PostEvent(self.parent, event) 
1302     
1303   
1304       
1305    def set_model_param_sizer(self, model):
1306        """
1307            Build the panel from the model content
1308            @param model: the model selected in combo box for fitting purpose
1309        """
1310        self.sizer3.Clear(True)
1311        self.parameters = []
1312        self.param_toFit=[]
1313        self.fittable_param=[]
1314        self.fixed_param=[]
1315        self.orientation_params=[]
1316        self.orientation_params_disp=[]
1317       
1318        if model ==None:
1319            self.sizer3.Layout()
1320            self.SetScrollbars(20,20,25,65)
1321            return
1322        ## the panel is drawn using the current value of the fit engine
1323        if self.engine_type==None and self.manager !=None:
1324            self.engine_type= self.manager._return_engine_type()
1325
1326           
1327        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
1328        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1329        sizer = wx.GridBagSizer(5,5)
1330        ## save the current model
1331        self.model = model
1332           
1333        keys = self.model.getParamList()
1334        #list of dispersion paramaters
1335        self.disp_list=self.model.getDispParamList()
1336
1337        keys.sort()
1338   
1339        iy = 0
1340        ix = 0
1341        select_text = "Uncheck all to fix"
1342        self.cb1 = wx.CheckBox(self, -1,str(select_text), (10, 10))
1343        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
1344        self.cb1.SetValue(True)
1345       
1346        sizer.Add(self.cb1,(iy, ix),(1,1),\
1347                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1348        ix +=1
1349        self.text2_2 = wx.StaticText(self, -1, 'Values')
1350        sizer.Add(self.text2_2,(iy, ix),(1,1),\
1351                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1352        ix +=2 
1353        self.text2_3 = wx.StaticText(self, -1, 'Errors')
1354        sizer.Add(self.text2_3,(iy, ix),(1,1),\
1355                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1356        self.text2_3.Hide()
1357        ix +=1 
1358        self.text2_min = wx.StaticText(self, -1, 'Min')
1359        sizer.Add(self.text2_min,(iy, ix),(1,1),\
1360                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1361        self.text2_min.Hide()
1362        ix +=1 
1363        self.text2_max = wx.StaticText(self, -1, 'Max')
1364        sizer.Add(self.text2_max,(iy, ix),(1,1),\
1365                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1366        self.text2_max.Hide()
1367        ix += 1
1368        self.text2_4 = wx.StaticText(self, -1, '[Units]')
1369        sizer.Add(self.text2_4,(iy, ix),(1,1),\
1370                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1371        self.text2_4.Hide()
1372        if self.engine_type=="park":
1373            self.text2_max.Show(True)
1374            self.text2_min.Show(True)
1375       
1376        for item in keys:
1377            if not item in self.disp_list and not item in self.model.orientation_params:
1378               
1379                ##prepare a spot to store errors
1380                if not self.model.details.has_key(item):
1381                    self.model.details [item] = ["",None,None] 
1382         
1383                iy += 1
1384                ix = 0
1385                ## add parameters name with checkbox for selecting to fit
1386                cb = wx.CheckBox(self, -1, item )
1387                cb.SetValue(True)
1388                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
1389                sizer.Add( cb,( iy, ix),(1,1),
1390                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1391               
1392                ## add parameter value
1393                ix += 1
1394                value= self.model.getParam(item)
1395                ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
1396                                    style=wx.TE_PROCESS_ENTER)
1397               
1398                ctl1.SetValue(format_number(value))
1399                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
1400                ## text to show error sign
1401                ix += 1
1402                text2=wx.StaticText(self, -1, '+/-')
1403                sizer.Add(text2,(iy, ix),(1,1),\
1404                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1405                text2.Hide() 
1406                ix += 1
1407                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
1408                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1409                ctl2.Hide()
1410               
1411                ix += 1
1412                ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1413                                               kill_focus_callback = self._onparamRangeEnter,
1414                                               text_enter_callback = self._onparamRangeEnter)
1415     
1416                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1417                ctl3.Hide()
1418       
1419                ix += 1
1420                ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1421                                               kill_focus_callback = self._onparamRangeEnter,
1422                                               text_enter_callback = self._onparamRangeEnter)
1423                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1424     
1425                ctl4.Hide()
1426
1427                if self.engine_type=="park":
1428                    ctl3.Show(True)
1429                    ctl4.Show(True)
1430                ix +=1
1431                # Units
1432                if self.model.details.has_key(item):
1433                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
1434                else:
1435                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
1436                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1437                   
1438                ##[cb state, name, value, "+/-", error of fit, min, max , units]
1439                self.parameters.append([cb,item, ctl1,
1440                                        text2,ctl2, ctl3, ctl4,units])
1441             
1442        iy+=1
1443        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1444       
1445        # type can be either Guassian or Array
1446        if len(self.model.dispersion.values())>0:
1447            type= self.model.dispersion.values()[0]["type"]
1448        else:
1449            type = "Gaussian"
1450           
1451        iy += 1
1452        ix = 0
1453        #Add tile for orientational angle
1454        for item in keys:
1455            if item in self.model.orientation_params:       
1456                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
1457                sizer.Add(orient_angle,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
1458                if not self.data.__class__.__name__ =="Data2D":
1459                    orient_angle.Hide()
1460                else:
1461                    orient_angle.Show(True)
1462                break
1463     
1464        #For Gaussian only
1465        if type.lower() != "array":
1466            for item in self.model.orientation_params:
1467                if not item in self.disp_list:
1468                    ##prepare a spot to store min max
1469                    if not self.model.details.has_key(item):
1470                        self.model.details [item] = ["",None,None] 
1471                         
1472                    iy += 1
1473                    ix = 0
1474                    ## add parameters name with checkbox for selecting to fit
1475                    cb = wx.CheckBox(self, -1, item )
1476                    cb.SetValue(False)
1477                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
1478                    if self.data.__class__.__name__ =="Data2D":
1479                        cb.Show(True)
1480                    else:
1481                        cb.Hide()
1482                    sizer.Add( cb,( iy, ix),(1,1),
1483                                 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1484   
1485                    ## add parameter value
1486                    ix += 1
1487                    value= self.model.getParam(item)
1488                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
1489                                        style=wx.TE_PROCESS_ENTER)
1490                   
1491                    ctl1.SetValue(format_number(value))
1492                    if self.data.__class__.__name__ =="Data2D":
1493                        ctl1.Show(True)
1494                    else:
1495                        ctl1.Hide()
1496                    sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
1497                    ## text to show error sign
1498                    ix += 1
1499                    text2=wx.StaticText(self, -1, '+/-')
1500                    sizer.Add(text2,(iy, ix),(1,1),\
1501                                    wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1502                    text2.Hide() 
1503                    ix += 1
1504                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
1505                   
1506                    sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1507                    ctl2.Hide()
1508                   
1509                   
1510                    ix += 1
1511                    ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1512                                                   kill_focus_callback = self._onparamRangeEnter,
1513                                                   text_enter_callback = self._onparamRangeEnter)
1514               
1515                    sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1516                    ctl3.Hide()
1517                 
1518                    ix += 1
1519                    ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1520                                                   kill_focus_callback = self._onparamRangeEnter,
1521                                                   text_enter_callback = self._onparamRangeEnter)
1522                    sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1523                   
1524                    ctl4.Hide()
1525                   
1526                    if self.engine_type =="park" and self.data.__class__.__name__ =="Data2D":                     
1527                        ctl3.Show(True)
1528                        ctl4.Show(True)
1529                   
1530                    ix +=1
1531                    # Units
1532                    if self.model.details.has_key(item):
1533                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
1534                    else:
1535                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
1536                    if self.data.__class__.__name__ =="Data2D":
1537                        units.Show(True)
1538                   
1539                    else:
1540                        units.Hide()
1541                   
1542                    sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1543                                         
1544                    ##[cb state, name, value, "+/-", error of fit, min, max , units]
1545                    self.parameters.append([cb,item, ctl1,
1546                                            text2,ctl2, ctl3, ctl4,units])
1547                    self.orientation_params.append([cb,item, ctl1,
1548                                            text2,ctl2, ctl3, ctl4,units])
1549             
1550        iy+=1
1551       
1552        #Display units text on panel
1553        for item in keys:   
1554            if self.model.details.has_key(item):
1555                self.text2_4.Show()
1556        #Fill the list of fittable parameters
1557        self.select_all_param(event=None)
1558
1559        self.save_current_state_fit()
1560        boxsizer1.Add(sizer)
1561        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1562        self.sizer3.Layout()
1563        self.Layout()
1564        self.Refresh()
1565        self.SetScrollbars(20,20,25,65)
1566
1567
1568       
1569class HelpWindow(wx.Frame):
1570    def __init__(self, parent, id, title):
1571        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
1572       
1573        from sans.models.CylinderModel import CylinderModel
1574        model = CylinderModel()
1575       
1576        from danse.common.plottools.plottables import Data1D
1577        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
1578   
1579        from fitpanel import PageInfo
1580        myinfo = PageInfo(self,  model, data=data )
1581       
1582        ## add data
1583       
1584        from models import ModelList
1585        mylist= ModelList()
1586
1587        from sans.models.SphereModel import SphereModel
1588        from sans.models.SquareWellStructure import SquareWellStructure
1589        from sans.models.DebyeModel import DebyeModel
1590        from sans.models.LineModel import LineModel
1591        name= "shapes"
1592        list1= [SphereModel]
1593        mylist.set_list( name, list1)
1594       
1595        name= "Shape-independent"
1596        list1= [DebyeModel]
1597        mylist.set_list( name, list1)
1598       
1599        name= "Structure Factors"
1600        list1= [SquareWellStructure]
1601        mylist.set_list( name, list1)
1602       
1603        name= "Added models"
1604        list1= [LineModel]
1605        mylist.set_list( name, list1)
1606       
1607        myinfo.model_list_box = mylist.get_list()
1608       
1609        self.page = FitPage(self, myinfo) 
1610       
1611        self.Centre()
1612        self.Show(True)
1613 
1614if __name__=="__main__":
1615    app = wx.App()
1616    HelpWindow(None, -1, 'HelpWindow')
1617    app.MainLoop()
1618               
Note: See TracBrowser for help on using the repository browser.