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

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

remove double call of draw panel in fitpanel select model

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