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

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

fixed the bug: Errors on theory panel when changing # of points w/ 2D plot

  • 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                if self.model != None:
1110                    self.smear_description_2d.Show(True)
1111                self.smear_description_none.Hide()
1112                self.pinhole_smearer.Disable()
1113                self.slit_smearer.Disable()
1114               
1115               
1116            self.formfactorbox.Enable()
1117            self.structurebox.Enable()
1118            data_name = self.data.name
1119            #set maximum range for x in linear scale
1120            if not hasattr(self.data,"data"): #Display only for 1D data fit
1121                # Minimum value of data   
1122                data_min = min(self.data.x)
1123                # Maximum value of data 
1124                data_max = max(self.data.x)
1125            else:
1126                ## Minimum value of data
1127                data_min = 0
1128                x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
1129                y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
1130                ## Maximum value of data 
1131                data_max = math.sqrt(x*x + y*y)
1132       
1133        self.dataSource.SetValue(data_name)
1134        self.qmin_x = data_min
1135        self.qmax_x = data_max
1136        self.minimum_q.SetValue(str(data_min))
1137        self.maximum_q.SetValue(str(data_max))
1138        self.qmin.SetValue(str(data_min))
1139        self.qmax.SetValue(str(data_max))
1140        self.qmin.SetBackgroundColour("white")
1141        self.qmax.SetBackgroundColour("white")
1142        self.state.data = data
1143        self.state.qmin = self.qmin_x
1144        self.state.qmax = self.qmax_x
1145       
1146
1147    def reset_page(self, state,first=False):
1148        """
1149            reset the state
1150        """
1151        self.reset_page_helper(state)
1152        import sans.guiframe.gui_manager
1153        evt = ModelEventbox(model=state.model)
1154        wx.PostEvent(self.event_owner, evt) 
1155   
1156        if self.engine_type != None:
1157            self.manager._on_change_engine(engine=self.engine_type)
1158
1159        self.select_param(event = None) 
1160        #Save state_fit
1161        self.save_current_state_fit()
1162        self._lay_out()
1163        self.Refresh()
1164       
1165    def get_range(self):
1166        """
1167            return the fitting range
1168        """
1169        return float(self.qmin_x) , float(self.qmax_x)
1170   
1171    def get_npts2fit(self):
1172        """
1173            return numbers of data points within qrange
1174            Note: This is for Park where chi2 is not normalized by Npts of fit
1175        """
1176        npts2fit = 0
1177        qmin,qmax = self.get_range()
1178        if self.data.__class__.__name__ =="Data2D":
1179            npts2fit = len(self.data.data[self.mask])
1180        else:
1181            for qx in self.data.x:
1182                   if qx >= qmin and qx <= qmax:
1183                       npts2fit += 1
1184        return npts2fit
1185
1186
1187    def get_chi2(self):
1188        """
1189            return the current chi2
1190        """
1191        return self.tcChi.GetLabel()
1192       
1193    def get_param_list(self):
1194        """
1195            @return self.param_toFit: list containing  references to TextCtrl
1196            checked.Theses TextCtrl will allow reference to parameters to fit.
1197            @raise: if return an empty list of parameter fit will nnote work
1198            properly so raise ValueError,"missing parameter to fit"
1199        """
1200        if self.param_toFit !=[]:
1201            return self.param_toFit
1202        else:
1203            raise ValueError,"missing parameter to fit"   
1204     
1205    def onsetValues(self,chisqr,p_name, out,cov):
1206        """
1207            Build the panel from the fit result
1208            @param chisqr:Value of the goodness of fit metric
1209            @p_name: the name of parameters
1210            @param out:list of parameter with the best value found during fitting
1211            @param cov:Covariance matrix
1212       
1213        """
1214        if out == None or not numpy.isfinite(chisqr):
1215            raise ValueError,"Fit error occured..." 
1216       
1217        is_modified = False
1218        has_error = False   
1219       
1220        #Hide textctrl boxes of errors.
1221        self._clear_Err_on_Fit()   
1222       
1223        #Check if chi2 is finite
1224        if chisqr != None or numpy.isfinite(chisqr):
1225        #format chi2 
1226            if self.engine_type == "park": 
1227                npt_fit = float(self.get_npts2fit()) 
1228                if npt_fit > 0:
1229                    chisqr =chisqr/npt_fit   
1230            chi2 = format_number(chisqr)   
1231            self.tcChi.SetLabel(chi2)   
1232            self.tcChi.Refresh()   
1233        else:
1234            self.tcChi.SetLabel("-")
1235       
1236        #Hide error title
1237        if self.text2_3.IsShown():
1238            self.text2_3.Hide()
1239     
1240        try:
1241            n = self.disp_box.GetCurrentSelection()
1242            dispersity= self.disp_box.GetClientData(n)
1243            if dispersity !=None and self.enable_disp.GetValue():
1244                name= dispersity.__name__
1245                if name == "GaussianDispersion":
1246                    if hasattr(self,"text_disp_1" ):
1247                        if self.text_disp_1 !=None:
1248                            self.text_disp_1.Hide()
1249        except:
1250            dispersty = None
1251            pass
1252        #set the panel when fit result are float not list
1253        if out.__class__== numpy.float64:
1254            self.param_toFit[0][2].SetValue(format_number(out))
1255           
1256            if self.param_toFit[0][4].IsShown:
1257                self.param_toFit[0][4].Hide()
1258            if cov !=None :
1259                self.text2_3.Show(True)
1260                try:
1261                    if dispersity !=None:
1262                        name= dispersity.__name__
1263                        if name == "GaussianDispersion" and self.enable_disp.GetValue():
1264                            if hasattr(self,"text_disp_1" ):
1265                                if self.text_disp_1 !=None:
1266                                    self.text_disp_1.Show(True)
1267                except:
1268                    pass
1269
1270                if cov[0]==None or  not numpy.isfinite(cov[0]): 
1271                    if self.param_toFit[0][3].IsShown:
1272                        self.param_toFit[0][3].Hide()
1273                else:                   
1274                    self.param_toFit[0][3].Show(True)               
1275                    self.param_toFit[0][4].Show(True)
1276                    self.param_toFit[0][4].SetValue(format_number(cov[0]))
1277                    has_error = True
1278        else:
1279
1280            i = 0
1281            #Set the panel when fit result are list
1282            for item in self.param_toFit:     
1283                if len(item)>5 and item != None:     
1284                    ## reset error value to initial state
1285                    item[3].Hide()
1286                    item[4].Hide()
1287                   
1288                    for ind in range(len(out)):
1289                       
1290                        if item[1] == p_name[ind]:
1291                            break       
1292                    if len(out)<=len(self.param_toFit) and out[ind] !=None:   
1293                        val_out = format_number(out[ind])                 
1294                        item[2].SetValue(val_out)
1295
1296                    if(cov !=None):
1297                       
1298                        try:
1299                            if dispersity !=None:
1300                                name= dispersity.__name__
1301                                if name == "GaussianDispersion" and self.enable_disp.GetValue():
1302                                    if hasattr(self,"text_disp_1" ):
1303                                        if self.text_disp_1!=None:
1304                                            if not self.text_disp_1.IsShown():
1305                                                self.text_disp_1.Show(True)
1306                        except:
1307                            pass   
1308                   
1309                        if cov[ind]!=None :
1310                            if numpy.isfinite(float(cov[ind])):
1311                                val_err = format_number(cov[ind])
1312                                item[3].Show(True)
1313                                item[4].Show(True)
1314                                item[4].SetValue(val_err)
1315
1316                                has_error = True
1317                    i += 1         
1318        #Show error title when any errors displayed
1319        if has_error: 
1320            if not self.text2_3.IsShown():
1321                self.text2_3.Show(True) 
1322               
1323        ## save current state 
1324        self.save_current_state()         
1325        #plot model
1326        self._draw_model()   
1327        self._lay_out()     
1328        #PostStatusEvent     
1329        msg = "Fit completed! "
1330        wx.PostEvent(self.manager.parent, StatusEvent(status=msg))
1331
1332    def onPinholeSmear(self, event):
1333        """
1334            Create a custom pinhole smear object that will change the way residuals
1335            are compute when fitting
1336        """
1337
1338        if self.check_invalid_panel():
1339            return
1340        if self.model ==None:
1341            msg="Need model and data to smear plot"
1342            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1343                            "Smear: %s"%msg))
1344            return
1345       
1346        # msg default
1347        msg = None
1348        if event != None:
1349            tcrtl= event.GetEventObject()
1350            # event case of radio button
1351            if tcrtl.GetValue()== True:
1352                self.dx_min = 0.0
1353                self.dx_max = 0.0
1354                is_new_pinhole = True
1355            else:
1356                is_new_pinhole = self._is_changed_pinhole()
1357        else:
1358            is_new_pinhole = self._is_changed_pinhole()
1359        # if any value is changed
1360        if is_new_pinhole:
1361            msg = self._set_pinhole_smear()
1362        # hide all silt sizer   
1363        self._hide_all_smear_info()
1364           
1365        ##Calculate chi2
1366        self.compute_chisqr(smearer= self.current_smearer) 
1367        # show relevant slit sizers
1368        self._show_smear_sizer()
1369        self.sizer_set_smearer.Layout()
1370        self.Layout()   
1371       
1372        if event != None: 
1373            event.Skip()                 
1374        #self._undo.Enable(True)
1375        self.save_current_state()
1376        event = PageInfoEvent(page = self)
1377        wx.PostEvent(self.parent, event)
1378       
1379    def _is_changed_pinhole(self): 
1380        """
1381            check if any of pinhole smear is changed
1382            return: True or False
1383        """
1384        # get the values
1385        pin_min = self.smear_pinhole_min.GetValue()
1386        pin_max = self.smear_pinhole_max.GetValue()
1387                   
1388        # Check changes in slit width   
1389        try:
1390            dx_min = float(pin_min)
1391        except:
1392            return True
1393        if self.dx_min != dx_min:
1394            return True
1395       
1396        # Check changes in slit heigth
1397        try:
1398            dx_max = float(pin_max)
1399        except:
1400            return True
1401        if self.dx_max != dx_max:
1402            return True
1403        return False
1404   
1405    def _set_pinhole_smear(self):
1406        """
1407            Set custom pinhole smear
1408            return: msg
1409        """
1410        # copy data
1411        data = copy.deepcopy(self.data)
1412        data_len = len(data.x)
1413        data.dx = None
1414        data.dxl = None
1415        data.dxw = None
1416        msg = None
1417   
1418        # make sure once more if it is smearer
1419        data = copy.deepcopy(self.data)
1420        len_data = len(data.x)
1421        data.dx = numpy.zeros(len_data)
1422        get_pin_min = self.smear_pinhole_min
1423        get_pin_max = self.smear_pinhole_max       
1424
1425        if self._validate_qrange(get_pin_min, get_pin_max ):
1426            if len_data < 2: len_data = 2     
1427            self.dx_min = float(get_pin_min.GetValue())
1428            self.dx_max = float(get_pin_max.GetValue())
1429            if self.dx_min != None and self.dx_max != None:             
1430                if self.dx_min == self.dx_max:
1431                    data.dx[data.dx==0] = self.dx_min
1432                else:
1433                    step = math.fabs(self.dx_max - self.dx_min)/(len_data-1)   
1434                    data.dx = numpy.arange(self.dx_min,self.dx_max+step/1.1,step)           
1435            elif self.dx_min != None: 
1436                data.dx[data.dx==0] = self.dx_min
1437            elif self.dx_max != None:
1438                data.dx[data.dx==0] = self.dx_max         
1439            self.current_smearer = smear_selection(data)
1440
1441        else:
1442            get_pin_min.SetBackgroundColour("pink")
1443            get_pin_max.SetBackgroundColour("pink")
1444            msg= "Model Error:wrong value entered!!!"
1445            wx.PostEvent(self.manager.parent, StatusEvent(status = msg ))
1446        ## set smearing value whether or not the data contain the smearing info
1447        self.manager.set_smearer(smearer=self.current_smearer, qmin= float(self.qmin_x),qmax= float(self.qmax_x))
1448 
1449        return msg
1450       
1451    def update_pinhole_smear(self):
1452        """
1453            called by kill_focus on pinhole TextCntrl
1454            to update the changes
1455            return: msg: False when wrong value was entered
1456        """
1457        # msg default
1458        msg = None
1459        # check if any value is changed
1460        if self._is_changed_pinhole():
1461            msg = self._set_pinhole_smear()           
1462        #self._undo.Enable(True)
1463        self.save_current_state()
1464
1465        if msg != None:
1466            return False   
1467        else:
1468            return True
1469                     
1470    def onSlitSmear(self, event):
1471        """
1472            Create a custom slit smear object that will change the way residuals
1473            are compute when fitting
1474        """
1475
1476               
1477        if self.check_invalid_panel():
1478            return
1479        if self.model ==None:
1480            msg="Need model and data to smear plot"
1481            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1482                            "Smear: %s"%msg))
1483            return
1484        # msg default
1485        msg = None
1486        # for event given
1487        if event != None:
1488            tcrtl= event.GetEventObject()
1489            # event case of radio button
1490            if tcrtl.GetValue():
1491                self.dxl = 0.0
1492                self.dxw = 0.0
1493                is_new_slit = True
1494            else:
1495                is_new_slit = self._is_changed_slit()
1496        else:
1497            is_new_slit = self._is_changed_slit()
1498               
1499        # if any value is changed
1500        if is_new_slit:
1501            msg = self._set_slit_smear()
1502        # hide all silt sizer
1503        self._hide_all_smear_info()       
1504        ##Calculate chi2
1505        self.compute_chisqr(smearer= self.current_smearer) 
1506        # show relevant slit sizers       
1507        self._show_smear_sizer()
1508        self.sizer_set_smearer.Layout()
1509        self.Layout()
1510       
1511        if event != None:
1512            event.Skip()     
1513        #self._undo.Enable(True)
1514        self.save_current_state()
1515        event = PageInfoEvent(page = self)
1516        wx.PostEvent(self.parent, event)
1517        if msg != None:
1518            wx.PostEvent(self.manager.parent, StatusEvent(status = msg))
1519
1520           
1521    def _is_changed_slit(self): 
1522        """
1523            check if any of slit lengths is changed
1524            return: True or False
1525        """
1526        # get the values
1527        width = self.smear_slit_width.GetValue()
1528        height = self.smear_slit_height.GetValue()
1529       
1530        # check and change the box bg color if it was pink but it should be white now
1531        # because this is the case that _set_slit_smear() will not handle
1532        if height.lstrip().rstrip()=="":
1533            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1534        if width.lstrip().rstrip()=="":
1535            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1536           
1537        # Check changes in slit width   
1538        if width == "": 
1539            dxw = 0.0
1540        else:
1541            try:
1542                dxw = float(width)
1543            except:
1544                return True
1545        if self.dxw != dxw:
1546            return True
1547       
1548        # Check changes in slit heigth
1549        if height == "": 
1550            dxl = 0.0
1551        else:
1552            try:
1553                dxl = float(height)
1554            except:
1555                return True
1556        if self.dxl != dxl:
1557            return True
1558        return False
1559   
1560    def _set_slit_smear(self):
1561        """
1562            Set custom slit smear
1563            return: msg
1564        """
1565        temp_smearer = None
1566        # make sure once more if it is smearer
1567        data = copy.deepcopy(self.data)
1568        data_len = len(data.x)
1569        data.dx = None
1570        data.dxl = None
1571        data.dxw = None
1572        msg = None
1573   
1574        try:
1575            self.dxl = float(self.smear_slit_height.GetValue())
1576            data.dxl = self.dxl* numpy.ones(data_len)
1577            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1578        except: 
1579            data.dxl = numpy.zeros(data_len)
1580            if self.smear_slit_height.GetValue().lstrip().rstrip()!="":
1581                self.smear_slit_height.SetBackgroundColour("pink")
1582                msg = "Wrong value entered... " 
1583            else:
1584                self.smear_slit_height.SetBackgroundColour(wx.WHITE)
1585        try:
1586            self.dxw = float(self.smear_slit_width.GetValue())
1587            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1588            data.dxw = self.dxw* numpy.ones(data_len)
1589        except: 
1590            data.dxw = numpy.zeros(data_len)
1591            if self.smear_slit_width.GetValue().lstrip().rstrip()!="":
1592                self.smear_slit_width.SetBackgroundColour("pink")
1593                msg = "Wrong Fit value entered... "
1594            else:
1595                self.smear_slit_width.SetBackgroundColour(wx.WHITE)
1596               
1597        self.current_smearer = smear_selection(data)
1598        #temp_smearer = self.current_smearer
1599        ## set smearing value whether or not the data contain the smearing info
1600        self.manager.set_smearer(smearer=self.current_smearer, qmin= float(self.qmin_x), qmax= float(self.qmax_x)) 
1601
1602        return msg
1603   
1604   
1605    def update_slit_smear(self):
1606        """
1607            called by kill_focus on pinhole TextCntrl
1608            to update the changes
1609            return: msg: False when wrong value was entered
1610        """             
1611        # msg default
1612        msg = None
1613        # check if any value is changed
1614        if self._is_changed_slit():
1615            msg = self._set_slit_smear()           
1616        #self._undo.Enable(True)
1617        self.save_current_state()
1618
1619        if msg != None:
1620            return False   
1621        else:
1622            return True
1623                           
1624   
1625    def onSmear(self, event):
1626        """
1627            Create a smear object that will change the way residuals
1628            are compute when fitting
1629        """
1630        if self.check_invalid_panel():
1631            return
1632        if self.model ==None:
1633            msg="Need model and data to smear plot"
1634            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1635                            "Smear: %s"%msg))
1636            return
1637        temp_smearer = None
1638        self._get_smear_info()
1639       
1640        #renew smear sizer
1641        if self.smear_type != None:
1642            self.smear_description_smear_type.SetValue(str(self.smear_type))
1643            self.smear_data_left.SetValue(str(self.dq_l))   
1644            self.smear_data_right.SetValue(str(self.dq_r))       
1645       
1646        self._hide_all_smear_info()
1647       
1648        data = copy.deepcopy(self.data)
1649        # make sure once more if it is smearer
1650        self.current_smearer = smear_selection(data)
1651
1652        if self.enable_smearer.GetValue():
1653            temp_smearer= self.current_smearer
1654            if hasattr(self.data,"dxl"):
1655               
1656                msg= ": Resolution smearing parameters"
1657            if hasattr(self.data,"dxw"):
1658                msg= ": Slit smearing parameters"
1659            if self.smearer ==None:
1660                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1661                            "Data contains no smearing information"))
1662            else:
1663                wx.PostEvent(self.manager.parent, StatusEvent(status=\
1664                            "Data contains smearing information %s"%msg))
1665            self.smear_description_dqdata.Show(True)
1666            self.smear_data_left.Show(True)
1667            self.smear_data_right.Show(True)
1668        elif self.disable_smearer.GetValue():
1669            self.smear_description_none.Show(True)
1670           
1671        self._show_smear_sizer()
1672        self.sizer_set_smearer.Layout()
1673        self.Layout()
1674        ## set smearing value whether or not the data contain the smearing info
1675        self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
1676                                     qmax= float(self.qmax_x)) 
1677        ##Calculate chi2
1678        self.compute_chisqr(smearer= temp_smearer) 
1679       
1680        self.state.enable_smearer=  self.enable_smearer.GetValue()
1681        self.state.disable_smearer=self.disable_smearer.GetValue()
1682        self.state.pinhole_smearer = self.pinhole_smearer.GetValue()
1683        self.state.slit_smearer = self.slit_smearer.GetValue()
1684       
1685    def complete_chisqr(self, output, elapsed=None): 
1686        """
1687            print result chisqr
1688        """
1689        try:
1690            if output ==None:
1691                output= "-"
1692
1693            self.tcChi.SetLabel(str(format_number(output)))
1694
1695            self.state.tcChi =self.tcChi
1696         
1697        except:
1698            pass
1699       
1700       
1701    def compute_chisqr1D(self, smearer=None):
1702        """
1703            Compute chisqr for 1D
1704        """
1705        try:
1706            self.qmin_x = float(self.qmin.GetValue())
1707            self.qmax_x = float(self.qmax.GetValue())
1708            ##return residuals within self.qmin_x and self.qmax_x
1709            from gui_thread import CalcChisqr1D
1710            ## If a thread is already started, stop it
1711            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1712                self.calc_Chisqr.stop()
1713               
1714            self.calc_Chisqr= CalcChisqr1D( data1d= self.data,
1715                                            model= self.model,
1716                                            smearer=smearer,
1717                                            qmin=self.qmin_x,
1718                                            qmax=self.qmax_x,
1719                                            completefn = self.complete_chisqr,
1720                                            updatefn   = None)
1721   
1722            self.calc_Chisqr.queue()
1723           
1724        except:
1725            raise ValueError," Could not compute Chisqr for %s Model 2D: "%self.model.name
1726           
1727           
1728   
1729       
1730       
1731    def compute_chisqr2D(self):
1732        """
1733            compute chi square given a model and data 2D and set the value
1734            to the tcChi txtcrl
1735        """
1736        try:
1737            self.qmin_x = float(self.qmin.GetValue())
1738            self.qmax_x = float(self.qmax.GetValue())
1739           
1740            ##return residuals within self.qmin_x and self.qmax_x
1741            from gui_thread import CalcChisqr2D
1742            ## If a thread is already started, stop it
1743            if self.calc_Chisqr!= None and self.calc_Chisqr.isrunning():
1744                self.calc_Chisqr.stop()
1745           
1746            self.calc_Chisqr= CalcChisqr2D( data2d= self.data,
1747                                            model= self.model,
1748                                            qmin= self.qmin_x,
1749                                            qmax = self.qmax_x,
1750                                            completefn = self.complete_chisqr,
1751                                            updatefn   = None)
1752   
1753            self.calc_Chisqr.queue()
1754         
1755        except:
1756           raise
1757
1758       
1759    def compute_chisqr(self , smearer=None):
1760        """
1761            compute chi square given a model and data 1D and set the value
1762            to the tcChi txtcrl
1763        """
1764        flag = self._validate_qrange( self.qmin, self.qmax)
1765        if flag== True:
1766            try:
1767                if hasattr(self.data,"data"):
1768                    self.compute_chisqr2D()
1769                    return
1770                else:
1771                    self.compute_chisqr1D(smearer=smearer)
1772                    return
1773            except:
1774                wx.PostEvent(self.parent.parent, StatusEvent(status=\
1775                            "Chisqr Error: %s"% sys.exc_value))
1776                return 
1777           
1778   
1779    def select_all_param(self,event): 
1780        """
1781             set to true or false all checkBox given the main checkbox value cb1
1782        """           
1783
1784        self.param_toFit=[]
1785        if  self.parameters !=[]:
1786            if  self.cb1.GetValue():
1787                for item in self.parameters:
1788                    ## for data2D select all to fit
1789                    if self.data.__class__.__name__=="Data2D":
1790                        item[0].SetValue(True)
1791                        self.param_toFit.append(item )
1792                    else:
1793                        ## for 1D all parameters except orientation
1794                        if not item in self.orientation_params:
1795                            item[0].SetValue(True)
1796                            self.param_toFit.append(item )
1797                #if len(self.fittable_param)>0:
1798                for item in self.fittable_param:
1799                    if self.data.__class__.__name__=="Data2D":
1800                        item[0].SetValue(True)
1801                        self.param_toFit.append(item )
1802                    else:
1803                        ## for 1D all parameters except orientation
1804                        if not item in self.orientation_params_disp:
1805                            item[0].SetValue(True)
1806                            self.param_toFit.append(item )
1807            else:
1808                for item in self.parameters:
1809                    item[0].SetValue(False)
1810                for item in self.fittable_param:
1811                    item[0].SetValue(False)
1812                self.param_toFit=[]
1813           
1814        self.save_current_state_fit() 
1815       
1816        if event !=None:
1817            #self._undo.Enable(True)
1818            ## post state to fit panel
1819            event = PageInfoEvent(page = self)
1820            wx.PostEvent(self.parent, event) 
1821     
1822               
1823               
1824    def select_param(self,event):
1825        """
1826            Select TextCtrl  checked for fitting purpose and stores them
1827            in  self.param_toFit=[] list
1828        """
1829        self.param_toFit=[]
1830        for item in self.parameters:
1831            #Skip t ifhe angle parameters if 1D data
1832            if self.data.__class__.__name__ !="Data2D":
1833                if item in self.orientation_params:
1834                    continue
1835            #Select parameters to fit for list of primary parameters
1836            if item[0].GetValue():
1837                if not (item in self.param_toFit):
1838                    self.param_toFit.append(item ) 
1839            else:
1840                #remove parameters from the fitting list
1841                if item in self.param_toFit:
1842                    self.param_toFit.remove(item)
1843
1844        #Select parameters to fit for list of fittable parameters with dispersion         
1845        for item in self.fittable_param:
1846            #Skip t ifhe angle parameters if 1D data
1847            if self.data.__class__.__name__ !="Data2D":
1848                if item in self.orientation_params:
1849                    continue
1850            if item[0].GetValue():
1851                if not (item in self.param_toFit):
1852                    self.param_toFit.append(item) 
1853            else:
1854                #remove parameters from the fitting list
1855                if item in self.param_toFit:
1856                    self.param_toFit.remove(item)
1857
1858        #Calculate num. of angle parameters
1859        if self.data.__class__.__name__ =="Data2D": 
1860            len_orient_para = 0
1861        else:
1862            len_orient_para = len(self.orientation_params)  #assume even len
1863        #Total num. of angle parameters
1864        if len(self.fittable_param) > 0:
1865            len_orient_para *= 2
1866        #Set the value of checkbox that selected every checkbox or not           
1867        if len(self.parameters)+len(self.fittable_param)-len_orient_para ==len(self.param_toFit):
1868            self.cb1.SetValue(True)
1869        else:
1870            self.cb1.SetValue(False)
1871        self.save_current_state_fit()
1872        if event !=None:
1873            #self._undo.Enable(True)
1874            ## post state to fit panel
1875            event = PageInfoEvent(page = self)
1876            wx.PostEvent(self.parent, event) 
1877     
1878   
1879       
1880    def set_model_param_sizer(self, model):
1881        """
1882            Build the panel from the model content
1883            @param model: the model selected in combo box for fitting purpose
1884        """
1885        self.sizer3.Clear(True)
1886        self.parameters = []
1887        self.param_toFit=[]
1888        self.fittable_param=[]
1889        self.fixed_param=[]
1890        self.orientation_params=[]
1891        self.orientation_params_disp=[]
1892       
1893        if model ==None:
1894            self.sizer3.Layout()
1895            self.SetScrollbars(20,20,25,65)
1896            return
1897        ## the panel is drawn using the current value of the fit engine
1898        if self.engine_type==None and self.manager !=None:
1899            self.engine_type= self.manager._return_engine_type()
1900
1901           
1902        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
1903        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1904        sizer = wx.GridBagSizer(5,5)
1905        ## save the current model
1906        self.model = model
1907           
1908        keys = self.model.getParamList()
1909        #list of dispersion paramaters
1910        self.disp_list=self.model.getDispParamList()
1911
1912        keys.sort()
1913   
1914        iy = 0
1915        ix = 0
1916        select_text = "Uncheck all to fix"
1917        self.cb1 = wx.CheckBox(self, -1,str(select_text), (10, 10))
1918        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
1919        self.cb1.SetValue(True)
1920       
1921        sizer.Add(self.cb1,(iy, ix),(1,1),\
1922                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1923        ix +=1
1924        self.text2_2 = wx.StaticText(self, -1, 'Values')
1925        sizer.Add(self.text2_2,(iy, ix),(1,1),\
1926                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1927        ix +=2 
1928        self.text2_3 = wx.StaticText(self, -1, 'Errors')
1929        sizer.Add(self.text2_3,(iy, ix),(1,1),\
1930                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1931        self.text2_3.Hide()
1932        ix +=1 
1933        self.text2_min = wx.StaticText(self, -1, 'Min')
1934        sizer.Add(self.text2_min,(iy, ix),(1,1),\
1935                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1936        self.text2_min.Hide()
1937        ix +=1 
1938        self.text2_max = wx.StaticText(self, -1, 'Max')
1939        sizer.Add(self.text2_max,(iy, ix),(1,1),\
1940                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1941        self.text2_max.Hide()
1942        ix += 1
1943        self.text2_4 = wx.StaticText(self, -1, '[Units]')
1944        sizer.Add(self.text2_4,(iy, ix),(1,1),\
1945                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1946        self.text2_4.Hide()
1947        if self.engine_type=="park":
1948            self.text2_max.Show(True)
1949            self.text2_min.Show(True)
1950       
1951        for item in keys:
1952            if not item in self.disp_list and not item in self.model.orientation_params:
1953               
1954                ##prepare a spot to store errors
1955                if not self.model.details.has_key(item):
1956                    self.model.details [item] = ["",None,None] 
1957         
1958                iy += 1
1959                ix = 0
1960                ## add parameters name with checkbox for selecting to fit
1961                cb = wx.CheckBox(self, -1, item )
1962                cb.SetValue(True)
1963                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
1964                sizer.Add( cb,( iy, ix),(1,1),
1965                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
1966               
1967                ## add parameter value
1968                ix += 1
1969                value= self.model.getParam(item)
1970                ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
1971                                    style=wx.TE_PROCESS_ENTER)
1972               
1973                ctl1.SetValue(format_number(value))
1974                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
1975                ## text to show error sign
1976                ix += 1
1977                text2=wx.StaticText(self, -1, '+/-')
1978                sizer.Add(text2,(iy, ix),(1,1),\
1979                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
1980                text2.Hide() 
1981                ix += 1
1982                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
1983                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1984                ctl2.Hide()
1985               
1986                ix += 1
1987                ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1988                                               text_enter_callback = self._onparamRangeEnter)
1989     
1990                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1991                ctl3.Hide()
1992       
1993                ix += 1
1994                ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
1995                                               text_enter_callback = self._onparamRangeEnter)
1996                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1997     
1998                ctl4.Hide()
1999
2000                if self.engine_type=="park":
2001                    ctl3.Show(True)
2002                    ctl4.Show(True)
2003                ix +=1
2004                # Units
2005                if self.model.details.has_key(item):
2006                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
2007                else:
2008                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
2009                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2010                   
2011                ##[cb state, name, value, "+/-", error of fit, min, max , units]
2012                self.parameters.append([cb,item, ctl1,
2013                                        text2,ctl2, ctl3, ctl4,units])
2014             
2015        iy+=1
2016        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
2017       
2018        # type can be either Guassian or Array
2019        if len(self.model.dispersion.values())>0:
2020            type= self.model.dispersion.values()[0]["type"]
2021        else:
2022            type = "Gaussian"
2023           
2024        iy += 1
2025        ix = 0
2026        #Add tile for orientational angle
2027        for item in keys:
2028            if item in self.model.orientation_params:       
2029                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
2030                sizer.Add(orient_angle,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
2031                if not self.data.__class__.__name__ =="Data2D":
2032                    orient_angle.Hide()
2033                else:
2034                    orient_angle.Show(True)
2035                break
2036     
2037        #For Gaussian only
2038        if type.lower() != "array":
2039            for item in self.model.orientation_params:
2040                if not item in self.disp_list:
2041                    ##prepare a spot to store min max
2042                    if not self.model.details.has_key(item):
2043                        self.model.details [item] = ["",None,None] 
2044                         
2045                    iy += 1
2046                    ix = 0
2047                    ## add parameters name with checkbox for selecting to fit
2048                    cb = wx.CheckBox(self, -1, item )
2049                    cb.SetValue(False)
2050                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
2051                    if self.data.__class__.__name__ =="Data2D":
2052                        cb.Show(True)
2053                    else:
2054                        cb.Hide()
2055                    sizer.Add( cb,( iy, ix),(1,1),
2056                                 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
2057   
2058                    ## add parameter value
2059                    ix += 1
2060                    value= self.model.getParam(item)
2061                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
2062                                        style=wx.TE_PROCESS_ENTER)
2063                   
2064                    ctl1.SetValue(format_number(value))
2065                    if self.data.__class__.__name__ =="Data2D":
2066                        ctl1.Show(True)
2067                    else:
2068                        ctl1.Hide()
2069                    sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
2070                    ## text to show error sign
2071                    ix += 1
2072                    text2=wx.StaticText(self, -1, '+/-')
2073                    sizer.Add(text2,(iy, ix),(1,1),\
2074                                    wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
2075                    text2.Hide() 
2076                    ix += 1
2077                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=0)
2078                   
2079                    sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2080                    ctl2.Hide()
2081                   
2082                   
2083                    ix += 1
2084                    ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
2085                                                   text_enter_callback = self._onparamRangeEnter)
2086               
2087                    sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2088                    ctl3.Hide()
2089                 
2090                    ix += 1
2091                    ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER,
2092                                                   text_enter_callback = self._onparamRangeEnter)
2093                    sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2094                   
2095                    ctl4.Hide()
2096                   
2097                    if self.engine_type =="park" and self.data.__class__.__name__ =="Data2D":                     
2098                        ctl3.Show(True)
2099                        ctl4.Show(True)
2100                   
2101                    ix +=1
2102                    # Units
2103                    if self.model.details.has_key(item):
2104                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
2105                    else:
2106                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
2107                    if self.data.__class__.__name__ =="Data2D":
2108                        units.Show(True)
2109                   
2110                    else:
2111                        units.Hide()
2112                   
2113                    sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2114                                         
2115                    ##[cb state, name, value, "+/-", error of fit, min, max , units]
2116                    self.parameters.append([cb,item, ctl1,
2117                                            text2,ctl2, ctl3, ctl4,units])
2118                    self.orientation_params.append([cb,item, ctl1,
2119                                            text2,ctl2, ctl3, ctl4,units])
2120             
2121        iy+=1
2122       
2123        #Display units text on panel
2124        for item in keys:   
2125            if self.model.details.has_key(item):
2126                self.text2_4.Show()
2127        #Fill the list of fittable parameters
2128        self.select_all_param(event=None)
2129
2130        self.save_current_state_fit()
2131        boxsizer1.Add(sizer)
2132        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
2133        self.sizer3.Layout()
2134        self.Layout()
2135        self.Refresh()
2136        self.SetScrollbars(20,20,25,65)
2137
2138class BGTextCtrl(wx.TextCtrl):
2139    """
2140        Text control used to display outputs.
2141        No editing allowed. The background is
2142        grayed out. User can't select text.
2143    """
2144    def __init__(self, *args, **kwds):
2145        wx.TextCtrl.__init__(self, *args, **kwds)
2146        self.SetEditable(False)
2147        self.SetBackgroundColour(self.GetParent().GetBackgroundColour())
2148       
2149        # Bind to mouse event to avoid text highlighting
2150        # The event will be skipped once the call-back
2151        # is called.
2152        self.Bind(wx.EVT_MOUSE_EVENTS, self._click)
2153       
2154    def _click(self, event):
2155        """
2156            Prevent further handling of the mouse event
2157            by not calling Skip().
2158        """ 
2159        pass
2160       
2161class HelpWindow(wx.Frame):
2162    def __init__(self, parent, id, title):
2163        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
2164       
2165        from sans.models.CylinderModel import CylinderModel
2166        model = CylinderModel()
2167       
2168        from danse.common.plottools.plottables import Data1D
2169        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
2170   
2171        from fitpanel import PageInfo
2172        myinfo = PageInfo(self,  model, data=data )
2173       
2174        ## add data
2175       
2176        from models import ModelList
2177        mylist= ModelList()
2178
2179        from sans.models.SphereModel import SphereModel
2180        from sans.models.SquareWellStructure import SquareWellStructure
2181        from sans.models.DebyeModel import DebyeModel
2182        from sans.models.LineModel import LineModel
2183        name= "shapes"
2184        list1= [SphereModel]
2185        mylist.set_list( name, list1)
2186       
2187        name= "Shape-independent"
2188        list1= [DebyeModel]
2189        mylist.set_list( name, list1)
2190       
2191        name= "Structure Factors"
2192        list1= [SquareWellStructure]
2193        mylist.set_list( name, list1)
2194       
2195        name= "Added models"
2196        list1= [LineModel]
2197        mylist.set_list( name, list1)
2198       
2199        myinfo.model_list_box = mylist.get_list()
2200       
2201        self.page = FitPage(self, myinfo) 
2202       
2203        self.Centre()
2204        self.Show(True)
2205 
2206if __name__=="__main__":
2207    app = wx.App()
2208    HelpWindow(None, -1, 'HelpWindow')
2209    app.MainLoop()
2210               
Note: See TracBrowser for help on using the repository browser.