source: sasview/fittingview/src/sans/perspectives/fitting/fitpage.py @ 0d795bf

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

more fixes in saving custom slit information

  • Property mode set to 100644
File size: 131.0 KB
Line 
1"""
2    FitPanel class contains fields allowing to display results when
3    fitting  a model and one data
4"""
5import sys
6import wx
7import wx.lib.newevent
8import numpy
9import copy
10import math
11import time
12from sans.guiframe.events import StatusEvent
13from sans.guiframe.events import NewPlotEvent
14from sans.guiframe.dataFitting import check_data_validity
15from sans.guiframe.utils import format_number
16from sans.guiframe.utils import check_float
17
18(Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent()
19_BOX_WIDTH = 76
20_DATA_BOX_WIDTH = 300
21SMEAR_SIZE_L = 0.00
22SMEAR_SIZE_H = 0.00
23
24from sans.perspectives.fitting.basepage import BasicPage as BasicPage
25from sans.perspectives.fitting.basepage import PageInfoEvent as PageInfoEvent
26from sans.models.qsmearing import smear_selection
27
28
29class FitPage(BasicPage):
30    """
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
35        on fit Panel window.
36    """
37
38    def __init__(self, parent, color='rand'):
39        """
40        Initialization of the Panel
41        """
42        BasicPage.__init__(self, parent, color=color)
43       
44        ## draw sizer
45        self._fill_data_sizer()
46        self.is_2D = None
47        self.fit_started = False
48        self.weightbt_string = None
49        self.m_name = None
50        # get smear info from data
51        self._get_smear_info()
52        self._fill_model_sizer(self.sizer1)
53        self._get_defult_custom_smear()
54        self._fill_range_sizer()
55        self._set_smear(self.data)
56        self.Bind(EVT_CHI2_UPDATE, self.on_complete_chisqr)
57        # bind key event
58        self.Bind(wx.EVT_RIGHT_DOWN, self.on_right_down)
59        self._set_bookmark_flag(False)
60        self._set_save_flag(False)
61        self._set_preview_flag(False)
62        self._set_copy_flag(False)
63        self._set_paste_flag(False)
64        self.btFit.SetFocus()
65        self.enable_fit_button()
66        self.fill_data_combobox(data_list=self.data_list)
67        #create a default data for an empty panel
68        self.create_default_data()
69   
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       
77    def _fill_data_sizer(self):
78        """
79        fill sizer 0 with data info
80        """
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)
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)
95        sizer_data.Add((0, 5))
96        boxsizer1.Add(sizer_data, 0, wx.ALL, 10)
97        self.sizer0.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
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()
116        if len(data_list) > 0:
117            #find the maximum range covering all data
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
128            self.qmax_x = self.qmax_data_set
129            self.state.qmin = self.qmin_x
130            self.state.qmax = self.qmax_x
131        is_data = False
132        for data in self.data_list:
133            if data is not None:
134                self.dataSource.Append(str(data.name), clientData=data)
135                if not is_data:
136                    is_data = check_data_validity(data)
137        self.dataSource.SetSelection(0)
138        self.on_select_data(event=None)
139               
140    def on_select_data(self, event=None):
141        """
142        On_select_data
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   
152    def _on_fit_complete(self):
153        """
154        When fit is complete ,reset the fit button label.
155        """
156        self.fit_started = False
157        self.set_fitbutton()
158       
159    def _is_2D(self):
160        """
161        Check if data_name is Data2D
162       
163        :return: True or False
164       
165        """
166        if self.data.__class__.__name__ == "Data2D" or \
167                        self.enable2D:
168            return True
169        return False
170           
171    def _on_engine_change(self, name):
172        """
173        get the current name of the fit engine type
174         and update the panel accordingly
175        """
176       
177        self.engine_type = str(name)
178        self.state.engine_type = self.engine_type
179        if not self.is_mac:
180            if len(self.parameters) == 0:
181                self.Layout()
182                return
183            self.Layout()
184            self.Refresh()
185       
186    def _fill_range_sizer(self):
187        """
188        Fill the sizer containing the plotting range
189        add  access to npts
190        """
191        is_2Ddata = False
192       
193        # Check if data is 2D
194        if self.data.__class__.__name__ == "Data2D" or \
195                        self.enable2D:
196            is_2Ddata = True
197           
198        title = "Fitting"
199        #smear messages & titles
200        smear_message_none = "No smearing is selected..."
201        smear_message_dqdata = "The dQ data is being used for smearing..."
202        smear_message_2d = \
203              "Higher accuracy is very time-expensive. Use it with care..."
204        smear_message_new_ssmear = \
205              "Please enter only the value of interest to customize smearing..."
206        smear_message_new_psmear = \
207              "Please enter both; the dQ will be generated by interpolation..."
208        smear_message_2d_x_title = "<dQp>[1/A]:"
209        smear_message_2d_y_title = "<dQs>[1/A]:"
210        smear_message_pinhole_min_title = "dQ_low[1/A]:"
211        smear_message_pinhole_max_title = "dQ_high[1/A]:"
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()
216       
217        #Sizers
218        box_description_range = wx.StaticBox(self, -1, str(title))
219        box_description_range.SetForegroundColour(wx.BLUE)
220        boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL)
221        self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL)
222        sizer_smearer = wx.BoxSizer(wx.HORIZONTAL)
223        self.sizer_new_smear = wx.BoxSizer(wx.HORIZONTAL)
224        self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL)
225        sizer_chi2 = wx.BoxSizer(wx.VERTICAL)
226        smear_set_box = wx.StaticBox(self, -1, 'Set Instrumental Smearing')
227        sizer_smearer_box = wx.StaticBoxSizer(smear_set_box, wx.HORIZONTAL)
228        sizer_smearer_box.SetMinSize((_DATA_BOX_WIDTH, 60))
229       
230        weighting_set_box = wx.StaticBox(self, -1, \
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.
236        self.dI_noweight = wx.RadioButton(self, -1, 'No Weighting',
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|')
241        self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting,
242                  id=self.dI_noweight.GetId())
243        self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting,
244                  id=self.dI_didata.GetId())
245        self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting,
246                  id=self.dI_sqrdata.GetId())
247        self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting,
248                  id=self.dI_idata.GetId())
249        self.dI_didata.SetValue(True)
250        # add 4 types of weighting to the sizer
251        sizer_weighting.Add(self.dI_noweight, 0, wx.LEFT, 10)
252        sizer_weighting.Add((14, 10))
253        sizer_weighting.Add(self.dI_didata)
254        sizer_weighting.Add((14, 10))
255        sizer_weighting.Add(self.dI_sqrdata)
256        sizer_weighting.Add((14, 10))
257        sizer_weighting.Add(self.dI_idata)
258        sizer_weighting.Add((10, 10))
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       
265        sizer_fit = wx.GridSizer(2, 4, 2, 6)
266       
267        # combobox for smear2d accuracy selection
268        self.smear_accuracy = wx.ComboBox(self, -1, size=(50, -1),
269                                          style=wx.CB_READONLY)
270        self._set_accuracy_list()
271        self.smear_accuracy.SetValue(self.smear2d_accuracy)
272        self.smear_accuracy.SetSelection(0)
273        self.smear_accuracy.SetToolTipString(\
274            "'Higher' uses more Gaussian points for smearing computation.")
275                   
276        wx.EVT_COMBOBOX(self.smear_accuracy, -1, self._on_select_accuracy)
277
278        #Fit button
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())
282        self.btFit.SetToolTipString("Start fitting.")
283       
284        #textcntrl for custom resolution
285        self.smear_pinhole_max = self.ModelTextCtrl(self, -1,
286                            size=(_BOX_WIDTH - 25, 20),
287                            style=wx.TE_PROCESS_ENTER,
288                            text_enter_callback=self.onPinholeSmear)
289        self.smear_pinhole_min = self.ModelTextCtrl(self, -1,
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)
297        self.smear_slit_width = self.ModelTextCtrl(self, -1,
298                            size=(_BOX_WIDTH - 25, 20),
299                            style=wx.TE_PROCESS_ENTER,
300                            text_enter_callback=self.onSlitSmear)
301
302        ## smear
303        self.smear_data_left = BGTextCtrl(self, -1,
304                                         size=(_BOX_WIDTH - 25, 20), style=0)
305        self.smear_data_left.SetValue(str(self.dq_l))
306        self.smear_data_right = BGTextCtrl(self, -1,
307                                        size=(_BOX_WIDTH - 25, 20), style=0)
308        self.smear_data_right.SetValue(str(self.dq_r))
309
310        #set default values for smear
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
316        #Filling the sizer containing instruments smearing info.
317        self.disable_smearer = wx.RadioButton(self, -1,
318                                              'None', style=wx.RB_GROUP)
319        self.enable_smearer = wx.RadioButton(self, -1,
320                                             'Use dQ Data')
321        #self.enable_smearer.SetToolTipString(
322        #"Click to use the loaded dQ data for smearing.")
323        self.pinhole_smearer = wx.RadioButton(self, -1,
324                                              'Custom Pinhole Smear')
325        #self.pinhole_smearer.SetToolTipString
326        #("Click to input custom resolution for pinhole smearing.")
327        self.slit_smearer = wx.RadioButton(self, -1, 'Custom Slit Smear')
328        #self.slit_smearer.SetToolTipString
329        #("Click to input custom resolution for slit smearing.")
330        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear,
331                  id=self.disable_smearer.GetId())
332        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear,
333                  id=self.enable_smearer.GetId())
334        self.Bind(wx.EVT_RADIOBUTTON, self.onPinholeSmear,
335                  id=self.pinhole_smearer.GetId())
336        self.Bind(wx.EVT_RADIOBUTTON, self.onSlitSmear,
337                  id=self.slit_smearer.GetId())
338        self.disable_smearer.SetValue(True)
339       
340        # add 4 types of smearing to the sizer
341        sizer_smearer.Add(self.disable_smearer, 0, wx.LEFT, 10)
342        sizer_smearer.Add((10, 10))
343        sizer_smearer.Add(self.enable_smearer)
344        sizer_smearer.Add((10, 10))
345        sizer_smearer.Add(self.pinhole_smearer)
346        sizer_smearer.Add((10, 10))
347        sizer_smearer.Add(self.slit_smearer)
348        sizer_smearer.Add((10, 10))
349       
350        # StaticText for chi2, N(for fitting), Npts
351        self.tcChi = BGTextCtrl(self, -1, "-", size=(75, 20), style=0)
352        self.tcChi.SetToolTipString("Chi2/Npts(Fit)")
353        self.Npts_fit = BGTextCtrl(self, -1, "-", size=(75, 20), style=0)
354        self.Npts_fit.SetToolTipString(\
355                            " Npts : number of points selected for fitting")
356        self.Npts_total = self.ModelTextCtrl(self, -1,
357                        size=(_BOX_WIDTH, 20),
358                        style=wx.TE_PROCESS_ENTER,
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       
364        # Update and Draw button
365        self.draw_button = wx.Button(self, wx.NewId(),
366                                     'Compute', size=(88, 24))
367        self.draw_button.Bind(wx.EVT_BUTTON, \
368                              self._onDraw, id=self.draw_button.GetId())
369        self.draw_button.SetToolTipString("Compute and Draw.")
370       
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')
374        box_description_3.SetToolTipString( \
375                                " Total Npts : total number of data points")
376       
377        sizer_fit.Add(box_description_1, 0, 0)
378        sizer_fit.Add(box_description_2, 0, 0)
379        sizer_fit.Add(box_description_3, 0, 0)
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)
384        sizer_fit.Add(self.btFit, 0, 0)
385
386        # StaticText for smear
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)
397        self.smear_description_smear_type.SetValue(str(self.dq_l))
398        self.SetBackgroundColour(self.GetParent().GetBackgroundColour())
399        self.smear_description_2d = wx.StaticText(self, -1,
400                                    smear_message_2d, style=wx.ALIGN_LEFT)
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,
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)
407        self.smear_description_2d_x.SetToolTipString(\
408                                        "  dQp(parallel) in q_r direction.")
409        self.smear_description_2d_y = wx.StaticText(self, -1,
410                            smear_message_2d_y_title, style=wx.ALIGN_LEFT)
411        self.smear_description_2d_y.SetToolTipString(\
412                                    " dQs(perpendicular) in q_phi direction.")
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)
445
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,
454                                  0, wx.CENTER, 10 )
455        self.sizer_new_smear.Add(self.smear_description_pin_max,
456                                  0, wx.CENTER, 10 )
457        self.sizer_new_smear.Add(self.smear_description_slit_width,
458                                  0, wx.CENTER, 10 )
459
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)
463           
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)
466        self.sizer_set_smearer.Add((5, 2))
467        self.sizer_set_smearer.Add(self.sizer_new_smear, 0, wx.CENTER, 10)
468       
469        # add all to chi2 sizer
470        sizer_smearer_box.Add(self.sizer_set_smearer)
471        sizer_chi2.Add(sizer_smearer_box)
472        sizer_chi2.Add((-1, 5))
473        sizer_chi2.Add(weighting_box)
474        sizer_chi2.Add((-1, 5))
475       
476        # hide all smear messages and textctrl
477        self._hide_all_smear_info()
478       
479        # get smear_selection
480        self.current_smearer = smear_selection(self.data, self.model)
481
482        # Show only the relevant smear messages, etc
483        if self.current_smearer == None:
484            if not is_2Ddata:
485                self.smear_description_none.Show(True)
486                self.enable_smearer.Disable()
487            else:
488                self.smear_description_none.Show(True)
489                self.slit_smearer.Disable()
490            if self.data == None:
491                self.slit_smearer.Disable()
492                self.pinhole_smearer.Disable()
493                self.enable_smearer.Disable()
494        else:
495            self._show_smear_sizer()
496        boxsizer_range.Add(self.sizer_set_masking)
497        #2D data? default
498        is_2Ddata = False
499       
500        #check if it is 2D data
501        if self.data.__class__.__name__ == "Data2D" or self.enable2D:
502            is_2Ddata = True
503           
504        self.sizer5.Clear(True)
505     
506        self.qmin = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
507                                    style=wx.TE_PROCESS_ENTER,
508                                    text_enter_callback=self._onQrangeEnter)
509        self.qmin.SetValue(str(self.qmin_x))
510        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
511     
512        self.qmax = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
513                                       style=wx.TE_PROCESS_ENTER,
514                                       text_enter_callback=self._onQrangeEnter)
515        self.qmax.SetValue(str(self.qmax_x))
516        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
517        id = wx.NewId()
518        self.reset_qrange = wx.Button(self, id, 'Reset', size=(77, 20))
519     
520        self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked, id=id)
521        self.reset_qrange.SetToolTipString("Reset Q range to the default")
522     
523        sizer = wx.GridSizer(2, 4, 2, 6)
524
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())
528        self.btEditMask.SetToolTipString("Edit Mask.")
529        self.EditMask_title = wx.StaticText(self, -1, ' Masking(2D)')
530
531        sizer.Add(wx.StaticText(self, -1, '   Q range'))
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)
535        sizer.Add(self.reset_qrange)
536        sizer.Add(self.qmin)
537        sizer.Add(self.qmax)
538        #sizer.Add(self.theory_npts_tcrtl)
539        sizer.Add(self.btEditMask)
540        boxsizer_range.Add(sizer_chi2)
541        boxsizer_range.Add((10, 10))
542        boxsizer_range.Add(sizer)
543       
544        boxsizer_range.Add((10, 15))
545        boxsizer_range.Add(sizer_fit)
546        if is_2Ddata:
547            self.btEditMask.Enable()
548            self.EditMask_title.Enable()
549        else:
550            self.btEditMask.Disable()
551            self.EditMask_title.Disable()
552        ## save state
553        self.save_current_state()
554        self.sizer5.Add(boxsizer_range, 0, wx.EXPAND | wx.ALL, 10)
555        self.sizer5.Layout()
556
557       
558    def _set_sizer_dispersion(self):
559        """
560        draw sizer with gaussian dispersity parameters
561        """
562        self.fittable_param = []
563        self.fixed_param = []
564        self.orientation_params_disp = []
565
566        self.sizer4_4.Clear(True)
567        if self.model == None:
568            ##no model is selected
569            return
570        if not self.enable_disp.GetValue():
571            ## the user didn't select dispersity display
572            return
573           
574        self._reset_dispersity()
575       
576        ## fill a sizer with the combobox to select dispersion type
577        model_disp = wx.StaticText(self, -1, 'Function')
578        CHECK_STATE = self.cb1.GetValue()
579        import sans.models.dispersion_models
580        self.polydisp = sans.models.dispersion_models.models
581
582        ix = 0
583        iy = 0
584        disp = wx.StaticText(self, -1, ' ')
585        self.sizer4_4.Add(disp, (iy, ix), (1, 1),
586                          wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
587        ix += 1
588        values = wx.StaticText(self, -1, 'PD[ratio]')
589        polytext = "Polydispersity (= STD/mean); "
590        polytext += "the standard deviation over the mean value."
591        values.SetToolTipString(polytext)
592
593        self.sizer4_4.Add(values, (iy, ix), (1, 1),
594                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
595        ix += 2
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)
601        self.sizer4_4.Add(self.text_disp_1, (iy, ix), (1, 1), \
602                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
603       
604        ix += 1
605        self.text_disp_min = wx.StaticText(self, -1, 'Min')
606        self.sizer4_4.Add(self.text_disp_min, (iy, ix), (1, 1), \
607                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
608
609        ix += 1
610        self.text_disp_max = wx.StaticText(self, -1, 'Max')
611        self.sizer4_4.Add(self.text_disp_max, (iy, ix), (1, 1),
612                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
613       
614        ix += 1
615        npts = wx.StaticText(self, -1, 'Npts')
616        npts.SetToolTipString("Number of sampling points for the numerical\n\
617        integration over the distribution function.")
618        self.sizer4_4.Add(npts, (iy, ix), (1, 1),
619                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
620        ix += 1
621        nsigmas = wx.StaticText(self, -1, 'Nsigs')
622        nsigmas.SetToolTipString("Number of sigmas between which the range\n\
623         of the distribution function will be used for weighting. \n\
624        The value '3' covers 99.5% for Gaussian distribution \n\
625        function. Note: Not recommended to change this value.")
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)
631       
632        if self.engine_type == "park":
633            self.text_disp_max.Show(True)
634            self.text_disp_min.Show(True)
635
636        for item in self.model.dispersion.keys():
637            if not self.magnetic_on:
638                if item in self.model.magnetic_params:
639                    continue
640            if not item in self.model.orientation_params:
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]
649
650                iy += 1
651                for p in self.model.dispersion[item].keys():
652       
653                    if p == "width":
654                        ix = 0
655                        cb = wx.CheckBox(self, -1, name0, (10, 10))
656                        cb.SetValue(CHECK_STATE)
657                        cb.SetToolTipString("Check mark to fit")
658                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
659                        self.sizer4_4.Add(cb, (iy, ix), (1, 1),
660                                wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
661                        ix = 1
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)
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)
671                        ctl1.SetValue(str(format_number(value, True)))
672                        self.sizer4_4.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
673                        ## text to show error sign
674                        ix = 2
675                        text2 = wx.StaticText(self, -1, '+/-')
676                        self.sizer4_4.Add(text2, (iy, ix), (1, 1),
677                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
678                        if not self.is_mac:
679                            text2.Hide()
680
681                        ix = 3
682                        ctl2 = wx.TextCtrl(self, -1,
683                                           size=(_BOX_WIDTH / 1.3, 20),
684                                           style=0)
685                 
686                        self.sizer4_4.Add(ctl2, (iy, ix), (1, 1),
687                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
688                        if not self.is_mac:
689                            ctl2.Hide()
690
691                        ix = 4
692                        ctl3 = self.ModelTextCtrl(self, -1,
693                                                  size=(_BOX_WIDTH / 2, 20),
694                                                  style=wx.TE_PROCESS_ENTER,
695                                text_enter_callback=self._onparamRangeEnter)
696                       
697                        self.sizer4_4.Add(ctl3, (iy, ix), (1, 1),
698                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
699                       
700                        ix = 5
701                        ctl4 = self.ModelTextCtrl(self, -1,
702                                                  size=(_BOX_WIDTH / 2, 20),
703                                                  style=wx.TE_PROCESS_ENTER,
704                            text_enter_callback=self._onparamRangeEnter)
705                       
706                        self.sizer4_4.Add(ctl4, (iy, ix), (1, 1),
707                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
708
709                        if self.engine_type == "park":
710                            ctl3.Show(True)
711                            ctl4.Show(True)
712                                                             
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])
738
739                ix = 8
740                disp_box = wx.ComboBox(self, -1, size=(65, -1),
741                                       style=wx.CB_READONLY, name='%s' % name1)
742                for key, value in self.polydisp.iteritems():
743                    name_disp = str(key)
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])
750                           
751        ix = 0
752        iy += 1
753        self.sizer4_4.Add((20, 20), (iy, ix), (1, 1),
754                          wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
755        first_orient = True
756        for item in self.model.dispersion.keys():
757            if not self.magnetic_on:
758                if item in self.model.magnetic_params:
759                    continue
760            if  item in self.model.orientation_params:
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"
767               
768                if not name1 in self.model.details:
769                    self.model.details[name1] = ["", None, None]
770 
771                iy += 1
772                for p in self.model.dispersion[item].keys():
773       
774                    if p == "width":
775                        ix = 0
776                        cb = wx.CheckBox(self, -1, name0, (10, 10))
777                        cb.SetValue(CHECK_STATE)
778                        cb.SetToolTipString("Check mark to fit")
779                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
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 \
783                                    self.enable2D:
784                            cb.Show(True)
785                        elif cb.IsShown():
786                            cb.Hide()
787                        ix = 1
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)
792                        poly_tip = "Absolute Sigma for %s." % item
793                        ctl1.SetToolTipString(poly_tip)
794                        ctl1.SetValue(str(format_number(value, True)))
795                        if self.data.__class__.__name__ == "Data2D" or \
796                                    self.enable2D:
797                            if first_orient:
798                                values.SetLabel('PD[ratio], Sig[deg]')
799                                poly_text = "PD(polydispersity for lengths):\n"
800                                poly_text += "It should be a value between"
801                                poly_text += "0 and 1\n"
802                                poly_text += "Sigma for angles: \n"
803                                poly_text += "It is the STD (ratio*mean)"
804                                poly_text += " of the distribution.\n "
805                           
806                                values.SetToolTipString(poly_text)
807                                first_orient = False
808                            ctl1.Show(True)
809                        elif ctl1.IsShown():
810                            ctl1.Hide()
811                       
812                        self.sizer4_4.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
813                        ## text to show error sign
814                        ix = 2
815                        text2 = wx.StaticText(self, -1, '+/-')
816                        self.sizer4_4.Add(text2, (iy, ix), (1, 1),
817                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
818
819                        text2.Hide()
820
821                        ix = 3
822                        ctl2 = wx.TextCtrl(self, -1,
823                                           size=(_BOX_WIDTH / 1.3, 20),
824                                           style=0)
825                   
826                        self.sizer4_4.Add(ctl2, (iy, ix), (1, 1),
827                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
828
829                        ctl2.Hide()
830                        if self.data.__class__.__name__ == "Data2D" or \
831                                self.enable2D:
832                            if self.is_mac:
833                                text2.Show(True)
834                                ctl2.Show(True)
835                           
836                        ix = 4
837                        ctl3 = self.ModelTextCtrl(self, -1,
838                                                  size=(_BOX_WIDTH / 2, 20),
839                                                  style=wx.TE_PROCESS_ENTER,
840                                text_enter_callback=self._onparamRangeEnter)
841
842                        self.sizer4_4.Add(ctl3, (iy, ix), (1, 1),
843                                          wx.EXPAND | wx.ADJUST_MINSIZE, 0)
844
845                        ctl3.Hide()
846               
847                        ix = 5
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)
854                        ctl4.Hide()
855                       
856                        if self.data.__class__.__name__ == "Data2D" or \
857                                self.enable2D:
858                            ctl3.Show(True)
859                            ctl4.Show(True)
860                             
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)
896
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])
902
903                ix = 8
904                disp_box = wx.ComboBox(self, -1, size=(65, -1),
905                                style=wx.CB_READONLY, name='%s' % name1)
906                for key, value in self.polydisp.iteritems():
907                    name_disp = str(key)
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,
913                                            ctl2, ctl3, ctl4, disp_box])
914                self.orientation_params_disp.append([cb, name1, ctl1,
915                                            text2, ctl2, ctl3, ctl4, disp_box])
916                       
917                if self.data.__class__.__name__ == "Data2D" or \
918                                self.enable2D:
919                    disp_box.Show(True)
920                else:
921                    disp_box.Hide()
922       
923        self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict)
924         
925        self.state.model = self.model.clone()
926        ## save state into
927        self.state.cb1 = self.cb1.GetValue()
928        self._copy_parameters_state(self.parameters, self.state.parameters)
929        self._copy_parameters_state(self.orientation_params_disp,
930                                     self.state.orientation_params_disp)
931        self._copy_parameters_state(self.fittable_param,
932                                    self.state.fittable_param)
933        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
934
935        wx.PostEvent(self.parent,
936                     StatusEvent(status=" Selected Distribution: Gaussian"))
937        #Fill the list of fittable parameters
938        #self.select_all_param(event=None)
939        self.get_all_checked_params()
940        self.Layout()
941
942    def _onDraw(self, event):
943        """
944        Update and Draw the model
945        """
946        if self.model == None:
947            msg = "Please select a Model first..."
948            wx.MessageBox(msg, 'Info')
949            return
950        """
951        if not self.data.is_data:
952            self.npts_x = self.Npts_total.GetValue()
953            self.Npts_fit.SetValue(self.npts_x)
954            self.create_default_data()
955        """
956        flag = self._update_paramv_on_fit()
957   
958        wx.CallAfter(self._onparamEnter_helper)
959        if not flag:
960            msg = "The parameters are invalid"
961            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
962            return
963       
964    def _onFit(self, event):
965        """
966        Allow to fit
967        """
968        if event != None:
969            event.Skip()
970        if self.fit_started:
971            self._StopFit()
972            self.fit_started = False
973            wx.CallAfter(self.set_fitbutton)
974            return
975
976        if len(self.parent._manager.fit_thread_list) > 0 and\
977                    self.parent._manager._fit_engine != "park" and\
978                    self._manager.sim_page != None and \
979                    self._manager.sim_page.uid == self.uid:
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           
984        if self.data is None:
985            msg = "Please get Data first..."
986            wx.MessageBox(msg, 'Info')
987            wx.PostEvent(self._manager.parent,
988                         StatusEvent(status="Fit: %s" % msg))
989            return
990        if self.model is None:
991            msg = "Please select a Model first..."
992            wx.MessageBox(msg, 'Info')
993            wx.PostEvent(self._manager.parent,
994                         StatusEvent(status="Fit: %s" % msg, type="stop"))
995            return
996       
997        if len(self.param_toFit) <= 0:
998            msg = "Select at least one parameter to fit"
999            wx.MessageBox(msg, 'Info')
1000            wx.PostEvent(self._manager.parent,
1001                         StatusEvent(status=msg, type="stop"))
1002            return
1003       
1004        flag = self._update_paramv_on_fit()
1005       
1006        if self.batch_on and not self._is_2D():
1007            if not self._validate_Npts_1D():
1008                return
1009               
1010        if not flag:
1011            msg = "Fitting range or parameters are invalid"
1012            wx.PostEvent(self.parent.parent,
1013                         StatusEvent(status=msg, type="stop"))
1014            return
1015             
1016        self.select_param(event=None)
1017
1018        # Remove or do not allow fitting on the Q=0 point, especially
1019        # when y(q=0)=None at x[0].
1020        self.qmin_x = float(self.qmin.GetValue())
1021        self.qmax_x = float(self.qmax.GetValue())
1022        self._manager._reset_schedule_problem(value=0, uid=self.uid)
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)
1026
1027        #single fit
1028        #self._manager.onFit(uid=self.uid)
1029        self.fit_started = self._manager.onFit(uid=self.uid)
1030        wx.CallAfter(self.set_fitbutton)
1031   
1032    def set_fitbutton(self):
1033        """
1034        Set fit button label depending on the fit_started[bool]
1035        """
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       
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                     
1052    def get_weight_flag(self):
1053        """
1054        Get flag corresponding to a given weighting dI data.
1055        """
1056        button_list = [self.dI_noweight,
1057                       self.dI_didata,
1058                       self.dI_sqrdata,
1059                       self.dI_idata]
1060        flag = 1
1061        for item in button_list:
1062            if item.GetValue():
1063                if button_list.index(item) == 0:
1064                    flag = 0  # dy = numpy.ones_like(dy_data)
1065                elif button_list.index(item) == 1:
1066                    flag = 1  # dy = dy_data
1067                elif button_list.index(item) == 2:
1068                    flag = 2  # dy = numpy.sqrt(numpy.abs(data))
1069                elif button_list.index(item) == 3:
1070                    flag = 3  # dy = numpy.abs(data)
1071                break
1072        return flag
1073               
1074    def _StopFit(self, event=None):
1075        """
1076        Stop fit
1077        """
1078        if event != None:
1079            event.Skip()
1080        self._manager.stop_fit(self.uid)
1081        self._manager._reset_schedule_problem(value=0)
1082        self._on_fit_complete()
1083         
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   
1091    def _on_select_model(self, event=None):
1092        """
1093        call back for model selection
1094        """
1095        self.Show(False)
1096        copy_flag = False
1097        is_poly_enabled = None
1098        if event != None:
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()
1105
1106        self._on_select_model_helper()
1107        self.set_model_param_sizer(self.model)
1108        if self.model is None:
1109            self._set_bookmark_flag(False)
1110            self._keep.Enable(False)
1111            self._set_save_flag(False)
1112        self.enable_disp.SetValue(False)
1113        self.disable_disp.SetValue(True)
1114        try:
1115            self.set_dispers_sizer()
1116        except:
1117            pass
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   
1123        self.state.structurecombobox = self.structurebox.GetLabel()
1124        self.state.formfactorcombobox = self.formfactorbox.GetLabel()
1125        self.enable_fit_button()
1126        if self.model != None:
1127            self.m_name = self.model.name
1128            self.state.m_name = self.m_name
1129            self.rename_model()
1130            self._set_copy_flag(True)
1131            self._set_paste_flag(True)
1132            if self.data is not None:
1133                is_data = check_data_validity(self.data)
1134                if is_data:
1135                    self._set_bookmark_flag(not self.batch_on)
1136                    self._keep.Enable(not self.batch_on)
1137                    self._set_save_flag(True)
1138            # Reset smearer, model and data
1139            if not copy_flag:
1140                self.disable_smearer.SetValue(True)
1141                self.enable_smearer.SetValue(False)
1142   
1143            # more disables for 2D
1144            self._set_smear_buttons()
1145           
1146            try:
1147                # update smearer sizer
1148                #if not self.enable_smearer.GetValue():
1149                #    self.disable_smearer.SetValue(True)
1150                self.onSmear(None)
1151                temp_smear = None
1152                if not self.disable_smearer.GetValue():
1153                    # Set the smearer environments
1154                    temp_smear = self.current_smearer
1155            except:
1156                raise
1157                ## error occured on chisqr computation
1158                #pass
1159            ## event to post model to fit to fitting plugins
1160            (ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
1161         
1162            ## set smearing value whether or not
1163            #    the data contain the smearing info
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))
1171   
1172            self._manager._on_model_panel(evt=evt)
1173            self.mbox_description.SetLabel("Model [ %s ]"% str(self.model.name))
1174            self.mbox_description.SetForegroundColour(wx.BLUE)
1175            self.state.model = self.model.clone()
1176            self.state.model.name = self.model.name
1177
1178        if event != None:
1179            ## post state to fit panel
1180            new_event = PageInfoEvent(page=self)
1181            wx.PostEvent(self.parent, new_event)
1182            #update list of plugins if new plugin is available
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)
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
1203            if copy_flag:
1204                self.get_paste_params(copy_flag)
1205                wx.CallAfter(self._onDraw, None)
1206               
1207        else:
1208            self._draw_model()
1209           
1210        if self.batch_on:
1211            self.slit_smearer.Enable(False)
1212            self.pinhole_smearer.Enable(False)
1213            self.btEditMask.Disable()
1214            self.EditMask_title.Disable()
1215           
1216        self.Show(True)
1217        self.SetupScrolling()
1218         
1219    def _onparamEnter(self, event):
1220        """
1221        when enter value on panel redraw model according to changed
1222        """
1223        if self.model == None:
1224            msg = "Please select a Model first..."
1225            wx.MessageBox(msg, 'Info')
1226            return
1227
1228        #default flag
1229        flag = False
1230        self.fitrange = True
1231        #get event object
1232        tcrtl = event.GetEventObject()
1233        #Clear msg if previously shown.
1234        msg = ""
1235        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1236
1237        if check_float(tcrtl):
1238            flag = self._onparamEnter_helper()
1239            self.set_npts2fit()
1240            if self.fitrange:
1241                temp_smearer = None
1242                if not self.disable_smearer.GetValue():
1243                    temp_smearer = self.current_smearer
1244                    ## set smearing value whether or not
1245                    #        the data contain the smearing info
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
1252                elif self.data.__class__.__name__ != "Data2D" and \
1253                        not self.enable2D:
1254                    self._manager.set_smearer(smearer=temp_smearer,
1255                                              fid=self.data.id,
1256                                              uid=self.uid,
1257                                              qmin=float(self.qmin_x),
1258                                              qmax=float(self.qmax_x),
1259                            enable_smearer=not self.disable_smearer.GetValue(),
1260                                            draw=True)
1261                if flag:
1262                    #self.compute_chisqr(smearer= temp_smearer)
1263       
1264                    ## new state posted
1265                    if self.state_change:
1266                        #self._undo.Enable(True)
1267                        event = PageInfoEvent(page=self)
1268                        wx.PostEvent(self.parent, event)
1269                    self.state_change = False
1270            else:
1271                # invalid fit range: do nothing here:
1272                # msg already displayed in validate
1273                return
1274        else:
1275            self.save_current_state()
1276            msg = "Cannot Plot :Must enter a number!!!  "
1277            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1278             
1279        self.save_current_state()
1280        return
1281   
1282    def _onparamRangeEnter(self, event):
1283        """
1284        Check validity of value enter in the parameters range field
1285        """
1286        tcrtl = event.GetEventObject()
1287        #Clear msg if previously shown.
1288        msg = ""
1289        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1290        # Flag to register when a parameter has changed.
1291        is_modified = False
1292        if tcrtl.GetValue().lstrip().rstrip() != "":
1293            try:
1294                tcrtl.SetBackgroundColour(wx.WHITE)
1295                self._check_value_enter(self.fittable_param, is_modified)
1296                self._check_value_enter(self.parameters, is_modified)
1297            except:
1298                tcrtl.SetBackgroundColour("pink")
1299                msg = "Model Error:wrong value entered : %s" % sys.exc_value
1300                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1301                return
1302        else:
1303            tcrtl.SetBackgroundColour(wx.WHITE)
1304           
1305        #self._undo.Enable(True)
1306        self.save_current_state()
1307        event = PageInfoEvent(page=self)
1308        wx.PostEvent(self.parent, event)
1309        self.state_change = False
1310         
1311    def _onQrangeEnter(self, event):
1312        """
1313        Check validity of value enter in the Q range field
1314        """
1315        tcrtl = event.GetEventObject()
1316        #Clear msg if previously shown.
1317        msg = ""
1318        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1319        # For theory mode
1320        if not self.data.is_data:
1321            self.npts_x = self.Npts_total.GetValue()
1322            self.Npts_fit.SetValue(self.npts_x)
1323            self.create_default_data()
1324        # Flag to register when a parameter has changed.
1325        if tcrtl.GetValue().lstrip().rstrip() != "":
1326            try:
1327                tcrtl.SetBackgroundColour(wx.WHITE)
1328                # If qmin and qmax have been modified, update qmin and qmax
1329                if self._validate_qrange(self.qmin, self.qmax):
1330                    tempmin = float(self.qmin.GetValue())
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")
1338                    msg = "Model Error:wrong value entered : %s" % sys.exc_value
1339                    wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1340                    return
1341            except:
1342                tcrtl.SetBackgroundColour("pink")
1343                msg = "Model Error:wrong value entered : %s" % sys.exc_value
1344                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1345                return
1346            #Check if # of points for theory model are valid(>0).
1347            # check for 2d
1348            if self.data.__class__.__name__ == "Data2D" or \
1349                    self.enable2D:
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))
1357                if len(index_data[index_data]) < 10:
1358                    msg = "Cannot Plot :No or too little npts in"
1359                    msg += " that data range!!!  "
1360                    wx.PostEvent(self.parent.parent,
1361                                 StatusEvent(status=msg))
1362                    return
1363                else:
1364                    #self.data.mask = index_data
1365                    #self.Npts_fit.SetValue(str(len(self.data.mask)))
1366                    self.set_npts2fit()
1367            else:
1368                index_data = ((self.qmin_x <= self.data.x) & \
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()
1375        else:
1376            tcrtl.SetBackgroundColour("pink")
1377            msg = "Model Error:wrong value entered!!!"
1378            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1379       
1380        self._draw_model()
1381        self.save_current_state()
1382        event = PageInfoEvent(page=self)
1383        wx.PostEvent(self.parent, event)
1384        self.state_change = False
1385        return
1386   
1387    def _clear_Err_on_Fit(self):
1388        """
1389        hide the error text control shown
1390        after fitting
1391        """
1392        if self.is_mac:
1393            return
1394        if hasattr(self, "text2_3"):
1395            self.text2_3.Hide()
1396
1397        if len(self.parameters) > 0:
1398            for item in self.parameters:
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:
1406                        continue
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()
1415 
1416        if len(self.fittable_param) > 0:
1417            for item in self.fittable_param:
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:
1425                        continue
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()
1434        return
1435               
1436    def _get_defult_custom_smear(self):
1437        """
1438        Get the defult values for custum smearing.
1439        """
1440        # get the default values
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
1449       
1450    def _get_smear_info(self):
1451        """
1452        Get the smear info from data.
1453       
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
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
1463        data = self.data
1464        if self.data is None:
1465            return
1466        elif self.data.__class__.__name__ == "Data2D" or \
1467            self.enable2D:
1468            if data.dqx_data == None or  data.dqy_data == None:
1469                return
1470            elif self.current_smearer != None \
1471                and data.dqx_data.any() != 0 \
1472                and data.dqx_data.any() != 0:
1473                self.smear_type = "Pinhole2d"
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:
1478                return
1479        # check if it is pinhole smear and get min max if it is.
1480        if data.dx != None and all(data.dx != 0):
1481            self.smear_type = "Pinhole"
1482            self.dq_l = data.dx[0]
1483            self.dq_r = data.dx[-1]
1484           
1485        # check if it is slit smear and get min max if it is.
1486        elif data.dxl != None or data.dxw != None:
1487            self.smear_type = "Slit"
1488            if data.dxl != None and all(data.dxl != 0):
1489                self.dq_l = data.dxl[0]
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
1493   
1494    def _show_smear_sizer(self):
1495        """
1496        Show only the sizers depending on smear selection
1497        """
1498        # smear disabled
1499        if self.disable_smearer.GetValue():
1500            self.smear_description_none.Show(True)
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
1513        elif self.enable_smearer.GetValue():
1514
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)
1520                    self.smear_description_slit_width.Show(True)
1521                elif self.smear_type == 'Pinhole':
1522                    self.smear_description_pin_min.Show(True)
1523                    self.smear_description_pin_max.Show(True)
1524                self.smear_description_smear_type.Show(True)
1525                self.smear_description_type.Show(True)
1526                self.smear_data_left.Show(True)
1527                self.smear_data_right.Show(True)
1528        # custom pinhole smear
1529        elif self.pinhole_smearer.GetValue():
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
1535            self.smear_pinhole_min.Show(True)
1536            self.smear_pinhole_max.Show(True)
1537        # custom slit smear
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        """
1547        Hide all smearing messages in the set_smearer sizer
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()
1553        self.smear_description_accuracy_type.Hide()
1554        self.smear_description_2d_x.Hide()
1555        self.smear_description_2d_y.Hide()
1556        self.smear_description_2d.Hide()
1557       
1558        self.smear_accuracy.Hide()
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   
1572    def _set_accuracy_list(self):
1573        """
1574        Set the list of an accuracy in 2D custum smear:
1575                Xhigh, High, Med, or Low
1576        """
1577        # list of accuracy choices
1578        list = ['Low', 'Med', 'High', 'Xhigh']
1579        for idx in range(len(list)):
1580            self.smear_accuracy.Append(list[idx], idx)
1581           
1582    def _set_fun_box_list(self, fun_box):
1583        """
1584        Set the list of func for multifunctional models
1585        """
1586        # Check if it is multi_functional model
1587        if self.model.__class__ not in self.model_list_box["Multi-Functions"] \
1588                and not self.temp_multi_functional:
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):
1599                    fun_box.Append(key, val)
1600                    break
1601            ind += 1
1602       
1603    def _on_select_accuracy(self, event):
1604        """
1605        Select an accuracy in 2D custom smear: Xhigh, High, Med, or Low
1606        """
1607        #event.Skip()
1608        # Check if the accuracy is same as before
1609        #self.smear2d_accuracy = event.GetEventObject().GetValue()
1610        self.smear2d_accuracy = self.smear_accuracy.GetValue()
1611        if self.pinhole_smearer.GetValue():
1612            self.onPinholeSmear(event=None)
1613        else:
1614            self.onSmear(event=None)
1615            if self.current_smearer != None:
1616                self.current_smearer.set_accuracy(accuracy=\
1617                                                  self.smear2d_accuracy) 
1618        event.Skip()
1619
1620    def _on_fun_box(self, event):
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()
1628        if value in self.model.fun_list:
1629            fun_val = self.model.fun_list[value]
1630
1631        self.model.setParam(name, fun_val)
1632        # save state
1633        self._copy_parameters_state(self.str_parameters,
1634                                    self.state.str_parameters)
1635        # update params
1636        self._update_paramv_on_fit()
1637        # draw
1638        self._draw_model()
1639        self.Refresh()
1640        # get ready for new event
1641        event.Skip()
1642       
1643    def _onMask(self, event):
1644        """
1645        Build a panel to allow to edit Mask
1646        """
1647        from sans.guiframe.local_perspectives.plotting.masking \
1648        import MaskPanel as MaskDialog
1649       
1650        self.panel = MaskDialog(base=self, data=self.data, id=wx.NewId())
1651        self.panel.ShowModal()
1652       
1653    def _draw_masked_model(self, event):
1654        """
1655        Draw model image w/mask
1656        """
1657        is_valid_qrange = self._update_paramv_on_fit()
1658
1659        if is_valid_qrange and self.model != None:
1660            self.panel.MakeModal(False)
1661            event.Skip()
1662            # try re draw the model plot if it exists
1663            self._draw_model()
1664            self.set_npts2fit()
1665        elif self.model == None:
1666            self.panel.MakeModal(False)
1667            event.Skip()
1668            self.set_npts2fit()
1669            msg = "No model is found on updating MASK in the model plot... "
1670            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1671        else:
1672            event.Skip()
1673            msg = ' Please consider your Q range, too.'
1674            self.panel.ShowMessage(msg)
1675
1676    def _set_smear(self, data):
1677        """
1678        Set_smear
1679        """
1680        if data is None:
1681            return
1682        self.current_smearer = smear_selection(data, self.model)
1683        flag = self.disable_smearer.GetValue()
1684        self.disable_smearer.SetValue(flag)
1685        if self.current_smearer == None:
1686            self.enable_smearer.Disable()
1687        else:
1688            self.enable_smearer.Enable()
1689        if not flag:
1690            self.onSmear(None)
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
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   
1705    def compute_data_set_range(self, data_list):
1706        """
1707        find the range that include all data  in the set
1708        return the minimum and the maximum values
1709        """
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
1717       
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:
1726            if not hasattr(data, "data"):
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                   
1739            else:
1740                qmin = 0
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
1750                ## Maximum value of data
1751                qmax = math.sqrt(x * x + y * y)
1752                npts = len(data.data)
1753        return qmin, qmax, npts
1754           
1755    def set_data(self, data):
1756        """
1757        reset the current data
1758        """
1759        id = None
1760        flag = False
1761        is_data = False
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
1768        if self.data is not None:
1769            is_data = check_data_validity(self.data)
1770        if not is_data and data is not None:
1771                flag = True
1772        if data is not None:
1773            id = data.id
1774            if is_data:
1775                self.graph_id = self.data.group_id
1776                flag = (data.id != self.data.id)
1777        self.data = data
1778        if check_data_validity(data):
1779            self.graph_id = data.group_id
1780        self.data.group_id = self.graph_id
1781       
1782        if self.data is None:
1783            data_name = ""
1784            self._set_bookmark_flag(False)
1785            self._keep.Enable(False)
1786            self._set_save_flag(False)
1787        else:
1788            if self.model != None:
1789                self._set_bookmark_flag(not self.batch_on)
1790                self._keep.Enable(not self.batch_on)
1791               
1792            self._set_save_flag(True)
1793            self._set_preview_flag(True)
1794
1795            self._set_smear(data)
1796            # more disables for 2D
1797            if self.data.__class__.__name__ == "Data2D" or \
1798                        self.enable2D:
1799                self.slit_smearer.Disable()
1800                self.pinhole_smearer.Enable(True)
1801                self.default_mask = copy.deepcopy(self.data.mask)
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()
1812            else:
1813                self.slit_smearer.Enable(True)
1814                self.pinhole_smearer.Enable(True)
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()
1825            # Enable weighting radio uttons
1826            self.dI_noweight.Enable(True)
1827            self.dI_sqrdata.Enable(True)
1828            self.dI_idata.Enable(True)
1829             
1830            self.formfactorbox.Enable()
1831            self.structurebox.Enable()
1832            data_name = self.data.name
1833            _, _, npts = self.compute_data_range(self.data)
1834            #set maximum range for x in linear scale
1835            if not hasattr(self.data, "data"):  # Display only for 1D data fit
1836                self.btEditMask.Disable()
1837                self.EditMask_title.Disable()
1838            else:
1839                self.btEditMask.Enable()
1840                self.EditMask_title.Enable()
1841   
1842        self.Npts_total.SetValue(str(npts))
1843        #default:number of data points selected to fit
1844        self.Npts_fit.SetValue(str(npts))
1845        self.Npts_total.SetEditable(False)
1846        self.Npts_total.SetBackgroundColour(\
1847                                    self.GetParent().GetBackgroundColour())
1848       
1849        self.Npts_total.Bind(wx.EVT_MOUSE_EVENTS, self._npts_click)
1850        self.dataSource.SetValue(data_name)
1851        self.state.data = data
1852        self.enable_fit_button()
1853        # send graph_id to page_finder
1854        self._manager.set_graph_id(uid=self.uid, graph_id=self.graph_id)
1855        #focus the page
1856        if check_data_validity(data):
1857            self.data_box_description.SetForegroundColour(wx.BLUE)
1858       
1859        if self.batch_on:
1860            self.slit_smearer.Enable(False)
1861            self.pinhole_smearer.Enable(False)
1862            self.btEditMask.Disable()
1863            self.EditMask_title.Disable()
1864
1865        self.on_set_focus(None)
1866        self.Refresh()
1867        #update model plot with new data information
1868        if flag:
1869            #set model view button
1870            if not self.enable_smearer.GetValue():
1871                    self.disable_smearer.SetValue(True)
1872            self.onSmear(None)
1873
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()
1881            #replace data plot on combo box selection
1882            #by removing the previous selected data
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
1889            #plot the current selected data
1890            wx.PostEvent(self._manager.parent,
1891                         NewPlotEvent(action="check", plot=self.data,
1892                                      title=str(self.data.title)))
1893            self._draw_model()
1894   
1895    def _npts_click(self, event):
1896        """
1897        Prevent further handling of the mouse event on Npts_total
1898        by not calling Skip().
1899        """
1900        pass
1901   
1902    def reset_page(self, state, first=False):
1903        """
1904        reset the state
1905        """
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"))
1919        self._lay_out()
1920        self.Refresh()
1921       
1922    def get_range(self):
1923        """
1924        return the fitting range
1925        """
1926        return float(self.qmin_x), float(self.qmax_x)
1927   
1928    def get_npts2fit(self):
1929        """
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       
1934        """
1935        if self.data is None:
1936            return
1937        npts2fit = 0
1938        qmin, qmax = self.get_range()
1939        if self.data.__class__.__name__ == "Data2D" or \
1940                        self.enable2D:
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))
1946            npts2fit = len(self.data.data[index_data])
1947        else:
1948            for qx in self.data.x:
1949                if qx >= qmin and qx <= qmax:
1950                    npts2fit += 1
1951        return npts2fit
1952
1953    def set_npts2fit(self):
1954        """
1955        setValue Npts for fitting
1956        """
1957        self.Npts_fit.SetValue(str(self.get_npts2fit()))
1958       
1959    def get_chi2(self):
1960        """
1961        return the current chi2
1962        """
1963        return self.tcChi.GetValue()
1964       
1965    def get_param_list(self):
1966        """
1967        :return self.param_toFit: list containing  references to TextCtrl
1968            checked.Theses TextCtrl will allow reference to parameters to fit.
1969       
1970        :raise: if return an empty list of parameter fit will nnote work
1971            properly so raise ValueError,"missing parameter to fit"
1972        """
1973        if self.param_toFit != []:
1974            return self.param_toFit
1975        else:
1976            msg = "missing parameters to fit"
1977            wx.MessageBox(msg, 'warning')
1978            return False
1979     
1980    def onsetValues(self, chisqr, p_name, out, cov):
1981        """
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   
1989        """
1990        # make sure stop button to fit button all the time
1991        self._on_fit_complete()
1992        if out == None or not numpy.isfinite(chisqr):
1993            raise ValueError, "Fit error occured..."
1994       
1995        is_modified = False
1996        has_error = False
1997        dispersity = ''
1998       
1999        #Hide textctrl boxes of errors.
2000        self._clear_Err_on_Fit()
2001       
2002        #Check if chi2 is finite
2003        if chisqr != None and numpy.isfinite(chisqr):
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()
2010        else:
2011            self.tcChi.SetValue("-")
2012       
2013        #Hide error title
2014        if self.text2_3.IsShown() and not self.is_mac:
2015            self.text2_3.Hide()
2016     
2017        try:
2018            if self.enable_disp.GetValue():
2019                if hasattr(self, "text_disp_1"):
2020                    if self.text_disp_1 != None and not self.is_mac:
2021                        self.text_disp_1.Hide()
2022        except:
2023            dispersity = None
2024            pass
2025     
2026        i = 0
2027        #Set the panel when fit result are list
2028        for item in self.param_toFit:
2029            if len(item) > 5 and item != None:
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
2062                i += 1
2063            else:
2064                raise ValueError, "onsetValues: Invalid parameters..."
2065        #Show error title when any errors displayed
2066        if has_error:
2067            if not self.text2_3.IsShown():
2068                self.text2_3.Show(True)
2069        ## save current state
2070        self.save_current_state()
2071       
2072        if not self.is_mac:
2073            self.Layout()
2074            self.Refresh()
2075        self._mac_sleep(0.1)
2076        #plot model ( when drawing, do not update chisqr value again)
2077        self._draw_model(update_chisqr=False, source='fit')
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()
2084        self._set_weight()
2085       
2086    def _set_weight(self, is_2D=None):
2087        """
2088        Set weight in fit problem
2089        """
2090        # compute weight for the current data
2091        from .utils import get_weight
2092        flag_weight = self.get_weight_flag()
2093        if is_2D == None:
2094            is_2D = self._is_2D()
2095        weight = get_weight(data=self.data,
2096                            is2d=is_2D,
2097                            flag=flag_weight)
2098        self._manager.set_fit_weight(uid=self.uid,
2099                                     flag=flag_weight,
2100                                     is2d=is_2D,
2101                                     fid=None)
2102   
2103    def onPinholeSmear(self, event):
2104        """
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                     
2111        """
2112        if self.model == None:
2113            self.disable_smearer.SetValue(True)
2114            if event == None:
2115                return
2116            msg = "Please select a Model first..."
2117            wx.MessageBox(msg, 'Info')
2118            wx.PostEvent(self._manager.parent,
2119                         StatusEvent(status="Smear: %s" % msg))
2120            return
2121
2122        # Need update param values
2123        self._update_paramv_on_fit()
2124
2125        # msg default
2126        msg = None
2127        if event != None:
2128            tcrtl = event.GetEventObject()
2129            # event case of radio button
2130            if tcrtl.GetValue() == True:
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()
2136        else:
2137            is_new_pinhole = True
2138        # if any value is changed
2139        if is_new_pinhole:
2140            msg = self._set_pinhole_smear()
2141        # hide all silt sizer
2142        self._hide_all_smear_info()
2143       
2144        # show relevant slit sizers
2145        self._show_smear_sizer()
2146
2147        self.sizer_set_smearer.Layout()
2148        self.Layout()
2149       
2150        if event != None:
2151            event.Skip()
2152        #self._undo.Enable(True)
2153        self.save_current_state()
2154        event = PageInfoEvent(page=self)
2155        wx.PostEvent(self.parent, event)
2156       
2157    def _is_changed_pinhole(self):
2158        """
2159        check if any of pinhole smear is changed
2160       
2161        :return: True or False
2162       
2163        """
2164        # get the values
2165        pin_min = self.smear_pinhole_min.GetValue()
2166        pin_max = self.smear_pinhole_max.GetValue()
2167                   
2168        # Check changes in slit width
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        """
2187        Set custom pinhole smear
2188       
2189        :return: msg
2190       
2191        """
2192        # copy data
2193        data = copy.deepcopy(self.data)
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
2205        msg = None
2206   
2207        get_pin_min = self.smear_pinhole_min
2208        get_pin_max = self.smear_pinhole_max
2209
2210        if not check_float(get_pin_min):
2211            get_pin_min.SetBackgroundColour("pink")
2212            msg = "Model Error:wrong value entered!!!"
2213        elif not check_float(get_pin_max):
2214            get_pin_max.SetBackgroundColour("pink")
2215            msg = "Model Error:wrong value entered!!!"
2216        else:
2217            if len_data < 2:
2218                len_data = 2
2219            self.dx_min = float(get_pin_min.GetValue())
2220            self.dx_max = float(get_pin_max.GetValue())
2221            if self.dx_min < 0:
2222                get_pin_min.SetBackgroundColour("pink")
2223                msg = "Model Error:This value can not be negative!!!"
2224            elif self.dx_max < 0:
2225                get_pin_max.SetBackgroundColour("pink")
2226                msg = "Model Error:This value can not be negative!!!"
2227            elif self.dx_min != None and self.dx_max != None:
2228                if self._is_2D():
2229                    data.dqx_data[data.dqx_data == 0] = self.dx_min
2230                    data.dqy_data[data.dqy_data == 0] = self.dx_max
2231                elif self.dx_min == self.dx_max:
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
2241                else:
2242                    data.dx[data.dx == 0] = self.dx_min
2243            elif self.dx_max != None:
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
2248            self.current_smearer = smear_selection(data, self.model)
2249            # 2D need to set accuracy
2250            if self._is_2D():
2251                self.current_smearer.set_accuracy(accuracy=\
2252                                                  self.smear2d_accuracy)
2253
2254        if msg != None:
2255            wx.PostEvent(self._manager.parent, StatusEvent(status=msg))
2256        else:
2257            get_pin_min.SetBackgroundColour("white")
2258            get_pin_max.SetBackgroundColour("white")
2259        ## set smearing value whether or not the data contain the smearing info
2260       
2261        self._manager.set_smearer(smearer=self.current_smearer,
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)
2267        return msg
2268       
2269    def update_pinhole_smear(self):
2270        """
2271        called by kill_focus on pinhole TextCntrl
2272        to update the changes
2273       
2274        :return: False when wrong value was entered
2275       
2276        """
2277        # msg default
2278        msg = None
2279        # check if any value is changed
2280        if self._is_changed_pinhole():
2281            msg = self._set_pinhole_smear()
2282        wx.CallAfter(self.save_current_state)
2283
2284        if msg != None:
2285            return False
2286        else:
2287            return True
2288                     
2289    def onSlitSmear(self, event):
2290        """
2291        Create a custom slit smear object that will change the way residuals
2292        are compute when fitting
2293        """
2294        if self.model == None:
2295            self.disable_smearer.SetValue(True)
2296            if event == None:
2297                return
2298            msg = "Please select a Model first..."
2299            wx.MessageBox(msg, 'Info')
2300            wx.PostEvent(self._manager.parent,
2301                         StatusEvent(status="Smear: %s" % msg))
2302            return
2303
2304        # Need update param values
2305        self._update_paramv_on_fit()
2306
2307        # msg default
2308        msg = None
2309        # for event given
2310        if event != None:
2311            tcrtl = event.GetEventObject()
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()
2319        else:
2320            is_new_slit = True
2321       
2322        # if any value is changed
2323        if is_new_slit:
2324            msg = self._set_slit_smear()
2325           
2326        # hide all silt sizer
2327        self._hide_all_smear_info()
2328        # show relevant slit sizers
2329        self._show_smear_sizer()
2330        self.sizer_set_smearer.Layout()
2331        self.Layout()
2332
2333        if event != None:
2334            event.Skip()
2335        self.save_current_state()
2336        event = PageInfoEvent(page=self)
2337        wx.PostEvent(self.parent, event)
2338        if msg != None:
2339            wx.PostEvent(self._manager.parent, StatusEvent(status=msg))
2340
2341    def _is_changed_slit(self):
2342        """
2343        check if any of slit lengths is changed
2344       
2345        :return: True or False
2346       
2347        """
2348        # get the values
2349        width = self.smear_slit_width.GetValue()
2350        height = self.smear_slit_height.GetValue()
2351       
2352        # check and change the box bg color if it was pink
2353        #    but it should be white now
2354        # because this is the case that _set_slit_smear() will not handle
2355        if height.lstrip().rstrip() == "":
2356            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
2357        if width.lstrip().rstrip() == "":
2358            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
2359           
2360        # Check changes in slit width
2361        if width == "":
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
2372        if height == "":
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
2381
2382        return False
2383   
2384    def _set_slit_smear(self):
2385        """
2386        Set custom slit smear
2387       
2388        :return: message to inform the user about the validity
2389            of the values entered for slit smear
2390        """
2391        if self.data.__class__.__name__ == "Data2D" or \
2392                        self.enable2D:
2393            return
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())
2404            data.dxl = self.dxl * numpy.ones(data_len)
2405            self.smear_slit_height.SetBackgroundColour(wx.WHITE)
2406        except:
2407            self.dxl = None
2408            data.dxl = numpy.zeros(data_len)
2409            if self.smear_slit_height.GetValue().lstrip().rstrip() != "":
2410                self.smear_slit_height.SetBackgroundColour("pink")
2411                msg = "Wrong value entered... "
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)
2417            data.dxw = self.dxw * numpy.ones(data_len)
2418        except:
2419            self.dxw = None
2420            data.dxw = numpy.zeros(data_len)
2421            if self.smear_slit_width.GetValue().lstrip().rstrip() != "":
2422                self.smear_slit_width.SetBackgroundColour("pink")
2423                msg = "Wrong Fit value entered... "
2424            else:
2425                self.smear_slit_width.SetBackgroundColour(wx.WHITE)
2426             
2427        self.current_smearer = smear_selection(data, self.model)
2428        ## set smearing value whether or not the data contain the smearing info
2429        self._manager.set_smearer(smearer=self.current_smearer,
2430                                 fid=self.data.id,
2431                                 qmin=float(self.qmin_x),
2432                                 qmax=float(self.qmax_x),
2433                        enable_smearer=not self.disable_smearer.GetValue(),
2434                                 uid=self.uid)
2435        return msg
2436   
2437    def update_slit_smear(self):
2438        """
2439        called by kill_focus on pinhole TextCntrl
2440        to update the changes
2441       
2442        :return: False when wrong value was entered
2443       
2444        """
2445        # msg default
2446        msg = None
2447        # check if any value is changed
2448        if self._is_changed_slit():
2449            msg = self._set_slit_smear()
2450        #self._undo.Enable(True)
2451        self.save_current_state()
2452
2453        if msg != None:
2454            return False
2455        else:
2456            return True
2457                           
2458    def onSmear(self, event):
2459        """
2460        Create a smear object that will change the way residuals
2461        are compute when fitting
2462        """
2463        if event != None:
2464            event.Skip()
2465        if self.data is None:
2466            return
2467
2468        if self.model == None:
2469            self.disable_smearer.SetValue(True)
2470            if event == None:
2471                return
2472            msg = "Please select a Model first..."
2473            wx.MessageBox(msg, 'Info')
2474            wx.PostEvent(self._manager.parent,
2475                         StatusEvent(status="Smear: %s" % msg))
2476            return
2477        # Need update param values
2478        self._update_paramv_on_fit()
2479        if self.model != None:
2480            if self.data.is_data:
2481                self._manager.page_finder[self.uid].add_data(data=self.data)
2482        temp_smearer = self.on_smear_helper()
2483       
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
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()
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
2505       
2506        :param update: force or not to update
2507        """
2508        self._get_smear_info()
2509        #renew smear sizer
2510        if self.smear_type != None:
2511            self.smear_description_smear_type.SetValue(str(self.smear_type))
2512            self.smear_data_left.SetValue(str(self.dq_l))
2513            self.smear_data_right.SetValue(str(self.dq_r))
2514
2515        self._hide_all_smear_info()
2516        data = copy.deepcopy(self.data)
2517       
2518        # make sure once more if it is smearer
2519        temp_smearer = smear_selection(data, self.model)
2520        if self.current_smearer != temp_smearer or update:
2521            self.current_smearer = temp_smearer
2522        if self.enable_smearer.GetValue():
2523            if self.current_smearer == None:
2524                wx.PostEvent(self._manager.parent,
2525                    StatusEvent(status="Data contains no smearing information"))
2526            else:
2527                wx.PostEvent(self._manager.parent,
2528                    StatusEvent(status="Data contains smearing information"))
2529
2530            self.smear_data_left.Show(True)
2531            self.smear_data_right.Show(True)
2532            temp_smearer = self.current_smearer
2533        elif self.disable_smearer.GetValue():
2534            self.smear_description_none.Show(True)
2535        elif self.pinhole_smearer.GetValue():
2536            self.onPinholeSmear(None)
2537        elif self.slit_smearer.GetValue():
2538            self.onSlitSmear(None)
2539        self._show_smear_sizer()
2540       
2541        return temp_smearer
2542   
2543    def on_complete_chisqr(self, event):
2544        """
2545        Display result chisqr on the panel
2546        :event: activated by fitting/ complete after draw
2547        """
2548        try:
2549            if event == None:
2550                output = "-"
2551            elif not numpy.isfinite(event.output):
2552                output = "-"
2553            else:
2554                output = event.output
2555            self.tcChi.SetValue(str(format_number(output, True)))
2556            self.state.tcChi = self.tcChi.GetValue()
2557        except:
2558            pass
2559           
2560    def get_all_checked_params(self):
2561        """
2562        Found all parameters current check and add them to list of parameters
2563        to fit
2564        """
2565        self.param_toFit = []
2566        for item in self.parameters:
2567            if item[0].GetValue() and item not in self.param_toFit:
2568                if item[0].IsShown():
2569                    self.param_toFit.append(item)
2570        for item in self.fittable_param:
2571            if item[0].GetValue() and item not in self.param_toFit:
2572                if item[0].IsShown():
2573                    self.param_toFit.append(item)
2574        self.save_current_state_fit()
2575       
2576        event = PageInfoEvent(page=self)
2577        wx.PostEvent(self.parent, event)
2578        param2fit = []
2579        for item in self.param_toFit:
2580            if item[0] and item[0].IsShown():
2581                param2fit.append(item[1])
2582        self.parent._manager.set_param2fit(self.uid, param2fit)
2583               
2584    def select_all_param(self, event):
2585        """
2586        set to true or false all checkBox given the main checkbox value cb1
2587        """
2588        self.param_toFit = []
2589        if  self.parameters != []:
2590            if  self.cb1.GetValue():
2591                for item in self.parameters:
2592                    if item[0].IsShown():
2593                        ## for data2D select all to fit
2594                        if self.data.__class__.__name__ == "Data2D" or \
2595                                self.enable2D:
2596                            item[0].SetValue(True)
2597                            self.param_toFit.append(item)
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)
2605                #if len(self.fittable_param)>0:
2606                for item in self.fittable_param:
2607                    if item[0].IsShown():
2608                        if self.data.__class__.__name__ == "Data2D" or \
2609                                self.enable2D:
2610                            item[0].SetValue(True)
2611                            self.param_toFit.append(item)
2612                            try:
2613                                if len(self.values[item[1]]) > 0:
2614                                    item[0].SetValue(False)
2615                            except:
2616                                pass
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)
2630
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)
2636                self.param_toFit = []
2637           
2638        self.save_current_state_fit()
2639       
2640        if event != None:
2641            #self._undo.Enable(True)
2642            ## post state to fit panel
2643            event = PageInfoEvent(page=self)
2644            wx.PostEvent(self.parent, event)
2645        param2fit = []
2646        for item in self.param_toFit:
2647            if item[0] and item[0].IsShown():
2648                param2fit.append(item[1])
2649        self.parent._manager.set_param2fit(self.uid, param2fit)
2650
2651    def select_param(self, event):
2652        """
2653        Select TextCtrl  checked for fitting purpose and stores them
2654        in  self.param_toFit=[] list
2655        """
2656        self.param_toFit = []
2657        for item in self.parameters:
2658            #Skip t ifhe angle parameters if 1D data
2659            if self.data.__class__.__name__ != "Data2D" and\
2660                        not self.enable2D:
2661                if item in self.orientation_params:
2662                    continue
2663            #Select parameters to fit for list of primary parameters
2664            if item[0].GetValue() and item[0].IsShown():
2665                if not (item in self.param_toFit):
2666                    self.param_toFit.append(item)
2667            else:
2668                #remove parameters from the fitting list
2669                if item in self.param_toFit:
2670                    self.param_toFit.remove(item)
2671
2672        #Select parameters to fit for list of fittable parameters
2673        #        with dispersion
2674        for item in self.fittable_param:
2675            #Skip t ifhe angle parameters if 1D data
2676            if self.data.__class__.__name__ != "Data2D" and\
2677                        not self.enable2D:
2678                if item in self.orientation_params:
2679                    continue
2680            if item[0].GetValue() and item[0].IsShown():
2681                if not (item in self.param_toFit):
2682                    self.param_toFit.append(item)
2683            else:
2684                #remove parameters from the fitting list
2685                if item in self.param_toFit:
2686                    self.param_toFit.remove(item)
2687
2688        #Calculate num. of angle parameters
2689        if self.data.__class__.__name__ == "Data2D" or \
2690                       self.enable2D:
2691            len_orient_para = 0
2692        else:
2693            len_orient_para = len(self.orientation_params)  # assume even len
2694        #Total num. of angle parameters
2695        if len(self.fittable_param) > 0:
2696            len_orient_para *= 2
2697        #Set the value of checkbox that selected every checkbox or not
2698        if len(self.parameters) + len(self.fittable_param) - len_orient_para \
2699            == len(self.param_toFit):
2700            self.cb1.SetValue(True)
2701        else:
2702            self.cb1.SetValue(False)
2703       
2704        self.save_current_state_fit()
2705        if event != None:
2706            ## post state to fit panel
2707            event = PageInfoEvent(page=self)
2708            wx.PostEvent(self.parent, event)
2709       
2710        param2fit = []
2711        for item in self.param_toFit:
2712            if item[0] and item[0].IsShown():
2713                param2fit.append(item[1])
2714        self.parent._manager.set_param2fit(self.uid, param2fit)
2715       
2716    def set_model_param_sizer(self, model):
2717        """
2718        Build the panel from the model content
2719       
2720        :param model: the model selected in combo box for fitting purpose
2721       
2722        """
2723        self.sizer3.Clear(True)
2724        self.parameters = []
2725        self.str_parameters = []
2726        self.param_toFit = []
2727        self.fittable_param = []
2728        self.fixed_param = []
2729        self.orientation_params = []
2730        self.orientation_params_disp = []
2731       
2732        if model == None:
2733            self.sizer3.Layout()
2734            self.SetupScrolling()
2735            return
2736        ## the panel is drawn using the current value of the fit engine
2737        if self.engine_type == None and self._manager != None:
2738            self.engine_type = self._manager._return_engine_type()
2739
2740        box_description = wx.StaticBox(self, -1, str("Model Parameters"))
2741        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
2742        sizer = wx.GridBagSizer(5, 5)
2743        ## save the current model
2744        self.model = model
2745           
2746        keys = self.model.getParamList()
2747        #list of dispersion paramaters
2748        self.disp_list = self.model.getDispParamList()
2749
2750        def custom_compare(a, b):
2751            """
2752            Custom compare to order, first by alphabets then second by number.
2753            """
2754            # number at the last digit
2755            a_last = a[len(a) - 1]
2756            b_last = b[len(b) - 1]
2757            # default
2758            num_a = None
2759            num_b = None
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)
2766            # check if it contains a int number(<10)
2767            try:
2768                num_a = int(a_last)
2769            except:
2770                pass
2771            try:
2772                num_b = int(b_last)
2773            except:
2774                pass
2775            # Put 'scale' near the top; happens
2776            # when numbered param name exists
2777            if a == 'scale':
2778                return -1
2779            # both have a number
2780            if num_a != None and num_b != None:
2781                if num_a > num_b:
2782                    return -1
2783                # same number
2784                elif num_a == num_b:
2785                    # different last names
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
2792            # one of them has a number
2793            elif num_a != None:
2794                return 1
2795            elif num_b != None:
2796                return -1
2797            # no numbers
2798            else:
2799                return cmp(a.lower(), b.lower())
2800
2801        keys.sort(custom_compare)
2802   
2803        iy = 0
2804        ix = 0
2805        select_text = "Select All"
2806        self.cb1 = wx.CheckBox(self, -1, str(select_text), (10, 10))
2807        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
2808        self.cb1.SetToolTipString("To check/uncheck all the boxes below.")
2809        self.cb1.SetValue(True)
2810       
2811        sizer.Add(self.cb1, (iy, ix), (1, 1), \
2812                             wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
2813        ix += 1
2814        self.text2_2 = wx.StaticText(self, -1, 'Value')
2815        sizer.Add(self.text2_2, (iy, ix), (1, 1), \
2816                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2817        ix += 2
2818        self.text2_3 = wx.StaticText(self, -1, 'Error')
2819        sizer.Add(self.text2_3, (iy, ix), (1, 1), \
2820                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2821        if not self.is_mac:
2822            self.text2_3.Hide()
2823        ix += 1
2824        self.text2_min = wx.StaticText(self, -1, 'Min')
2825        sizer.Add(self.text2_min, (iy, ix), (1, 1), \
2826                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2827        #self.text2_min.Hide()
2828        ix += 1
2829        self.text2_max = wx.StaticText(self, -1, 'Max')
2830        sizer.Add(self.text2_max, (iy, ix), (1, 1), \
2831                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2832        #self.text2_max.Hide()
2833        ix += 1
2834        self.text2_4 = wx.StaticText(self, -1, '[Units]')
2835        sizer.Add(self.text2_4, (iy, ix), (1, 1), \
2836                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2837        self.text2_4.Hide()
2838       
2839        CHECK_STATE = self.cb1.GetValue()
2840        for item in keys:
2841            if not item in self.disp_list and not item in \
2842                    self.model.orientation_params:
2843               
2844                ##prepare a spot to store errors
2845                if not item in self.model.details:
2846                    self.model.details[item] = ["", None, None]
2847         
2848                iy += 1
2849                ix = 0
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):
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)
2857                    ## add parameter value
2858                    ix += 1
2859                    value = self.model.getParam(item)
2860                    if len(self.model.fun_list) > 0:
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)
2864                        self._set_fun_box_list(fun_box)
2865                        fun_box.SetSelection(0)
2866                        #self.fun_box.SetToolTipString("A function
2867                        #    describing the interface")
2868                        wx.EVT_COMBOBOX(fun_box, -1, self._on_fun_box)
2869                    else:
2870                        fun_box = self.ModelTextCtrl(self, -1,
2871                                                     size=(_BOX_WIDTH, 20),
2872                                style=wx.TE_PROCESS_ENTER, name='%s' % item)
2873                        fun_box.SetToolTipString(\
2874                                "Hit 'Enter' after typing to update the plot.")
2875                        fun_box.SetValue(format_number(value, True))
2876                    sizer.Add(fun_box, (iy, ix), (1, 1), wx.EXPAND)
2877                    self.str_parameters.append([None, item, fun_box,
2878                                                None, None, None,
2879                                                None, None])
2880                else:
2881                    ## add parameters name with checkbox for selecting to fit
2882                    cb = wx.CheckBox(self, -1, item)
2883                    cb.SetValue(CHECK_STATE)
2884                    cb.SetToolTipString(" Check mark to fit.")
2885                    #cb.SetValue(True)
2886                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
2887                   
2888                    sizer.Add(cb, (iy, ix), (1, 1),
2889                              wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
2890
2891                    ## add parameter value
2892                    ix += 1
2893                    value = self.model.getParam(item)
2894                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
2895                                        style=wx.TE_PROCESS_ENTER)
2896                    ctl1.SetToolTipString(\
2897                                "Hit 'Enter' after typing to update the plot.")
2898                    ctl1.SetValue(format_number(value, True))
2899                    sizer.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
2900                    ## text to show error sign
2901                    ix += 1
2902                    text2 = wx.StaticText(self, -1, '+/-')
2903                    sizer.Add(text2, (iy, ix), (1, 1), \
2904                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2905                    if not self.is_mac:
2906                        text2.Hide()
2907                    ix += 1
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)
2912                    if not self.is_mac:
2913                        ctl2.Hide()
2914                   
2915                    ix += 1
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)
2920         
2921                    sizer.Add(ctl3, (iy, ix), (1, 1),
2922                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2923           
2924                    ix += 1
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)
2931   
2932                    ix += 1
2933                    # Units
2934                    if item in self.model.details:
2935                        units = wx.StaticText(self, -1,
2936                            self.model.details[item][0], style=wx.ALIGN_LEFT)
2937                    else:
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)
2942                       
2943                    self.parameters.append([cb, item, ctl1,
2944                                            text2, ctl2, ctl3, ctl4, units])
2945                                 
2946        iy += 1
2947        sizer.Add((10, 10), (iy, ix), (1, 1),
2948                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
2949       
2950        # type can be either Guassian or Array
2951        if len(self.model.dispersion.values()) > 0:
2952            type = self.model.dispersion.values()[0]["type"]
2953        else:
2954            type = "Gaussian"
2955           
2956        iy += 1
2957        ix = 0
2958        #Add tile for orientational angle
2959        for item in keys:
2960            if item in self.model.orientation_params:
2961                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
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)
2966                sizer.Add(orient_angle, (iy, ix), (1, 1),
2967                          wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
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                       
2990                if not self.data.__class__.__name__ == "Data2D" and \
2991                        not self.enable2D:
2992                    orient_angle.Hide()
2993                else:
2994                    orient_angle.Show(True)
2995                break
2996     
2997        #For Gaussian only
2998        if type.lower() != "array":
2999            for item in self.model.orientation_params:
3000                if not self.magnetic_on:
3001                    if item in self.model.magnetic_params:
3002                        continue
3003                if not item in self.disp_list:
3004                    ##prepare a spot to store min max
3005                    if not item in self.model.details:
3006                        self.model.details[item] = ["", None, None]
3007                         
3008                    iy += 1
3009                    ix = 0
3010                    ## add parameters name with checkbox for selecting to fit
3011                    cb = wx.CheckBox(self, -1, item)
3012                    cb.SetValue(CHECK_STATE)
3013                    cb.SetToolTipString("Check mark to fit")
3014                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
3015                    if self.data.__class__.__name__ == "Data2D" or \
3016                            self.enable2D:
3017                        cb.Show(True)
3018                    else:
3019                        cb.Hide()
3020                    sizer.Add(cb, (iy, ix), (1, 1),
3021                              wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
3022   
3023                    ## add parameter value
3024                    ix += 1
3025                    value = self.model.getParam(item)
3026                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
3027                                        style=wx.TE_PROCESS_ENTER)
3028                    ctl1.SetToolTipString(\
3029                                "Hit 'Enter' after typing to update the plot.")
3030                    ctl1.SetValue(format_number(value, True))
3031                    if self.data.__class__.__name__ == "Data2D" or \
3032                            self.enable2D:
3033                        ctl1.Show(True)
3034                    else:
3035                        ctl1.Hide()
3036                    sizer.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
3037                    ## text to show error sign
3038                    ix += 1
3039                    text2 = wx.StaticText(self, -1, '+/-')
3040                    sizer.Add(text2, (iy, ix), (1, 1), \
3041                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3042
3043                    text2.Hide()
3044                    ix += 1
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)
3049
3050                    ctl2.Hide()
3051                   
3052                    ix += 1
3053                    ctl3 = self.ModelTextCtrl(self, -1,
3054                                              size=(_BOX_WIDTH / 1.8, 20),
3055                                              style=wx.TE_PROCESS_ENTER,
3056                                text_enter_callback=self._onparamRangeEnter)
3057                   
3058                    sizer.Add(ctl3, (iy, ix), (1, 1),
3059                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3060                    ctl3.Hide()
3061                 
3062                    ix += 1
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)
3069                   
3070                    ctl4.Hide()
3071                   
3072                    if self.data.__class__.__name__ == "Data2D" or \
3073                            self.enable2D:
3074                        if self.is_mac:
3075                            text2.Show(True)
3076                            ctl2.Show(True)
3077                        ctl3.Show(True)
3078                        ctl4.Show(True)
3079                   
3080                    ix += 1
3081                    # Units
3082                    if item in self.model.details:
3083                        units = wx.StaticText(self, -1,
3084                                              self.model.details[item][0],
3085                                              style=wx.ALIGN_LEFT)
3086                    else:
3087                        units = wx.StaticText(self, -1, "",
3088                                              style=wx.ALIGN_LEFT)
3089                    if self.data.__class__.__name__ == "Data2D" or \
3090                            self.enable2D:
3091                        units.Show(True)
3092                    else:
3093                        units.Hide()
3094                   
3095                    sizer.Add(units, (iy, ix), (1, 1),
3096                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3097                                         
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])
3102             
3103        iy += 1
3104        box_description.SetForegroundColour(wx.BLUE)
3105        #Display units text on panel
3106        for item in keys:
3107            if item in self.model.details:
3108                self.text2_4.Show()
3109        #Fill the list of fittable parameters
3110        self.get_all_checked_params()
3111        self.save_current_state_fit()
3112        boxsizer1.Add(sizer)
3113        self.sizer3.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
3114        self.sizer3.Layout()
3115        self.Layout()
3116
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():
3125            self._manager.show_ftol_dialog()
3126            flag = True
3127        elif event.AltDown() or event.ShiftDown():
3128            flag = False
3129        else:
3130            return
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
3139            wx.PostEvent(self.parent.parent,
3140                        StatusEvent(status=msg, info=infor))
3141       
3142    def _onModel2D(self, event):
3143        """
3144        toggle view of model from 1D to 2D  or 2D from 1D
3145        """
3146        if self.model_view.GetLabelText() == "Show 2D":
3147            self.model_view.SetLabel("Show 1D")
3148            self.enable2D = True
3149             
3150        else:
3151            self.model_view.SetLabel("Show 2D")
3152            self.enable2D = False
3153        self.Show(False)
3154        self.create_default_data()
3155        self._manager.store_data(self.uid, data_list=[self.data])
3156
3157        self.set_model_param_sizer(self.model)
3158        self._set_sizer_dispersion()
3159        self._set_weight(is_2D=self.enable2D)
3160        self._set_smear_buttons()
3161        self.Show(True)
3162        self.SetupScrolling()
3163        self._draw_model()
3164       
3165        self.state.enable2D = copy.deepcopy(self.enable2D)
3166   
3167    def _set_smear_buttons(self):
3168        """
3169        Set semarer radio buttons
3170        """
3171        # more disables for 2D
3172        if self.data.__class__.__name__ == "Data2D" or \
3173                    self.enable2D:
3174            self.slit_smearer.Disable()
3175            self.pinhole_smearer.Enable(True)
3176            self.default_mask = copy.deepcopy(self.data.mask)
3177        else:
3178            self.slit_smearer.Enable(True)
3179            self.pinhole_smearer.Enable(True)
3180           
3181           
3182class BGTextCtrl(wx.TextCtrl):
3183    """
3184    Text control used to display outputs.
3185    No editing allowed. The background is
3186    grayed out. User can't select text.
3187    """
3188    def __init__(self, *args, **kwds):
3189        wx.TextCtrl.__init__(self, *args, **kwds)
3190        self.SetEditable(False)
3191        self.SetBackgroundColour(self.GetParent().parent.GetBackgroundColour())
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        """
3200        Prevent further handling of the mouse event
3201        by not calling Skip().
3202        """
3203        pass
Note: See TracBrowser for help on using the repository browser.