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

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

found and fixed minor bugs: 1)remaining unchanged the smearer option checked if already checked on the empty fit panel before data for fitting selected, 2) Error on resetting the page from bookmark

  • Property mode set to 100644
File size: 90.5 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
11from DataLoader.data_info import Data1D
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
23SMEAR_SIZE_L = 0.005
24SMEAR_SIZE_H = 0.01
25
26import basepage
27from basepage import BasicPage
28from basepage import PageInfoEvent
29from DataLoader.qsmearing import smear_selection
30
31class FitPage(BasicPage):
32    """
33        FitPanel class contains fields allowing to display results when
34        fitting  a model and one data
35        @note: For Fit to be performed the user should check at least one parameter
36        on fit Panel window.
37 
38    """
39   
40    def __init__(self,parent, page_info):
41        BasicPage.__init__(self, parent, page_info)
42
43        """
44            Initialization of the Panel
45        """
46        ## fit page does not content npts txtcrtl
47        self.npts=None
48        ## thread for compute Chisqr
49        self.calc_Chisqr=None
50        ## default fitengine type
51        self.engine_type = None
52        ## smear default
53        self.smearer = None
54        self.current_smearer = None
55        self.dxl = None
56        self.dxw = None
57        self.dx_min = None
58        self.dx_max = None
59       
60        ## draw sizer
61        self._fill_datainfo_sizer()
62       
63        # get smear info from data
64        self._get_smear_info()
65       
66        self._fill_model_sizer( self.sizer1)
67       
68        self._get_defult_custom_smear()
69       
70        self._fill_range_sizer() 
71       
72        if self.data is None:
73            self.formfactorbox.Disable()
74            self.structurebox.Disable()
75        else:
76            self.smearer = smear_selection( self.data )
77            if self.smearer ==None:
78                self.enable_smearer.Disable()
79                #self.disable_smearer.Disable()
80
81        self.disp_cb_dict = {}
82        ## to update the panel according to the fit engine type selected
83        self.Bind(EVT_FITTER_TYPE,self._on_engine_change)
84        self.Bind(EVT_FIT_STOP,self._on_fit_complete)
85       
86
87    def _on_fit_complete(self, event):
88        """
89            When fit is complete ,reset the fit button label.
90        """
91        #self.btFit.SetLabel("Fit")
92        #self.btFit.Unbind(event=wx.EVT_BUTTON, id=self.btFit.GetId())
93        #self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._onFit,id=self.btFit.GetId())
94        pass
95       
96       
97    def _on_engine_change(self, event):
98        """
99            get an event containing the current name of the fit engine type
100            @param event: FitterTypeEvent containing  the name of the current engine
101        """
102        self.engine_type = event.type
103        if len(self.parameters)==0:
104            self.Layout()
105            return
106        if event.type =="park":
107            self.btFit.SetLabel("Fit")
108
109        for item in self.parameters:
110            if event.type =="scipy" :
111                item[5].SetValue("")
112                item[5].Hide()
113                item[6].SetValue("")
114                item[6].Hide()
115                self.text2_min.Hide()
116                self.text2_max.Hide()
117
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        for item in self.fittable_param:
124            if item[5]!=None and item[6]!=None and not item in self.orientation_params_disp:
125                if event.type =="scipy" and not item in self.orientation_params:
126                    item[5].SetValue("")
127                    item[5].Hide()
128                    item[6].SetValue("")
129                    item[6].Hide()
130                    self.text2_min.Hide()
131                    self.text2_max.Hide()
132                    self.text_disp_min.Hide()
133                    self.text_disp_max.Hide()
134                else:
135                    item[5].Show(True)
136                    item[6].Show(True)
137                    self.text2_min.Show(True)
138                    self.text2_max.Show(True)
139                    self.text_disp_min.Show(True)
140                    self.text_disp_max.Show(True)
141           
142        for item in self.orientation_params:
143            if item[5]!=None and item[6]!=None:
144                if event.type =="scipy" or self.data.__class__.__name__ !="Data2D":
145                    item[5].SetValue("")
146                    item[5].Hide()
147                    item[6].SetValue("")
148                    item[6].Hide()
149                else:
150                    item[5].Show(True)
151                    item[6].Show(True)
152                   
153        for item in self.orientation_params_disp:         
154            if item[5]!=None and item[6]!=None:
155                if event.type =="scipy" or self.data.__class__.__name__ !="Data2D":
156                    item[5].SetValue("")
157                    item[5].Hide()
158                    item[6].SetValue("")
159                    item[6].Hide()
160                else:
161                    item[5].Show(True)
162                    item[6].Show(True)
163        self.Layout()
164        self.Refresh()
165
166    def _fill_range_sizer(self):
167        """
168            Fill the sizer containing the plotting range
169            add  access to npts
170        """
171        title = "Fitting"
172        #smear messages & titles
173        smear_message_none  =  "No smearing is selected..."
174        smear_message_dqdata  =  "The dQ data is being used for smearing..."
175        smear_message_2d  =  "No smearing is supported for 2D model fitting..."
176        smear_message_new_ssmear  =  "Please enter only the value of interest to customize smearing..."
177        smear_message_new_psmear  =  "Please enter both; the dQ will be generated by interpolation..."
178        smear_message_pinhole_min_title = "dQ_min[1/A]:"
179        smear_message_pinhole_max_title = "dQ_max[1/A]:"
180        smear_message_slit_height_title = "Slit height[1/A]:"
181        smear_message_slit_width_title = "Slit width[1/A]:"
182       
183        self._get_smear_info()
184
185        box_description_range = wx.StaticBox(self, -1,str(title))
186        boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL)
187
188        sizer_fit = wx.GridSizer(1, 1,0, 0)
189   
190        self.btFit = wx.Button(self,wx.NewId(),'Fit', size=(80,23))
191        self.btFit.Bind(wx.EVT_BUTTON, self._onFit,id= self.btFit.GetId())
192        self.btFit.SetToolTipString("Perform fit.")
193     
194       
195
196        self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL)
197        sizer_smearer = wx.BoxSizer(wx.HORIZONTAL)
198        self.sizer_new_smear= wx.BoxSizer(wx.HORIZONTAL)
199        self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL)
200        sizer_chi2 = wx.BoxSizer(wx.VERTICAL)
201        smear_set_box= wx.StaticBox(self, -1,'Set Instrumental Smearing')
202        sizer_smearer_box = wx.StaticBoxSizer(smear_set_box, wx.HORIZONTAL)
203        sizer_smearer_box.SetMinSize((_DATA_BOX_WIDTH,85))
204       
205        #textcntrl for new resolution
206        self.smear_pinhole_max = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH-20,20),style=wx.TE_PROCESS_ENTER,
207                                            text_enter_callback = self.onPinholeSmear)
208        self.smear_pinhole_min = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH-20,20),style=wx.TE_PROCESS_ENTER,
209                                            text_enter_callback = self.onPinholeSmear)
210        self.smear_slit_height= self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH-20,20),style=wx.TE_PROCESS_ENTER,
211                                            text_enter_callback = self.onSlitSmear)
212        self.smear_slit_width = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH-20,20),style=wx.TE_PROCESS_ENTER,
213                                            text_enter_callback = self.onSlitSmear)
214        self.smear_data_left= BGTextCtrl(self, -1, size=(_BOX_WIDTH-20,20), style=0)
215        self.smear_data_left.SetValue(str(self.dq_l))
216        self.smear_data_right = BGTextCtrl(self, -1, size=(_BOX_WIDTH-20,20), style=0)
217        self.smear_data_right.SetValue(str(self.dq_r))
218
219        #set default values
220        self.smear_pinhole_max.SetValue(str(self.dx_max))
221        self.smear_pinhole_min.SetValue(str(self.dx_min))
222        self.smear_slit_height.SetValue(str(self.dxl))
223        self.smear_slit_width.SetValue(str(self.dxw))
224
225        #Filling the sizer containing instruments smearing info.
226        self.disable_smearer = wx.RadioButton(self, -1, 'None', style=wx.RB_GROUP)
227        self.enable_smearer = wx.RadioButton(self, -1, 'Use dQ Data')
228        #self.enable_smearer.SetToolTipString("Click to use the loaded dQ data for smearing.")
229        self.pinhole_smearer = wx.RadioButton(self, -1, 'Custom Pinhole Smear')
230        #self.pinhole_smearer.SetToolTipString("Click to input custom resolution for pinhole smearing.")
231        self.slit_smearer = wx.RadioButton(self, -1, 'Custom Slit Smear')
232        #self.slit_smearer.SetToolTipString("Click to input custom resolution for slit smearing.")
233        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId())
234        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId())
235        self.Bind(wx.EVT_RADIOBUTTON, self.onPinholeSmear, id=self.pinhole_smearer.GetId())
236        self.Bind(wx.EVT_RADIOBUTTON, self.onSlitSmear, id=self.slit_smearer.GetId())
237        self.disable_smearer.SetValue(True)
238       
239        # add 4 types of smearing to the sizer
240        sizer_smearer.Add( self.disable_smearer,0, wx.LEFT, 10)
241        sizer_smearer.Add((10,10))
242        sizer_smearer.Add( self.enable_smearer)
243        sizer_smearer.Add((10,10))
244        sizer_smearer.Add( self.pinhole_smearer ) 
245        sizer_smearer.Add((10,10))
246        sizer_smearer.Add( self.slit_smearer ) 
247        sizer_smearer.Add((10,10))       
248       
249        # static box for chi2
250        box_description= wx.StaticBox(self, -1,'Chi2/dof')
251        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
252        boxsizer1.SetMinSize((70,40))
253       
254       
255       
256        # StaticText for chi2 and smear
257        self.tcChi    =  wx.StaticText(self, -1, "-", style=wx.ALIGN_LEFT)
258        self.smear_description_none    =  wx.StaticText(self, -1, smear_message_none , style=wx.ALIGN_LEFT)
259        self.smear_description_dqdata    =  wx.StaticText(self, -1, smear_message_dqdata , style=wx.ALIGN_LEFT)
260        self.smear_description_type    =  wx.StaticText(self, -1, "Type:" , style=wx.ALIGN_LEFT)
261        self.smear_description_smear_type    =  BGTextCtrl(self, -1, size=(45,20), style=0)
262        self.smear_description_smear_type.SetValue(str(self.dq_l))
263        self.SetBackgroundColour(self.GetParent().GetBackgroundColour())
264        self.smear_description_2d     =  wx.StaticText(self, -1, smear_message_2d  , style=wx.ALIGN_LEFT)
265        self.smear_message_new_s = wx.StaticText(self, -1, smear_message_new_ssmear  , style=wx.ALIGN_LEFT)
266        self.smear_message_new_p = wx.StaticText(self, -1, smear_message_new_psmear  , style=wx.ALIGN_LEFT)
267        self.smear_description_pin_min     =  wx.StaticText(self, -1, smear_message_pinhole_min_title  , style=wx.ALIGN_LEFT)
268        self.smear_description_pin_max     =  wx.StaticText(self, -1, smear_message_pinhole_max_title  , style=wx.ALIGN_LEFT)
269        self.smear_description_slit_height    =  wx.StaticText(self, -1, smear_message_slit_height_title   , style=wx.ALIGN_LEFT)
270        self.smear_description_slit_width    =  wx.StaticText(self, -1, smear_message_slit_width_title   , style=wx.ALIGN_LEFT)
271       
272        #arrange sizers
273        boxsizer1.Add( self.tcChi ) 
274        self.sizer_set_smearer.Add(sizer_smearer )
275        self.sizer_set_smearer.Add((10,10))
276        self.sizer_set_smearer.Add( self.smear_description_none,0, wx.CENTER, 10 ) 
277        self.sizer_set_smearer.Add( self.smear_description_dqdata,0, wx.CENTER, 10 )
278        self.sizer_set_smearer.Add( self.smear_description_2d,0, wx.CENTER, 10 )
279        self.sizer_new_smear.Add( self.smear_description_type,0, wx.CENTER, 10 )
280        self.sizer_new_smear.Add( self.smear_description_smear_type,0, wx.CENTER, 10 )
281        self.sizer_new_smear.Add((15,-1))
282        self.sizer_new_smear.Add( self.smear_description_pin_min,0, wx.CENTER, 10 )
283        self.sizer_new_smear.Add( self.smear_description_slit_height,0, wx.CENTER, 10 )
284        self.sizer_new_smear.Add( self.smear_pinhole_min,0, wx.CENTER, 10 )
285        self.sizer_new_smear.Add( self.smear_slit_height,0, wx.CENTER, 10 )
286        self.sizer_new_smear.Add( self.smear_data_left,0, wx.CENTER, 10 )
287        self.sizer_new_smear.Add((20,-1))
288        self.sizer_new_smear.Add( self.smear_description_pin_max,0, wx.CENTER, 10 )
289        self.sizer_new_smear.Add( self.smear_description_slit_width,0, wx.CENTER, 10 )
290        self.sizer_new_smear.Add( self.smear_pinhole_max,0, wx.CENTER, 10 )
291        self.sizer_new_smear.Add( self.smear_slit_width,0, wx.CENTER, 10 )
292        self.sizer_new_smear.Add( self.smear_data_right,0, wx.CENTER, 10 )
293           
294        self.sizer_set_smearer.Add( self.smear_message_new_s,0, wx.CENTER, 10)
295        self.sizer_set_smearer.Add( self.smear_message_new_p,0, wx.CENTER, 10)
296        self.sizer_set_smearer.Add((5,2))
297        self.sizer_set_smearer.Add( self.sizer_new_smear,0, wx.CENTER, 10 )
298       
299        # add all to chi2 sizer
300       
301        sizer_smearer_box.Add(self.sizer_set_smearer) 
302       
303        sizer_chi2.Add(sizer_smearer_box)
304        sizer_chi2.Add((-1,5))
305        self.sizer_set_masking.Add((305,-1))
306        #self.sizer_set_masking.Add(boxsizer1,0, wx.RIGHT, 10)
307        sizer_chi2.Add(self.sizer_set_masking )
308         
309        sizer_fit.Add(boxsizer1,0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 63)
310        #sizer_fit.Add((-1,1),0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 1)
311        sizer_fit.Add(self.btFit,0, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 63) 
312        sizer_fit.Layout()
313        #sizer_smearer_box.Add(sizer_chi2)
314        # hide all smear messages and textctrl
315        self._hide_all_smear_info()
316       
317        # get smear_selection
318        self.current_smearer= smear_selection( self.data )
319
320        # Show only the relevant smear messages, etc
321        if self.current_smearer == None:
322            if self.data.__class__.__name__ != 'Data2D':
323                self.smear_description_none.Show(True)
324                self.enable_smearer.Disable() 
325            else:
326                self.smear_description_2d.Show(True) 
327                self.pinhole_smearer.Disable() 
328                self.slit_smearer.Disable()   
329                self.enable_smearer.Disable() 
330        else: self._show_smear_sizer()
331 
332           
333        #Set sizer for Fitting section
334        self._set_range_sizer( title=title,box_sizer=boxsizer_range, object1=sizer_chi2, object= sizer_fit)
335       
336    def _fill_datainfo_sizer(self):
337        """
338            fill sizer 0 with data info
339        """
340        ## no loaded data , don't fill the sizer
341        if self.data is None:
342            data_min = ""
343            data_max = ""
344            data_name = ""
345        else:
346            data_name = self.data.name
347            #set maximum range for x in linear scale
348            if not hasattr(self.data,"data"): #Display only for 1D data fit
349                # Minimum value of data   
350                data_min = min(self.data.x)
351                # Maximum value of data 
352                data_max = max(self.data.x)
353            else:
354                ## Minimum value of data
355                data_min = 0
356                x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
357                y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
358                ## Maximum value of data 
359                data_max = math.sqrt(x*x + y*y)
360       
361        box_description= wx.StaticBox(self, -1, 'Data')
362        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
363        #----------------------------------------------------------
364        sizer_data = wx.BoxSizer(wx.HORIZONTAL)
365        #Filling the sizer containing data related fields
366        #self.dataSource = wx.StaticText(self, -1,str(self.data.name))
367        self.dataSource = BGTextCtrl(self, -1)
368        self.dataSource.SetValue(str(data_name))
369        #self.dataSource.SetEditable(False)
370        self.dataSource.SetMinSize((_DATA_BOX_WIDTH, -1))
371        sizer_data.Add(wx.StaticText(self, -1, 'Source Name : '))
372        sizer_data.Add(self.dataSource )
373        sizer_data.Add( (0,5) )
374       
375        #---------sizer 2 draw--------------------------------
376        text4_3 = wx.StaticText(self, -1, 'Total Q Range (1/A)',
377                                 style=wx.ALIGN_LEFT)
378        sizer_range = wx.BoxSizer(wx.HORIZONTAL)
379        sizer_range.Add( text4_3 ,0, wx.RIGHT, 10)
380        self.minimum_q = BGTextCtrl(self, -1, size=(_BOX_WIDTH,20))
381        self.minimum_q.SetValue(str(data_min))
382        #self.minimum_q.SetEditable(False)
383        self.maximum_q = BGTextCtrl(self, -1,size=(_BOX_WIDTH,20))
384        self.maximum_q.SetValue(str(data_max))
385        #self.maximum_q.SetEditable(False)
386        sizer_range.Add(wx.StaticText(self, -1, "Min: "),0, wx.LEFT, 10)
387        sizer_range.Add(self.minimum_q,0, wx.LEFT, 10)
388        sizer_range.Add(wx.StaticText(self, -1, "Max: "),0, wx.LEFT, 10)
389        sizer_range.Add(self.maximum_q,0, wx.LEFT, 10)
390
391        ## set q range to plot
392        self.qmin_x = data_min
393        self.qmax_x = data_max
394
395        boxsizer1.Add(sizer_data,0, wx.ALL, 10)
396        boxsizer1.Add(sizer_range, 0 , wx.LEFT, 10)
397        #------------------------------------------------------------
398        self.sizer0.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
399        self.sizer0.Layout()
400       
401    def _fill_model_sizer(self, sizer):
402        """
403            fill sizer containing model info
404        """
405        ##Add model function Details button in fitpanel.
406        ##The following 3 lines are for Mac. Let JHC know before modifying...
407        title = "Model"
408        box_description= wx.StaticBox(self, -1,str(title))
409        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
410         
411        id = wx.NewId()
412        self.model_help =wx.Button(self,id,'Details', size=(80,23))
413        self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked,id=id)
414        self.model_help.SetToolTipString("Model Function Help")
415       
416        ## class base method  to add view 2d button   
417        self._set_model_sizer(sizer=sizer, box_sizer=boxsizer1, title="Model",object=self.model_help )   
418
419   
420    def _set_sizer_dispersion(self, dispersity):
421        """
422            draw sizer with gaussian dispersity parameters
423        """
424        self.fittable_param=[]
425        self.fixed_param=[]
426        self.orientation_params_disp=[]
427
428        self.sizer4_4.Clear(True)
429        if self.model==None:
430            ##no model is selected
431            return
432        if not self.enable_disp.GetValue():
433            ## the user didn't select dispersity display
434            return 
435           
436        self._reset_dispersity()
437       
438        # Create the dispersion objects
439        for item in self.model.dispersion.keys():
440            #disp_model =  GaussianDispersion()
441            disp_model = dispersity()
442            self._disp_obj_dict[item] = disp_model
443            self.model.set_dispersion(item, disp_model)
444            self.state._disp_obj_dict[item]= disp_model
445
446
447        ix=0
448        iy=1
449        disp = wx.StaticText(self, -1, 'Names')
450        self.sizer4_4.Add(disp,( iy, ix),(1,1), 
451                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
452        ix += 1 
453        values = wx.StaticText(self, -1, 'Sigmas (STD)')
454        self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
455        ix +=2 
456        self.text_disp_1 = wx.StaticText(self, -1, '')
457        self.sizer4_4.Add( self.text_disp_1,(iy, ix),(1,1),\
458                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
459        self.text_disp_1.Hide()
460       
461       
462        ix +=1 
463        self.text_disp_min = wx.StaticText(self, -1, 'Min')
464        self.sizer4_4.Add(self.text_disp_min,(iy, ix),(1,1),\
465                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
466        self.text_disp_min.Hide()
467        ix +=1 
468        self.text_disp_max = wx.StaticText(self, -1, 'Max')
469        self.sizer4_4.Add(self.text_disp_max,(iy, ix),(1,1),\
470                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
471        self.text_disp_max.Hide()
472                       
473       
474        ix += 1 
475        npts = wx.StaticText(self, -1, 'Npts')
476        self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
477        ix += 1 
478        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
479        self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
480       
481        if self.engine_type=="park":
482            self.text_disp_max.Show(True)
483            self.text_disp_min.Show(True)
484
485        for item in self.model.dispersion.keys():
486            if not item in self.model.orientation_params:
487                if not self.disp_cb_dict.has_key(item):
488                    self.disp_cb_dict[item]= None
489                name1=item+".width"
490                name2=item+".npts"
491                name3=item+".nsigmas"
492                if not self.model.details.has_key(name1):
493                    self.model.details [name1] = ["",None,None] 
494
495                iy += 1
496                for p in self.model.dispersion[item].keys(): 
497       
498                    if p=="width":
499                        ix = 0
500                        cb = wx.CheckBox(self, -1, name1, (10, 10))
501                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
502                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
503                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
504                        ix = 1
505                        value= self.model.getParam(name1)
506                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
507                                            style=wx.TE_PROCESS_ENTER)
508                        ctl1.SetValue(str (format_number(value)))
509                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
510                        ## text to show error sign
511                        ix = 2
512                        text2=wx.StaticText(self, -1, '+/-')
513                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
514                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
515                        text2.Hide() 
516
517                        ix = 3
518                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
519                 
520                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
521                     
522                        ctl2.Hide()
523
524                        ix = 4
525                        ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
526                                                       text_enter_callback = self._onparamRangeEnter)
527
528                        self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
529                        ctl3.Hide()
530               
531                        ix = 5
532                        ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
533                                                       text_enter_callback = self._onparamRangeEnter)
534                        self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
535
536                        ctl4.Hide()
537                       
538                        if self.engine_type=="park":
539                            ctl3.Show(True)
540                            ctl4.Show(True)
541                                         
542                        self.fittable_param.append([cb,name1,ctl1,text2,
543                                                    ctl2, ctl3, ctl4,None])                   
544                   
545                    elif p=="npts":
546                            ix = 6
547                            value= self.model.getParam(name2)
548                            Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
549                                                style=wx.TE_PROCESS_ENTER)
550                           
551                            Tctl.SetValue(str (format_number(value)))
552                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
553                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
554                            self.fixed_param.append([None,name2, Tctl,None,None,
555                                                      None, None,None])
556                    elif p=="nsigmas":
557                            ix = 7
558                            value= self.model.getParam(name3)
559                            Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
560                                                style=wx.TE_PROCESS_ENTER)
561                            Tct2.SetValue(str (format_number(value)))
562                            self.sizer4_4.Add(Tct2, (iy,ix),(1,1),
563                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
564                            ix +=1
565                            self.sizer4_4.Add((20,20), (iy,ix),(1,1),
566                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
567                           
568                            self.fixed_param.append([None,name3, Tct2
569                                                     ,None,None,None, None,None])
570                           
571        ix =0
572        iy +=1 
573        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
574        for item in self.model.dispersion.keys():
575            if  item in self.model.orientation_params:
576                if not self.disp_cb_dict.has_key(item):
577                    self.disp_cb_dict[item]= None
578                name1=item+".width"
579                name2=item+".npts"
580                name3=item+".nsigmas"
581                if not self.model.details.has_key(name1):
582                    self.model.details [name1] = ["",None,None]                 
583 
584
585                iy += 1
586                for p in self.model.dispersion[item].keys(): 
587       
588                    if p=="width":
589                        ix = 0
590                        cb = wx.CheckBox(self, -1, name1, (10, 10))
591                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
592                        self.sizer4_4.Add( cb,( iy, ix),(1,1), 
593                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
594                        if self.data.__class__.__name__ =="Data2D":
595                            cb.Show(True)
596                        elif cb.IsShown():
597                            cb.Hide()
598                        ix = 1
599                        value= self.model.getParam(name1)
600                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
601                                            style=wx.TE_PROCESS_ENTER)
602                        ctl1.SetValue(str (format_number(value)))
603                        if self.data.__class__.__name__ =="Data2D":
604                            ctl1.Show(True)
605                        elif ctl1.IsShown():
606                            ctl1.Hide()
607                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND)
608                        ## text to show error sign
609                        ix = 2
610                        text2=wx.StaticText(self, -1, '+/-')
611                        self.sizer4_4.Add(text2,(iy, ix),(1,1),
612                                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
613                        text2.Hide() 
614
615                        ix = 3
616                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
617                   
618                        self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
619                        ctl2.Hide()
620                           
621                        ix = 4
622                        ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
623                                                       text_enter_callback = self._onparamRangeEnter)
624
625                        self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
626
627                        ctl3.Hide()
628               
629                        ix = 5
630                        ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
631                                                       text_enter_callback = self._onparamRangeEnter)
632                        self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
633                        ctl4.Hide()
634                        #if self.data.__class__.__name__ =="Data2D":
635                            #ctl4.Enable(True)
636                        #elif ctl4.Shown():
637                            #ctl4.Hide()
638                       
639                        if self.engine_type=="park" and self.data.__class__.__name__ =="Data2D":
640                            ctl3.Show(True)
641                            ctl4.Show(True) 
642                           
643                           
644                           
645                           
646                        self.fittable_param.append([cb,name1,ctl1,text2,
647                                                    ctl2, ctl3, ctl4,None])
648                        self.orientation_params_disp.append([cb,name1,ctl1,text2,
649                                                    ctl2, ctl3, ctl4,None])
650                    elif p=="npts":
651                            ix = 6
652                            value= self.model.getParam(name2)
653                            Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
654                                                style=wx.TE_PROCESS_ENTER)
655                           
656                            Tctl.SetValue(str (format_number(value)))
657                            if self.data.__class__.__name__ =="Data2D":
658                                Tctl.Show(True)
659                            else:
660                                Tctl.Hide()
661                            self.sizer4_4.Add(Tctl, (iy,ix),(1,1),
662                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
663                            self.fixed_param.append([None,name2, Tctl,None,None,
664                                                      None, None,None])
665                            self.orientation_params_disp.append([None,name2, Tctl,None,None,
666                                                      None, None,None])
667                    elif p=="nsigmas":
668                            ix = 7
669                            value= self.model.getParam(name3)
670                            Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
671                                                style=wx.TE_PROCESS_ENTER)
672                            Tct2.SetValue(str (format_number(value)))
673                            if self.data.__class__.__name__ =="Data2D":
674                                Tct2.Show(True)
675                            else:
676                                Tct2.Hide()
677                            self.sizer4_4.Add(Tct2, (iy,ix),(1,1),
678                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
679                            ix +=1
680
681                            self.fixed_param.append([None,name3, Tct2
682                                                     ,None,None, None, None,None])   
683                                                       
684                            self.orientation_params_disp.append([None,name3, Tct2
685                                                     ,None,None, None, None,None])
686       
687
688        self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict) 
689         
690        self.state.model = self.model.clone() 
691         ## save state into
692        self.state.cb1 = self.cb1.GetValue()
693        self._copy_parameters_state(self.parameters, self.state.parameters)
694        self._copy_parameters_state(self.orientation_params_disp,
695                                     self.state.orientation_params_disp)
696        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
697        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
698
699
700        wx.PostEvent(self.parent, StatusEvent(status=\
701                        " Selected Distribution: Gaussian"))   
702        #Fill the list of fittable parameters
703        self.select_all_param(event=None)
704       
705        self.Layout()
706
707
708    def _onFit(self, event):     
709        """
710            Allow to fit
711        """
712        #make sure all parameter values are updated.
713        if self.check_invalid_panel():
714            return
715        flag = self._update_paramv_on_fit() 
716               
717        if not flag:
718            msg= "Fitting range or parameters are invalid"
719            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
720            return 
721       
722        if len(self.param_toFit) <= 0:
723            msg= "Select at least one parameter to fit"
724            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
725            return 
726     
727
728        self.select_param(event =None)
729       
730        #Clear errors if exist from previous fitting
731        #self._clear_Err_on_Fit()
732
733        # Remove or do not allow fitting on the Q=0 point, especially when y(q=0)=None at x[0].         
734        self.qmin_x = float(self.qmin.GetValue())
735        self.qmax_x = float( self.qmax.GetValue())
736        self.manager._reset_schedule_problem( value=0)
737        self.manager.schedule_for_fit( value=1,page=self,fitproblem =None) 
738        self.manager.set_fit_range(page= self,qmin= self.qmin_x, qmax= self.qmax_x)
739       
740        #single fit
741        self.manager.onFit()
742        ## allow stopping the fit
743        #if self.engine_type=="scipy":
744        #    self.btFit.SetLabel("Stop")
745        #    self.btFit.Unbind(event=wx.EVT_BUTTON, id= self.btFit.GetId())
746        #    self.btFit.Bind(event= wx.EVT_BUTTON, handler=self._StopFit, id=self.btFit.GetId())
747        #else:
748        #    self.btFit.SetLabel("Fit")
749        #    self.btFit.Bind(event= wx.EVT_BUTTON, handler=self._onFit, id=self.btFit.GetId())
750           
751
752       
753    def _StopFit(self, event):
754        """
755            Stop fit
756        """
757        self.btFit.SetLabel("Fit")
758        if self.engine_type=="scipy":
759            self.manager.stop_fit()
760        self.btFit.Unbind(event=wx.EVT_BUTTON, id=self.btFit.GetId())
761        self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._onFit,id=self.btFit.GetId())
762       
763           
764    def _on_select_model(self, event): 
765        """
766             call back for model selection
767        """   
768        self._on_select_model_helper() 
769        self.set_model_param_sizer(self.model)                   
770       
771        self.enable_disp.SetValue(False)
772        self.disable_disp.SetValue(True)
773        try:
774            self.set_dispers_sizer()
775        except:
776            pass
777        if self.model != None:
778            try:
779                temp_smear= None
780                if self.enable_smearer.GetValue():
781                    temp_smear= self.smearer
782                self.compute_chisqr(temp_smear)
783            except:
784                ## error occured on chisqr computation
785                pass
786            if self.data is not None and self.data.__class__.__name__ !="Data2D":
787                ## set smearing value whether or not the data contain the smearing info
788                self.manager.set_smearer(smearer=temp_smear, qmin= float(self.qmin_x),
789                                     qmax= float(self.qmax_x)) 
790           
791            evt = ModelEventbox(model=self.model)
792            wx.PostEvent(self.event_owner, evt) 
793           
794        self.btFit.SetFocus() 
795        self.state.enable_disp = self.enable_disp.GetValue()
796        self.state.disable_disp = self.disable_disp.GetValue()
797        self.state.pinhole_smearer = self.pinhole_smearer.GetValue()
798        self.state.slit_smearer = self.slit_smearer.GetValue()
799   
800        self.state.structurecombobox = self.structurebox.GetCurrentSelection()
801        self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection()
802     
803       
804        if event !=None:
805            #self._undo.Enable(True)
806            ## post state to fit panel
807            event = PageInfoEvent(page = self)
808            wx.PostEvent(self.parent, event) 
809     
810               
811    def _onparamEnter(self,event):
812        """
813            when enter value on panel redraw model according to changed
814        """
815        flag = False
816        tcrtl= event.GetEventObject()
817
818        #Clear msg if previously shown.
819        msg= ""
820        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
821
822        if check_float(tcrtl):
823            flag = self._onparamEnter_helper()               
824            temp_smearer = None
825            if not self.disable_smearer.GetValue():
826                temp_smearer= self.current_smearer
827                ## set smearing value whether or not the data contain the smearing info
828                if self.slit_smearer.GetValue():
829                    flag1 = self.update_slit_smear()
830                    flag = flag or flag1
831                elif self.pinhole_smearer.GetValue():
832                    flag1 = self.update_pinhole_smear()
833                    flag = flag or flag1
834            elif self.data.__class__.__name__ !="Data2D":
835                self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
836                                                         qmax= float(self.qmax_x)) 
837            if flag:   
838                self.compute_chisqr(smearer= temp_smearer)
839   
840                ## new state posted
841                if self.state_change:
842                    #self._undo.Enable(True)
843                    event = PageInfoEvent(page = self)
844                    wx.PostEvent(self.parent, event)
845                self.state_change= False           
846        else:
847            self.save_current_state()
848            msg= "Cannot Plot :Must enter a number!!!  "
849            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
850             
851        self.save_current_state() 
852        return 
853   
854    def _onparamRangeEnter(self, event):
855        """
856            Check validity of value enter in the parameters range field
857        """
858        if self.check_invalid_panel():
859            return
860        tcrtl= event.GetEventObject()
861        #Clear msg if previously shown.
862        msg= ""
863        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
864        # Flag to register when a parameter has changed.
865        is_modified = False
866        if tcrtl.GetValue().lstrip().rstrip()!="":
867            try:
868                value = float(tcrtl.GetValue())
869                tcrtl.SetBackgroundColour(wx.WHITE)
870                self._check_value_enter(self.fittable_param ,is_modified)
871                self._check_value_enter(self.parameters ,is_modified) 
872            except:
873                tcrtl.SetBackgroundColour("pink")
874                msg= "Model Error:wrong value entered : %s"% sys.exc_value
875                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
876                return 
877        else:
878           tcrtl.SetBackgroundColour(wx.WHITE)
879           
880        #self._undo.Enable(True)
881        self.save_current_state()
882        event = PageInfoEvent(page = self)
883        wx.PostEvent(self.parent, event)
884        self.state_change= False
885
886                   
887    def _onQrangeEnter(self, event):
888        """
889            Check validity of value enter in the Q range field
890        """
891        if self.check_invalid_panel():
892            return
893        tcrtl= event.GetEventObject()
894        #Clear msg if previously shown.
895        msg= ""
896        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
897        # Flag to register when a parameter has changed.
898        is_modified = False
899        if tcrtl.GetValue().lstrip().rstrip()!="":
900            try:
901                value = float(tcrtl.GetValue())
902                tcrtl.SetBackgroundColour(wx.WHITE)
903
904                # If qmin and qmax have been modified, update qmin and qmax
905                if self._validate_qrange( self.qmin, self.qmax):
906                    tempmin = float(self.qmin.GetValue())
907                    if tempmin != self.qmin_x:
908                        self.qmin_x = tempmin
909                    tempmax = float(self.qmax.GetValue())
910                    if tempmax != self.qmax_x:
911                        self.qmax_x = tempmax
912                else:
913                    tcrtl.SetBackgroundColour("pink")
914                    msg= "Model Error:wrong value entered : %s"% sys.exc_value
915                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
916                    return 
917               
918            except:
919                tcrtl.SetBackgroundColour("pink")
920                msg= "Model Error:wrong value entered : %s"% sys.exc_value
921                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
922                return 
923            #Check if # of points for theory model are valid(>0).
924            if self.npts != None:
925                if check_float(self.npts):
926                    temp_npts = float(self.npts.GetValue())
927                    if temp_npts !=  self.num_points:
928                        self.num_points = temp_npts
929                        is_modified = True
930                else:
931                    msg= "Cannot Plot :No npts in that Qrange!!!  "
932                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
933           
934        else:
935           tcrtl.SetBackgroundColour("pink")
936           msg= "Model Error:wrong value entered!!!"
937           wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
938       
939        self.compute_chisqr()   
940        #self._undo.Enable(True)
941        self.save_current_state()
942        event = PageInfoEvent(page = self)
943        wx.PostEvent(self.parent, event)
944        self.state_change= False
945        self._draw_model()
946       
947    def _clear_Err_on_Fit(self):
948        """
949            hide the error text control shown
950            after fitting
951        """
952       
953        if hasattr(self,"text2_3"):
954            self.text2_3.Hide()
955
956        if len(self.parameters)>0:
957            for item in self.parameters:
958                #Skip t ifhe angle parameters if 1D data
959                if self.data.__class__.__name__ !="Data2D":
960                    if item in self.orientation_params:
961                        continue
962                if item in self.param_toFit:
963                    continue
964                ## hide statictext +/-   
965                if item[3]!=None and item[3].IsShown():
966                    item[3].Hide()
967                ## hide textcrtl  for error after fit
968                if item[4]!=None and item[4].IsShown():                   
969                    item[4].Hide()
970 
971        if len(self.fittable_param)>0:
972            for item in self.fittable_param:
973                #Skip t ifhe angle parameters if 1D data
974                if self.data.__class__.__name__ !="Data2D":
975                    if item in self.orientation_params:
976                        continue
977                if item in self.param_toFit:
978                    continue
979                ## hide statictext +/-   
980                if item[3]!=None and item[3].IsShown():
981                    item[3].Hide()
982                ## hide textcrtl  for error after fit
983                if item[4]!=None and item[4].IsShown():
984                    item[4].Hide()
985        return       
986               
987    def _get_defult_custom_smear(self):
988        """
989           Get the defult values for custum smearing.
990        """
991
992        # get the default values
993        if self.dxl == None: self.dxl = 0.0
994        if self.dxw == None: self.dxw = ""
995        if self.dx_min == None: self.dx_min = SMEAR_SIZE_L
996        if self.dx_max == None: self.dx_max = SMEAR_SIZE_H
997       
998    def _get_smear_info(self):
999        """
1000           Get the smear info from data.
1001           @return: self.smear_type, self.dq_l and self.dq_r,
1002            respectively the type of the smear, dq_min and dq_max for pinhole smear data
1003            while dxl and dxw for slit smear
1004        """
1005
1006        # default
1007        self.smear_type = None
1008        self.dq_l = None
1009        self.dq_r = None
1010       
1011        if self.data is None or\
1012                self.data.__class__.__name__ == 'Data2D':           
1013            return
1014
1015        data = self.data
1016
1017        # check if it is pinhole smear and get min max if it is.
1018        if data.dx != None and all(data.dx !=0): 
1019            self.smear_type = "Pinhole" 
1020            self.dq_l = numpy.min(data.dx)
1021            self.dq_r = numpy.max(data.dx)
1022           
1023        # check if it is slit smear and get min max if it is.
1024        elif data.dxl != None or data.dxw != None: 
1025            self.smear_type = "Slit" 
1026            if data.dxl != None and all(data.dxl !=0):
1027                self.dq_l = data.dxl[0]
1028            if data.dxw != None and all(data.dxw !=0): 
1029                self.dq_r = data.dxw[0]
1030               
1031        #return self.smear_type,self.dq_l,self.dq_r       
1032   
1033    def _show_smear_sizer(self):   
1034        """
1035            Show only the sizers depending on smear selection
1036        """
1037        if self.disable_smearer.GetValue():
1038            self.smear_description_none.Show(True)
1039        elif self.enable_smearer.GetValue():
1040            self.smear_description_dqdata.Show(True)
1041            if self.smear_type != None:
1042                self.smear_description_type.Show(True)
1043                self.smear_description_smear_type.Show(True)
1044                if self.smear_type == 'Slit':
1045                    self.smear_description_slit_height.Show(True)
1046                    self.smear_description_slit_width.Show(True)
1047                elif self.smear_type == 'Pinhole':
1048                    self.smear_description_pin_min.Show(True)
1049                    self.smear_description_pin_max.Show(True)
1050                self.smear_data_left.Show(True)
1051                self.smear_data_right.Show(True)
1052        elif self.pinhole_smearer.GetValue():
1053            self.smear_message_new_p.Show(True)
1054            self.smear_description_pin_min.Show(True)
1055            self.smear_pinhole_min.Show(True)
1056            self.smear_description_pin_max.Show(True)
1057            self.smear_pinhole_max.Show(True)
1058        elif self.slit_smearer.GetValue():
1059            self.smear_message_new_s.Show(True)
1060            self.smear_description_slit_height.Show(True)
1061            self.smear_slit_height.Show(True)
1062            self.smear_description_slit_width.Show(True)
1063            self.smear_slit_width.Show(True)
1064
1065    def _hide_all_smear_info(self):
1066        """
1067           Hide all smearing messages in the set_smearer sizer
1068        """
1069        self.smear_description_none.Hide()
1070        self.smear_description_dqdata.Hide()
1071        self.smear_description_type.Hide()
1072        self.smear_description_smear_type.Hide()
1073        self.smear_description_2d.Hide()
1074        self.smear_data_left.Hide()
1075        self.smear_data_right.Hide()
1076        self.smear_description_pin_min.Hide()
1077        self.smear_pinhole_min.Hide()
1078        self.smear_description_pin_max.Hide()
1079        self.smear_pinhole_max.Hide()
1080        self.smear_description_slit_height.Hide()
1081        self.smear_slit_height.Hide()
1082        self.smear_description_slit_width.Hide()
1083        self.smear_slit_width.Hide()
1084        self.smear_message_new_p.Hide()
1085        self.smear_message_new_s.Hide()
1086   
1087       
1088    def set_data(self, data):
1089        """
1090            reset the current data
1091        """
1092        self.data = data
1093        if self.data is None:
1094            data_min = ""
1095            data_max = ""
1096            data_name = ""
1097            self.formfactorbox.Disable()
1098            self.structurebox.Disable()
1099        else:
1100            self.smearer = smear_selection( self.data )
1101            self.disable_smearer.SetValue(True)
1102            if self.smearer == None:
1103                self.enable_smearer.Disable()
1104            else:
1105                self.enable_smearer.Enable()
1106
1107            # more disables for 2D
1108            if self.data.__class__.__name__ =="Data2D":
1109                self.smear_description_none.Hide()
1110                self.smear_description_2d.Show(True)
1111                self.pinhole_smearer.Disable()
1112                self.slit_smearer.Disable()
1113               
1114               
1115            self.formfactorbox.Enable()
1116            self.structurebox.Enable()
1117            data_name = self.data.name
1118            #set maximum range for x in linear scale
1119            if not hasattr(self.data,"data"): #Display only for 1D data fit
1120                # Minimum value of data   
1121                data_min = min(self.data.x)
1122                # Maximum value of data 
1123                data_max = max(self.data.x)
1124            else:
1125                ## Minimum value of data
1126                data_min = 0
1127                x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
1128                y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
1129                ## Maximum value of data 
1130                data_max = math.sqrt(x*x + y*y)
1131       
1132        self.dataSource.SetValue(data_name)
1133        self.qmin_x = data_min
1134        self.qmax_x = data_max
1135        self.minimum_q.SetValue(str(data_min))
1136        self.maximum_q.SetValue(str(data_max))
1137        self.qmin.SetValue(str(data_min))
1138        self.qmax.SetValue(str(data_max))
1139        self.qmin.SetBackgroundColour("white")
1140        self.qmax.SetBackgroundColour("white")
1141        self.state.data = data
1142        self.state.qmin = self.qmin_x
1143        self.state.qmax = self.qmax_x
1144       
1145
1146    def reset_page(self, state,first=False):
1147        """
1148            reset the state
1149        """
1150        self.reset_page_helper(state)
1151        import sans.guiframe.gui_manager
1152        evt = ModelEventbox(model=state.model)
1153        wx.PostEvent(self.event_owner, evt) 
1154   
1155        if self.engine_type != None:
1156            self.manager._on_change_engine(engine=self.engine_type)
1157
1158        self.select_param(event = None) 
1159        #Save state_fit
1160        self.save_current_state_fit()
1161        self._lay_out()
1162        self.Refresh()
1163       
1164    def get_range(self):
1165        """
1166            return the fitting range
1167        """
1168        return float(self.qmin_x) , float(self.qmax_x)
1169   
1170    def get_npts2fit(self):
1171        """
1172            return numbers of data points within qrange
1173            Note: This is for Park where chi2 is not normalized by Npts of fit
1174        """
1175        npts2fit = 0
1176        qmin,qmax = self.get_range()
1177        if self.data.__class__.__name__ =="Data2D":
1178            npts2fit = len(self.data.data[self.mask])
1179        else:
1180            for qx in self.data.x:
1181                   if qx >= qmin and qx <= qmax:
1182                       npts2fit += 1
1183        return npts2fit
1184
1185
1186    def get_chi2(self):
1187        """
1188            return the current chi2
1189        """
1190        return self.tcChi.GetLabel()
1191       
1192    def get_param_list(self):
1193        """
1194            @return self.param_toFit: list containing  references to TextCtrl
1195            checked.Theses TextCtrl will allow reference to parameters to fit.
1196            @raise: if return an empty list of parameter fit will nnote work
1197            properly so raise ValueError,"missing parameter to fit"
1198        """
1199        if self.param_toFit !=[]:
1200            return self.param_toFit
1201        else:
1202            raise ValueError,"missing parameter to fit"   
1203     
1204    def onsetValues(self,chisqr,p_name, out,cov):
1205        """
1206            Build the panel from the fit result
1207            @param chisqr:Value of the goodness of fit metric
1208            @p_name: the name of parameters
1209            @param out:list of parameter with the best value found during fitting
1210            @param cov:Covariance matrix
1211       
1212        """
1213        if out == None or not numpy.isfinite(chisqr):
1214            raise ValueError,"Fit error occured..." 
1215       
1216        is_modified = False
1217        has_error = False   
1218       
1219        #Hide textctrl boxes of errors.
1220        self._clear_Err_on_Fit()   
1221       
1222        #Check if chi2 is finite
1223        if chisqr != None or numpy.isfinite(chisqr):
1224        #format chi2 
1225            if self.engine_type == "park": 
1226                npt_fit = float(self.get_npts2fit()) 
1227                if npt_fit > 0:
1228                    chisqr =chisqr/npt_fit   
1229            chi2 = format_number(chisqr)   
1230            self.tcChi.SetLabel(chi2)   
1231            self.tcChi.Refresh()   
1232        else:
1233            self.tcChi.SetLabel("-")
1234       
1235        #Hide error title
1236        if self.text2_3.IsShown():
1237            self.text2_3.Hide()
1238     
1239        try:
1240            n = self.disp_box.GetCurrentSelection()
1241            dispersity= self.disp_box.GetClientData(n)
1242            if dispersity !=None and self.enable_disp.GetValue():
1243                name= dispersity.__name__
1244                if name == "GaussianDispersion":
1245                    if hasattr(self,"text_disp_1" ):
1246                        if self.text_disp_1 !=None:
1247                            self.text_disp_1.Hide()
1248        except:
1249            dispersty = None
1250            pass
1251        #set the panel when fit result are float not list
1252        if out.__class__== numpy.float64:
1253            self.param_toFit[0][2].SetValue(format_number(out))
1254           
1255            if self.param_toFit[0][4].IsShown:
1256                self.param_toFit[0][4].Hide()
1257            if cov !=None :
1258                self.text2_3.Show(True)
1259                try:
1260                    if dispersity !=None:
1261                        name= dispersity.__name__
1262                        if name == "GaussianDispersion" and self.enable_disp.GetValue():
1263                            if hasattr(self,"text_disp_1" ):
1264                                if self.text_disp_1 !=None:
1265                                    self.text_disp_1.Show(True)
1266                except:
1267                    pass
1268
1269                if cov[0]==None or  not numpy.isfinite(cov[0]): 
1270                    if self.param_toFit[0][3].IsShown:
1271                        self.param_toFit[0][3].Hide()
1272                else:                   
1273                    self.param_toFit[0][3].Show(True)               
1274                    self.param_toFit[0][4].Show(True)
1275                    self.param_toFit[0][4].SetValue(format_number(cov[0]))
1276                    has_error = True
1277        else:
1278
1279            i = 0
1280            #Set the panel when fit result are list
1281            for item in self.param_toFit:     
1282                if len(item)>5 and item != None:     
1283                    ## reset error value to initial state
1284                    item[3].Hide()
1285                    item[4].Hide()
1286                   
1287                    for ind in range(len(out)):
1288                       
1289                        if item[1] == p_name[ind]:
1290                            break       
1291                    if len(out)<=len(self.param_toFit) and out[ind] !=None:   
1292                        val_out = format_number(out[ind])                 
1293                        item[2].SetValue(val_out)
1294
1295                    if(cov !=None):
1296                       
1297                        try:
1298                            if dispersity !=None:
1299                                name= dispersity.__name__
1300                                if name == "GaussianDispersion" and self.enable_disp.GetValue():
1301                                    if hasattr(self,"text_disp_1" ):
1302                                        if self.text_disp_1!=None:
1303                                            if not self.text_disp_1.IsShown():
1304                                                self.text_disp_1.Show(True)
1305                        except:
1306                            pass   
1307                   
1308                        if cov[ind]!=None :
1309                            if numpy.isfinite(float(cov[ind])):
1310                                val_err = format_number(cov[ind])
1311                                item[3].Show(True)
1312                                item[4].Show(True)
1313                                item[4].SetValue(val_err)
1314
1315                                has_error = True
1316                    i += 1         
1317        #Show error title when any errors displayed
1318        if has_error: 
1319            if not self.text2_3.IsShown():
1320                self.text2_3.Show(True) 
1321               
1322        ## save current state 
1323        self.save_current_state()         
1324        #plot model
1325        self._draw_model()   
1326        self._lay_out()     
1327        #PostStatusEvent     
1328        msg = "Fit completed! "
1329        wx.PostEvent(self.manager.parent, StatusEvent(status=msg))
1330
1331    def onPinholeSmear(self, event):
1332        """
1333            Create a custom pinhole smear object that will change the way residuals
1334            are compute when fitting
1335        """
1336
1337        if self.check_invalid_panel():
1338            return
1339        if self.model ==None:
1340            msg="Need model and data to smear plot"
1341            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1342                            "Smear: %s"%msg))
1343            return
1344       
1345        # msg default
1346        msg = None
1347        if event != None:
1348            tcrtl= event.GetEventObject()
1349            # event case of radio button
1350            if tcrtl.GetValue()== True:
1351                self.dx_min = 0.0
1352                self.dx_max = 0.0
1353                is_new_pinhole = True
1354            else:
1355                is_new_pinhole = self._is_changed_pinhole()
1356        else:
1357            is_new_pinhole = self._is_changed_pinhole()
1358        # if any value is changed
1359        if is_new_pinhole:
1360            msg = self._set_pinhole_smear()
1361        # hide all silt sizer   
1362        self._hide_all_smear_info()
1363           
1364        ##Calculate chi2
1365        self.compute_chisqr(smearer= self.current_smearer) 
1366        # show relevant slit sizers
1367        self._show_smear_sizer()
1368        self.sizer_set_smearer.Layout()
1369        self.Layout()   
1370       
1371        if event != None: 
1372            event.Skip()                 
1373        #self._undo.Enable(True)
1374        self.save_current_state()
1375        event = PageInfoEvent(page = self)
1376        wx.PostEvent(self.parent, event)
1377       
1378    def _is_changed_pinhole(self): 
1379        """
1380            check if any of pinhole smear is changed
1381            return: True or False
1382        """
1383        # get the values
1384        pin_min = self.smear_pinhole_min.GetValue()
1385        pin_max = self.smear_pinhole_max.GetValue()
1386                   
1387        # Check changes in slit width   
1388        try:
1389            dx_min = float(pin_min)
1390        except:
1391            return True
1392        if self.dx_min != dx_min:
1393            return True
1394       
1395        # Check changes in slit heigth
1396        try:
1397            dx_max = float(pin_max)
1398        except:
1399            return True
1400        if self.dx_max != dx_max:
1401            return True
1402        return False
1403   
1404    def _set_pinhole_smear(self):
1405        """
1406            Set custom pinhole smear
1407            return: msg
1408        """
1409        # copy data
1410        data = copy.deepcopy(self.data)
1411        data_len = len(data.x)
1412        data.dx = None
1413        data.dxl = None
1414        data.dxw = None
1415        msg = None
1416   
1417        # make sure once more if it is smearer
1418        data = copy.deepcopy(self.data)
1419        len_data = len(data.x)
1420        data.dx = numpy.zeros(len_data)
1421        get_pin_min = self.smear_pinhole_min
1422        get_pin_max = self.smear_pinhole_max       
1423
1424        if self._validate_qrange(get_pin_min, get_pin_max ):
1425            if len_data < 2: len_data = 2     
1426            self.dx_min = float(get_pin_min.GetValue())
1427            self.dx_max = float(get_pin_max.GetValue())
1428            if self.dx_min != None and self.dx_max != None:             
1429                if self.dx_min == self.dx_max:
1430                    data.dx[data.dx==0] = self.dx_min
1431                else:
1432                    step = math.fabs(self.dx_max - self.dx_min)/(len_data-1)   
1433                    data.dx = numpy.arange(self.dx_min,self.dx_max+step/1.1,step)           
1434            elif self.dx_min != None: 
1435                data.dx[data.dx==0] = self.dx_min
1436            elif self.dx_max != None:
1437                data.dx[data.dx==0] = self.dx_max         
1438            self.current_smearer = smear_selection(data)
1439
1440        else:
1441            get_pin_min.SetBackgroundColour("pink")
1442            get_pin_max.SetBackgroundColour("pink")
1443            msg= "Model Error:wrong value entered!!!"
1444            wx.PostEvent(self.manager.parent, StatusEvent(status = msg ))
1445        ## set smearing value whether or not the data contain the smearing info
1446        self.manager.set_smearer(smearer=self.current_smearer, qmin= float(self.qmin_x),qmax= float(self.qmax_x))
1447 
1448        return msg
1449       
1450    def update_pinhole_smear(self):
1451        """
1452            called by kill_focus on pinhole TextCntrl
1453            to update the changes
1454            return: msg: False when wrong value was entered
1455        """
1456        # msg default
1457        msg = None
1458        # check if any value is changed
1459        if self._is_changed_pinhole():
1460            msg = self._set_pinhole_smear()           
1461        #self._undo.Enable(True)
1462        self.save_current_state()
1463
1464        if msg != None:
1465            return False   
1466        else:
1467            return True
1468                     
1469    def onSlitSmear(self, event):
1470        """
1471            Create a custom slit smear object that will change the way residuals
1472            are compute when fitting
1473        """
1474
1475               
1476        if self.check_invalid_panel():
1477            return
1478        if self.model ==None:
1479            msg="Need model and data to smear plot"
1480            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1481                            "Smear: %s"%msg))
1482            return
1483        # msg default
1484        msg = None
1485        # for event given
1486        if event != None:
1487            tcrtl= event.GetEventObject()
1488            # event case of radio button
1489            if tcrtl.GetValue():
1490                self.dxl = 0.0
1491                self.dxw = 0.0
1492                is_new_slit = True
1493            else:
1494                is_new_slit = self._is_changed_slit()
1495        else:
1496            is_new_slit = self._is_changed_slit()
1497               
1498        # if any value is changed
1499        if is_new_slit:
1500            msg = self._set_slit_smear()
1501        # hide all silt sizer
1502        self._hide_all_smear_info()       
1503        ##Calculate chi2
1504        self.compute_chisqr(smearer= self.current_smearer) 
1505        # show relevant slit sizers       
1506        self._show_smear_sizer()
1507        self.sizer_set_smearer.Layout()
1508        self.Layout()
1509       
1510        if event != None:
1511            event.Skip()     
1512        #self._undo.Enable(True)
1513        self.save_current_state()
1514        event = PageInfoEvent(page = self)
1515        wx.PostEvent(self.parent, event)
1516        if msg != None:
1517            wx.PostEvent(self.manager.parent, StatusEvent(status = msg))
1518
1519           
1520    def _is_changed_slit(self): 
1521        """
1522            check if any of slit lengths is changed
1523            return: True or False
1524        """
1525        # get the values
1526        width = self.smear_slit_width.GetValue()
1527        height = self.smear_slit_height.GetValue()
1528       
1529        # check and change the box bg color if it was pink but it should be white now
1530        # because this is the case that _set_slit_smear() will not handle
1531        if height.lstrip().rstrip()=="":
1532            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1533        if width.lstrip().rstrip()=="":
1534            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1535           
1536        # Check changes in slit width   
1537        if width == "": 
1538            dxw = 0.0
1539        else:
1540            try:
1541                dxw = float(width)
1542            except:
1543                return True
1544        if self.dxw != dxw:
1545            return True
1546       
1547        # Check changes in slit heigth
1548        if height == "": 
1549            dxl = 0.0
1550        else:
1551            try:
1552                dxl = float(height)
1553            except:
1554                return True
1555        if self.dxl != dxl:
1556            return True
1557        return False
1558   
1559    def _set_slit_smear(self):
1560        """
1561            Set custom slit smear
1562            return: msg
1563        """
1564        temp_smearer = None
1565        # make sure once more if it is smearer
1566        data = copy.deepcopy(self.data)
1567        data_len = len(data.x)
1568        data.dx = None
1569        data.dxl = None
1570        data.dxw = None
1571        msg = None
1572   
1573        try:
1574            self.dxl = float(self.smear_slit_height.GetValue())
1575            data.dxl = self.dxl* numpy.ones(data_len)
1576            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1577        except: 
1578            data.dxl = numpy.zeros(data_len)
1579            if self.smear_slit_height.GetValue().lstrip().rstrip()!="":
1580                self.smear_slit_height.SetBackgroundColour("pink")
1581                msg = "Wrong value entered... " 
1582            else:
1583                self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1584        try:
1585            self.dxw = float(self.smear_slit_width.GetValue())
1586            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1587            data.dxw = self.dxw* numpy.ones(data_len)
1588        except: 
1589            data.dxw = numpy.zeros(data_len)
1590            if self.smear_slit_width.GetValue().lstrip().rstrip()!="":
1591                self.smear_slit_width.SetBackgroundColour("pink")
1592                msg = "Wrong Fit value entered... "
1593            else:
1594                self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1595               
1596        self.current_smearer = smear_selection(data)
1597        #temp_smearer = self.current_smearer
1598        ## set smearing value whether or not the data contain the smearing info
1599        self.manager.set_smearer(smearer=self.current_smearer, qmin= float(self.qmin_x), qmax= float(self.qmax_x)) 
1600
1601        return msg
1602   
1603   
1604    def update_slit_smear(self):
1605        """
1606            called by kill_focus on pinhole TextCntrl
1607            to update the changes
1608            return: msg: False when wrong value was entered
1609        """             
1610        # msg default
1611        msg = None
1612        # check if any value is changed
1613        if self._is_changed_slit():
1614            msg = self._set_slit_smear()           
1615        #self._undo.Enable(True)
1616        self.save_current_state()
1617
1618        if msg != None:
1619            return False   
1620        else:
1621            return True
1622                           
1623   
1624    def onSmear(self, event):
1625        """
1626            Create a smear object that will change the way residuals
1627            are compute when fitting
1628        """
1629        if self.check_invalid_panel():
1630            return
1631        if self.model ==None:
1632            msg="Need model and data to smear plot"
1633            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1634                            "Smear: %s"%msg))
1635            return
1636        temp_smearer = None
1637        self._get_smear_info()
1638       
1639        #renew smear sizer
1640        if self.smear_type != None:
1641            self.smear_description_smear_type.SetValue(str(self.smear_type))
1642            self.smear_data_left.SetValue(str(self.dq_l))   
1643            self.smear_data_right.SetValue(str(self.dq_r))       
1644       
1645        self._hide_all_smear_info()
1646       
1647        data = copy.deepcopy(self.data)
1648        # make sure once more if it is smearer
1649        self.current_smearer = smear_selection(data)
1650
1651        if self.enable_smearer.GetValue():
1652            temp_smearer= self.current_smearer
1653            if hasattr(self.data,"dxl"):
1654               
1655                msg= ": Resolution smearing parameters"
1656            if hasattr(self.data,"dxw"):
1657                msg= ": Slit smearing parameters"
1658            if self.smearer ==None:
1659                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1660                            "Data contains no smearing information"))
1661            else:
1662                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1663                            "Data contains smearing information %s"%msg))
1664            self.smear_description_dqdata.Show(True)
1665            self.smear_data_left.Show(True)
1666            self.smear_data_right.Show(True)
1667        elif self.disable_smearer.GetValue():
1668            self.smear_description_none.Show(True)
1669           
1670        self._show_smear_sizer()
1671        self.sizer_set_smearer.Layout()
1672        self.Layout()
1673        ## set smearing value whether or not the data contain the smearing info
1674        self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
1675                                     qmax= float(self.qmax_x)) 
1676        ##Calculate chi2
1677        self.compute_chisqr(smearer= temp_smearer) 
1678       
1679        self.state.enable_smearer=  self.enable_smearer.GetValue()
1680        self.state.disable_smearer=self.disable_smearer.GetValue()
1681        self.state.pinhole_smearer = self.pinhole_smearer.GetValue()
1682        self.state.slit_smearer = self.slit_smearer.GetValue()
1683       
1684    def complete_chisqr(self, output, elapsed=None): 
1685        """
1686            print result chisqr
1687        """
1688        try:
1689            if output ==None:
1690                output= "-"
1691
1692            self.tcChi.SetLabel(str(format_number(output)))
1693
1694            self.state.tcChi =self.tcChi
1695         
1696        except:
1697            pass
1698       
1699       
1700    def compute_chisqr1D(self, smearer=None):
1701        """
1702            Compute chisqr for 1D
1703        """
1704        try:
1705            self.qmin_x = float(self.qmin.GetValue())
1706            self.qmax_x = float(self.qmax.GetValue())
1707            ##return residuals within self.qmin_x and self.qmax_x
1708            from gui_thread import CalcChisqr1D
1709            ## If a thread is already started, stop it
1710            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1711                self.calc_Chisqr.stop()
1712               
1713            self.calc_Chisqr= CalcChisqr1D( data1d= self.data,
1714                                            model= self.model,
1715                                            smearer=smearer,
1716                                            qmin=self.qmin_x,
1717                                            qmax=self.qmax_x,
1718                                            completefn = self.complete_chisqr,
1719                                            updatefn   = None)
1720   
1721            self.calc_Chisqr.queue()
1722           
1723        except:
1724            raise ValueError," Could not compute Chisqr for %s Model 2D: "%self.model.name
1725           
1726           
1727   
1728       
1729       
1730    def compute_chisqr2D(self):
1731        """
1732            compute chi square given a model and data 2D and set the value
1733            to the tcChi txtcrl
1734        """
1735        try:
1736            self.qmin_x = float(self.qmin.GetValue())
1737            self.qmax_x = float(self.qmax.GetValue())
1738           
1739            ##return residuals within self.qmin_x and self.qmax_x
1740            from gui_thread import CalcChisqr2D
1741            ## If a thread is already started, stop it
1742            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1743                self.calc_Chisqr.stop()
1744           
1745            self.calc_Chisqr= CalcChisqr2D( data2d= self.data,
1746                                            model= self.model,
1747                                            qmin= self.qmin_x,
1748                                            qmax = self.qmax_x,
1749                                            completefn = self.complete_chisqr,
1750                                            updatefn   = None)
1751   
1752            self.calc_Chisqr.queue()
1753         
1754        except:
1755           raise
1756
1757       
1758    def compute_chisqr(self , smearer=None):
1759        """
1760            compute chi square given a model and data 1D and set the value
1761            to the tcChi txtcrl
1762        """
1763        flag = self._validate_qrange( self.qmin, self.qmax)
1764        if flag== True:
1765            try:
1766                if hasattr(self.data,"data"):
1767                    self.compute_chisqr2D()
1768                    return
1769                else:
1770                    self.compute_chisqr1D(smearer=smearer)
1771                    return
1772            except:
1773                wx.PostEvent(self.parent.parent, StatusEvent(status=\
1774                            "Chisqr Error: %s"% sys.exc_value))
1775                return 
1776           
1777   
1778    def select_all_param(self,event): 
1779        """
1780             set to true or false all checkBox given the main checkbox value cb1
1781        """           
1782
1783        self.param_toFit=[]
1784        if  self.parameters !=[]:
1785            if  self.cb1.GetValue():
1786                for item in self.parameters:
1787                    ## for data2D select all to fit
1788                    if self.data.__class__.__name__=="Data2D":
1789                        item[0].SetValue(True)
1790                        self.param_toFit.append(item )
1791                    else:
1792                        ## for 1D all parameters except orientation
1793                        if not item in self.orientation_params:
1794                            item[0].SetValue(True)
1795                            self.param_toFit.append(item )
1796                #if len(self.fittable_param)>0:
1797                for item in self.fittable_param:
1798                    if self.data.__class__.__name__=="Data2D":
1799                        item[0].SetValue(True)
1800                        self.param_toFit.append(item )
1801                    else:
1802                        ## for 1D all parameters except orientation
1803                        if not item in self.orientation_params_disp:
1804                            item[0].SetValue(True)
1805                            self.param_toFit.append(item )
1806            else:
1807                for item in self.parameters:
1808                    item[0].SetValue(False)
1809                for item in self.fittable_param:
1810                    item[0].SetValue(False)
1811                self.param_toFit=[]
1812           
1813        self.save_current_state_fit() 
1814       
1815        if event !=None:
1816            #self._undo.Enable(True)
1817            ## post state to fit panel
1818            event = PageInfoEvent(page = self)
1819            wx.PostEvent(self.parent, event) 
1820     
1821               
1822               
1823    def select_param(self,event):
1824        """
1825            Select TextCtrl  checked for fitting purpose and stores them
1826            in  self.param_toFit=[] list
1827        """
1828        self.param_toFit=[]
1829        for item in self.parameters:
1830            #Skip t ifhe angle parameters if 1D data
1831            if self.data.__class__.__name__ !="Data2D":
1832                if item in self.orientation_params:
1833                    continue
1834            #Select parameters to fit for list of primary parameters
1835            if item[0].GetValue():
1836                if not (item in self.param_toFit):
1837                    self.param_toFit.append(item ) 
1838            else:
1839                #remove parameters from the fitting list
1840                if item in self.param_toFit:
1841                    self.param_toFit.remove(item)
1842
1843        #Select parameters to fit for list of fittable parameters with dispersion         
1844        for item in self.fittable_param:
1845            #Skip t ifhe angle parameters if 1D data
1846            if self.data.__class__.__name__ !="Data2D":
1847                if item in self.orientation_params:
1848                    continue
1849            if item[0].GetValue():
1850                if not (item in self.param_toFit):
1851                    self.param_toFit.append(item) 
1852            else:
1853                #remove parameters from the fitting list
1854                if item in self.param_toFit:
1855                    self.param_toFit.remove(item)
1856
1857        #Calculate num. of angle parameters
1858        if self.data.__class__.__name__ =="Data2D": 
1859            len_orient_para = 0
1860        else:
1861            len_orient_para = len(self.orientation_params)  #assume even len
1862        #Total num. of angle parameters
1863        if len(self.fittable_param) > 0:
1864            len_orient_para *= 2
1865        #Set the value of checkbox that selected every checkbox or not           
1866        if len(self.parameters)+len(self.fittable_param)-len_orient_para ==len(self.param_toFit):
1867            self.cb1.SetValue(True)
1868        else:
1869            self.cb1.SetValue(False)
1870        self.save_current_state_fit()
1871        if event !=None:
1872            #self._undo.Enable(True)
1873            ## post state to fit panel
1874            event = PageInfoEvent(page = self)
1875            wx.PostEvent(self.parent, event) 
1876     
1877   
1878       
1879    def set_model_param_sizer(self, model):
1880        """
1881            Build the panel from the model content
1882            @param model: the model selected in combo box for fitting purpose
1883        """
1884        self.sizer3.Clear(True)
1885        self.parameters = []
1886        self.param_toFit=[]
1887        self.fittable_param=[]
1888        self.fixed_param=[]
1889        self.orientation_params=[]
1890        self.orientation_params_disp=[]
1891       
1892        if model ==None:
1893            self.sizer3.Layout()
1894            self.SetScrollbars(20,20,25,65)
1895            return
1896        ## the panel is drawn using the current value of the fit engine
1897        if self.engine_type==None and self.manager !=None:
1898            self.engine_type= self.manager._return_engine_type()
1899
1900           
1901        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
1902        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1903        sizer = wx.GridBagSizer(5,5)
1904        ## save the current model
1905        self.model = model
1906           
1907        keys = self.model.getParamList()
1908        #list of dispersion paramaters
1909        self.disp_list=self.model.getDispParamList()
1910
1911        keys.sort()
1912   
1913        iy = 0
1914        ix = 0
1915        select_text = "Uncheck all to fix"
1916        self.cb1 = wx.CheckBox(self, -1,str(select_text), (10, 10))
1917        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
1918        self.cb1.SetValue(True)
1919       
1920        sizer.Add(self.cb1,(iy, ix),(1,1),\
1921                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1922        ix +=1
1923        self.text2_2 = wx.StaticText(self, -1, 'Values')
1924        sizer.Add(self.text2_2,(iy, ix),(1,1),\
1925                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1926        ix +=2 
1927        self.text2_3 = wx.StaticText(self, -1, 'Errors')
1928        sizer.Add(self.text2_3,(iy, ix),(1,1),\
1929                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1930        self.text2_3.Hide()
1931        ix +=1 
1932        self.text2_min = wx.StaticText(self, -1, 'Min')
1933        sizer.Add(self.text2_min,(iy, ix),(1,1),\
1934                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1935        self.text2_min.Hide()
1936        ix +=1 
1937        self.text2_max = wx.StaticText(self, -1, 'Max')
1938        sizer.Add(self.text2_max,(iy, ix),(1,1),\
1939                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1940        self.text2_max.Hide()
1941        ix += 1
1942        self.text2_4 = wx.StaticText(self, -1, '[Units]')
1943        sizer.Add(self.text2_4,(iy, ix),(1,1),\
1944                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1945        self.text2_4.Hide()
1946        if self.engine_type=="park":
1947            self.text2_max.Show(True)
1948            self.text2_min.Show(True)
1949       
1950        for item in keys:
1951            if not item in self.disp_list and not item in self.model.orientation_params:
1952               
1953                ##prepare a spot to store errors
1954                if not self.model.details.has_key(item):
1955                    self.model.details [item] = ["",None,None] 
1956         
1957                iy += 1
1958                ix = 0
1959                ## add parameters name with checkbox for selecting to fit
1960                cb = wx.CheckBox(self, -1, item )
1961                cb.SetValue(True)
1962                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
1963                sizer.Add( cb,( iy, ix),(1,1),
1964                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1965               
1966                ## add parameter value
1967                ix += 1
1968                value= self.model.getParam(item)
1969                ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
1970                                    style=wx.TE_PROCESS_ENTER)
1971               
1972                ctl1.SetValue(format_number(value))
1973                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
1974                ## text to show error sign
1975                ix += 1
1976                text2=wx.StaticText(self, -1, '+/-')
1977                sizer.Add(text2,(iy, ix),(1,1),\
1978                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1979                text2.Hide() 
1980                ix += 1
1981                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
1982                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1983                ctl2.Hide()
1984               
1985                ix += 1
1986                ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1987                                               text_enter_callback = self._onparamRangeEnter)
1988     
1989                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1990                ctl3.Hide()
1991       
1992                ix += 1
1993                ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1994                                               text_enter_callback = self._onparamRangeEnter)
1995                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1996     
1997                ctl4.Hide()
1998
1999                if self.engine_type=="park":
2000                    ctl3.Show(True)
2001                    ctl4.Show(True)
2002                ix +=1
2003                # Units
2004                if self.model.details.has_key(item):
2005                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
2006                else:
2007                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
2008                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2009                   
2010                ##[cb state, name, value, "+/-", error of fit, min, max , units]
2011                self.parameters.append([cb,item, ctl1,
2012                                        text2,ctl2, ctl3, ctl4,units])
2013             
2014        iy+=1
2015        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
2016       
2017        # type can be either Guassian or Array
2018        if len(self.model.dispersion.values())>0:
2019            type= self.model.dispersion.values()[0]["type"]
2020        else:
2021            type = "Gaussian"
2022           
2023        iy += 1
2024        ix = 0
2025        #Add tile for orientational angle
2026        for item in keys:
2027            if item in self.model.orientation_params:       
2028                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
2029                sizer.Add(orient_angle,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
2030                if not self.data.__class__.__name__ =="Data2D":
2031                    orient_angle.Hide()
2032                else:
2033                    orient_angle.Show(True)
2034                break
2035     
2036        #For Gaussian only
2037        if type.lower() != "array":
2038            for item in self.model.orientation_params:
2039                if not item in self.disp_list:
2040                    ##prepare a spot to store min max
2041                    if not self.model.details.has_key(item):
2042                        self.model.details [item] = ["",None,None] 
2043                         
2044                    iy += 1
2045                    ix = 0
2046                    ## add parameters name with checkbox for selecting to fit
2047                    cb = wx.CheckBox(self, -1, item )
2048                    cb.SetValue(False)
2049                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
2050                    if self.data.__class__.__name__ =="Data2D":
2051                        cb.Show(True)
2052                    else:
2053                        cb.Hide()
2054                    sizer.Add( cb,( iy, ix),(1,1),
2055                                 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
2056   
2057                    ## add parameter value
2058                    ix += 1
2059                    value= self.model.getParam(item)
2060                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
2061                                        style=wx.TE_PROCESS_ENTER)
2062                   
2063                    ctl1.SetValue(format_number(value))
2064                    if self.data.__class__.__name__ =="Data2D":
2065                        ctl1.Show(True)
2066                    else:
2067                        ctl1.Hide()
2068                    sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
2069                    ## text to show error sign
2070                    ix += 1
2071                    text2=wx.StaticText(self, -1, '+/-')
2072                    sizer.Add(text2,(iy, ix),(1,1),\
2073                                    wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
2074                    text2.Hide() 
2075                    ix += 1
2076                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
2077                   
2078                    sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2079                    ctl2.Hide()
2080                   
2081                   
2082                    ix += 1
2083                    ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
2084                                                   text_enter_callback = self._onparamRangeEnter)
2085               
2086                    sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2087                    ctl3.Hide()
2088                 
2089                    ix += 1
2090                    ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
2091                                                   text_enter_callback = self._onparamRangeEnter)
2092                    sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2093                   
2094                    ctl4.Hide()
2095                   
2096                    if self.engine_type =="park" and self.data.__class__.__name__ =="Data2D":                     
2097                        ctl3.Show(True)
2098                        ctl4.Show(True)
2099                   
2100                    ix +=1
2101                    # Units
2102                    if self.model.details.has_key(item):
2103                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
2104                    else:
2105                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
2106                    if self.data.__class__.__name__ =="Data2D":
2107                        units.Show(True)
2108                   
2109                    else:
2110                        units.Hide()
2111                   
2112                    sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2113                                         
2114                    ##[cb state, name, value, "+/-", error of fit, min, max , units]
2115                    self.parameters.append([cb,item, ctl1,
2116                                            text2,ctl2, ctl3, ctl4,units])
2117                    self.orientation_params.append([cb,item, ctl1,
2118                                            text2,ctl2, ctl3, ctl4,units])
2119             
2120        iy+=1
2121       
2122        #Display units text on panel
2123        for item in keys:   
2124            if self.model.details.has_key(item):
2125                self.text2_4.Show()
2126        #Fill the list of fittable parameters
2127        self.select_all_param(event=None)
2128
2129        self.save_current_state_fit()
2130        boxsizer1.Add(sizer)
2131        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
2132        self.sizer3.Layout()
2133        self.Layout()
2134        self.Refresh()
2135        self.SetScrollbars(20,20,25,65)
2136
2137class BGTextCtrl(wx.TextCtrl):
2138    """
2139        Text control used to display outputs.
2140        No editing allowed. The background is
2141        grayed out. User can't select text.
2142    """
2143    def __init__(self, *args, **kwds):
2144        wx.TextCtrl.__init__(self, *args, **kwds)
2145        self.SetEditable(False)
2146        self.SetBackgroundColour(self.GetParent().GetBackgroundColour())
2147       
2148        # Bind to mouse event to avoid text highlighting
2149        # The event will be skipped once the call-back
2150        # is called.
2151        self.Bind(wx.EVT_MOUSE_EVENTS, self._click)
2152       
2153    def _click(self, event):
2154        """
2155            Prevent further handling of the mouse event
2156            by not calling Skip().
2157        """ 
2158        pass
2159       
2160class HelpWindow(wx.Frame):
2161    def __init__(self, parent, id, title):
2162        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
2163       
2164        from sans.models.CylinderModel import CylinderModel
2165        model = CylinderModel()
2166       
2167        from danse.common.plottools.plottables import Data1D
2168        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
2169   
2170        from fitpanel import PageInfo
2171        myinfo = PageInfo(self,  model, data=data )
2172       
2173        ## add data
2174       
2175        from models import ModelList
2176        mylist= ModelList()
2177
2178        from sans.models.SphereModel import SphereModel
2179        from sans.models.SquareWellStructure import SquareWellStructure
2180        from sans.models.DebyeModel import DebyeModel
2181        from sans.models.LineModel import LineModel
2182        name= "shapes"
2183        list1= [SphereModel]
2184        mylist.set_list( name, list1)
2185       
2186        name= "Shape-independent"
2187        list1= [DebyeModel]
2188        mylist.set_list( name, list1)
2189       
2190        name= "Structure Factors"
2191        list1= [SquareWellStructure]
2192        mylist.set_list( name, list1)
2193       
2194        name= "Added models"
2195        list1= [LineModel]
2196        mylist.set_list( name, list1)
2197       
2198        myinfo.model_list_box = mylist.get_list()
2199       
2200        self.page = FitPage(self, myinfo) 
2201       
2202        self.Centre()
2203        self.Show(True)
2204 
2205if __name__=="__main__":
2206    app = wx.App()
2207    HelpWindow(None, -1, 'HelpWindow')
2208    app.MainLoop()
2209               
Note: See TracBrowser for help on using the repository browser.