source: sasview/sansview/perspectives/fitting/fitpage.py @ 918fcb1

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 918fcb1 was 66c488b, checked in by Jae Cho <jhjcho@…>, 15 years ago

Corrected autoupdate of plots after qrange changed

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