source: sasview/fittingview/src/sans/perspectives/fitting/fitpage.py @ 397b4e7

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 397b4e7 was 0d795bf, checked in by Jae Cho <jhjcho@…>, 12 years ago

more fixes in saving custom slit information

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