source: sasview/fittingview/src/sans/perspectives/fitting/fitpage.py @ 56acb5d

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 56acb5d was ac2b835, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Pep-8-ification

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