source: sasview/sansview/perspectives/fitting/fitpage.py @ 10f3b23

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

working on guiframe

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