source: sasview/sansview/perspectives/fitting/fitpage.py @ 71bd773

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

remove bug

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