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

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 db8fd5b was b11e127, checked in by Jae Cho <jhjcho@…>, 12 years ago

removing pre-computation on set data

  • 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            data.dxl = numpy.zeros(data_len)
2408            if self.smear_slit_height.GetValue().lstrip().rstrip() != "":
2409                self.smear_slit_height.SetBackgroundColour("pink")
2410                msg = "Wrong value entered... "
2411            else:
2412                self.smear_slit_height.SetBackgroundColour(wx.WHITE)
2413        try:
2414            self.dxw = float(self.smear_slit_width.GetValue())
2415            self.smear_slit_width.SetBackgroundColour(wx.WHITE)
2416            data.dxw = self.dxw * numpy.ones(data_len)
2417        except:
2418            data.dxw = numpy.zeros(data_len)
2419            if self.smear_slit_width.GetValue().lstrip().rstrip() != "":
2420                self.smear_slit_width.SetBackgroundColour("pink")
2421                msg = "Wrong Fit value entered... "
2422            else:
2423                self.smear_slit_width.SetBackgroundColour(wx.WHITE)
2424             
2425        self.current_smearer = smear_selection(data, self.model)
2426        ## set smearing value whether or not the data contain the smearing info
2427        self._manager.set_smearer(smearer=self.current_smearer,
2428                                 fid=self.data.id,
2429                                 qmin=float(self.qmin_x),
2430                                 qmax=float(self.qmax_x),
2431                        enable_smearer=not self.disable_smearer.GetValue(),
2432                                 uid=self.uid)
2433        return msg
2434   
2435    def update_slit_smear(self):
2436        """
2437        called by kill_focus on pinhole TextCntrl
2438        to update the changes
2439       
2440        :return: False when wrong value was entered
2441       
2442        """
2443        # msg default
2444        msg = None
2445        # check if any value is changed
2446        if self._is_changed_slit():
2447            msg = self._set_slit_smear()
2448        #self._undo.Enable(True)
2449        self.save_current_state()
2450
2451        if msg != None:
2452            return False
2453        else:
2454            return True
2455                           
2456    def onSmear(self, event):
2457        """
2458        Create a smear object that will change the way residuals
2459        are compute when fitting
2460        """
2461        if event != None:
2462            event.Skip()
2463        if self.data is None:
2464            return
2465
2466        if self.model == None:
2467            self.disable_smearer.SetValue(True)
2468            if event == None:
2469                return
2470            msg = "Please select a Model first..."
2471            wx.MessageBox(msg, 'Info')
2472            wx.PostEvent(self._manager.parent,
2473                         StatusEvent(status="Smear: %s" % msg))
2474            return
2475        # Need update param values
2476        self._update_paramv_on_fit()
2477        if self.model != None:
2478            if self.data.is_data:
2479                self._manager.page_finder[self.uid].add_data(data=self.data)
2480        temp_smearer = self.on_smear_helper()
2481       
2482        self.sizer_set_smearer.Layout()
2483        self.Layout()
2484        self._set_weight()
2485       
2486        ## set smearing value whether or not the data contain the smearing info
2487        wx.CallAfter(self._manager.set_smearer, uid=self.uid,
2488                     smearer=temp_smearer,
2489                     fid=self.data.id,
2490                     qmin=float(self.qmin_x),
2491                     qmax=float(self.qmax_x),
2492                     enable_smearer=not self.disable_smearer.GetValue(),
2493                     draw=True)
2494       
2495        self.state.enable_smearer = self.enable_smearer.GetValue()
2496        self.state.disable_smearer = self.disable_smearer.GetValue()
2497        self.state.pinhole_smearer = self.pinhole_smearer.GetValue()
2498        self.state.slit_smearer = self.slit_smearer.GetValue()
2499       
2500    def on_smear_helper(self, update=False):
2501        """
2502        Help for onSmear
2503       
2504        :param update: force or not to update
2505        """
2506        self._get_smear_info()
2507        #renew smear sizer
2508        if self.smear_type != None:
2509            self.smear_description_smear_type.SetValue(str(self.smear_type))
2510            self.smear_data_left.SetValue(str(self.dq_l))
2511            self.smear_data_right.SetValue(str(self.dq_r))
2512
2513        self._hide_all_smear_info()
2514        data = copy.deepcopy(self.data)
2515       
2516        # make sure once more if it is smearer
2517        temp_smearer = smear_selection(data, self.model)
2518        if self.current_smearer != temp_smearer or update:
2519            self.current_smearer = temp_smearer
2520        if self.enable_smearer.GetValue():
2521            if self.current_smearer == None:
2522                wx.PostEvent(self._manager.parent,
2523                    StatusEvent(status="Data contains no smearing information"))
2524            else:
2525                wx.PostEvent(self._manager.parent,
2526                    StatusEvent(status="Data contains smearing information"))
2527
2528            self.smear_data_left.Show(True)
2529            self.smear_data_right.Show(True)
2530            temp_smearer = self.current_smearer
2531        elif self.disable_smearer.GetValue():
2532            self.smear_description_none.Show(True)
2533        elif self.pinhole_smearer.GetValue():
2534            self.onPinholeSmear(None)
2535        elif self.slit_smearer.GetValue():
2536            self.onSlitSmear(None)
2537        self._show_smear_sizer()
2538       
2539        return temp_smearer
2540   
2541    def on_complete_chisqr(self, event):
2542        """
2543        Display result chisqr on the panel
2544        :event: activated by fitting/ complete after draw
2545        """
2546        try:
2547            if event == None:
2548                output = "-"
2549            elif not numpy.isfinite(event.output):
2550                output = "-"
2551            else:
2552                output = event.output
2553            self.tcChi.SetValue(str(format_number(output, True)))
2554            self.state.tcChi = self.tcChi.GetValue()
2555        except:
2556            pass
2557           
2558    def get_all_checked_params(self):
2559        """
2560        Found all parameters current check and add them to list of parameters
2561        to fit
2562        """
2563        self.param_toFit = []
2564        for item in self.parameters:
2565            if item[0].GetValue() and item not in self.param_toFit:
2566                if item[0].IsShown():
2567                    self.param_toFit.append(item)
2568        for item in self.fittable_param:
2569            if item[0].GetValue() and item not in self.param_toFit:
2570                if item[0].IsShown():
2571                    self.param_toFit.append(item)
2572        self.save_current_state_fit()
2573       
2574        event = PageInfoEvent(page=self)
2575        wx.PostEvent(self.parent, event)
2576        param2fit = []
2577        for item in self.param_toFit:
2578            if item[0] and item[0].IsShown():
2579                param2fit.append(item[1])
2580        self.parent._manager.set_param2fit(self.uid, param2fit)
2581               
2582    def select_all_param(self, event):
2583        """
2584        set to true or false all checkBox given the main checkbox value cb1
2585        """
2586        self.param_toFit = []
2587        if  self.parameters != []:
2588            if  self.cb1.GetValue():
2589                for item in self.parameters:
2590                    if item[0].IsShown():
2591                        ## for data2D select all to fit
2592                        if self.data.__class__.__name__ == "Data2D" or \
2593                                self.enable2D:
2594                            item[0].SetValue(True)
2595                            self.param_toFit.append(item)
2596                        else:
2597                            ## for 1D all parameters except orientation
2598                            if not item in self.orientation_params:
2599                                item[0].SetValue(True)
2600                                self.param_toFit.append(item)
2601                    else:
2602                        item[0].SetValue(False)
2603                #if len(self.fittable_param)>0:
2604                for item in self.fittable_param:
2605                    if item[0].IsShown():
2606                        if self.data.__class__.__name__ == "Data2D" or \
2607                                self.enable2D:
2608                            item[0].SetValue(True)
2609                            self.param_toFit.append(item)
2610                            try:
2611                                if len(self.values[item[1]]) > 0:
2612                                    item[0].SetValue(False)
2613                            except:
2614                                pass
2615   
2616                        else:
2617                            ## for 1D all parameters except orientation
2618                            if not item in self.orientation_params_disp:
2619                                item[0].SetValue(True)
2620                                self.param_toFit.append(item)
2621                                try:
2622                                    if len(self.values[item[1]]) > 0:
2623                                        item[0].SetValue(False)
2624                                except:
2625                                    pass
2626                    else:
2627                        item[0].SetValue(False)
2628
2629            else:
2630                for item in self.parameters:
2631                    item[0].SetValue(False)
2632                for item in self.fittable_param:
2633                    item[0].SetValue(False)
2634                self.param_toFit = []
2635           
2636        self.save_current_state_fit()
2637       
2638        if event != None:
2639            #self._undo.Enable(True)
2640            ## post state to fit panel
2641            event = PageInfoEvent(page=self)
2642            wx.PostEvent(self.parent, event)
2643        param2fit = []
2644        for item in self.param_toFit:
2645            if item[0] and item[0].IsShown():
2646                param2fit.append(item[1])
2647        self.parent._manager.set_param2fit(self.uid, param2fit)
2648
2649    def select_param(self, event):
2650        """
2651        Select TextCtrl  checked for fitting purpose and stores them
2652        in  self.param_toFit=[] list
2653        """
2654        self.param_toFit = []
2655        for item in self.parameters:
2656            #Skip t ifhe angle parameters if 1D data
2657            if self.data.__class__.__name__ != "Data2D" and\
2658                        not self.enable2D:
2659                if item in self.orientation_params:
2660                    continue
2661            #Select parameters to fit for list of primary parameters
2662            if item[0].GetValue() and item[0].IsShown():
2663                if not (item in self.param_toFit):
2664                    self.param_toFit.append(item)
2665            else:
2666                #remove parameters from the fitting list
2667                if item in self.param_toFit:
2668                    self.param_toFit.remove(item)
2669
2670        #Select parameters to fit for list of fittable parameters
2671        #        with dispersion
2672        for item in self.fittable_param:
2673            #Skip t ifhe angle parameters if 1D data
2674            if self.data.__class__.__name__ != "Data2D" and\
2675                        not self.enable2D:
2676                if item in self.orientation_params:
2677                    continue
2678            if item[0].GetValue() and item[0].IsShown():
2679                if not (item in self.param_toFit):
2680                    self.param_toFit.append(item)
2681            else:
2682                #remove parameters from the fitting list
2683                if item in self.param_toFit:
2684                    self.param_toFit.remove(item)
2685
2686        #Calculate num. of angle parameters
2687        if self.data.__class__.__name__ == "Data2D" or \
2688                       self.enable2D:
2689            len_orient_para = 0
2690        else:
2691            len_orient_para = len(self.orientation_params)  # assume even len
2692        #Total num. of angle parameters
2693        if len(self.fittable_param) > 0:
2694            len_orient_para *= 2
2695        #Set the value of checkbox that selected every checkbox or not
2696        if len(self.parameters) + len(self.fittable_param) - len_orient_para \
2697            == len(self.param_toFit):
2698            self.cb1.SetValue(True)
2699        else:
2700            self.cb1.SetValue(False)
2701       
2702        self.save_current_state_fit()
2703        if event != None:
2704            ## post state to fit panel
2705            event = PageInfoEvent(page=self)
2706            wx.PostEvent(self.parent, event)
2707       
2708        param2fit = []
2709        for item in self.param_toFit:
2710            if item[0] and item[0].IsShown():
2711                param2fit.append(item[1])
2712        self.parent._manager.set_param2fit(self.uid, param2fit)
2713       
2714    def set_model_param_sizer(self, model):
2715        """
2716        Build the panel from the model content
2717       
2718        :param model: the model selected in combo box for fitting purpose
2719       
2720        """
2721        self.sizer3.Clear(True)
2722        self.parameters = []
2723        self.str_parameters = []
2724        self.param_toFit = []
2725        self.fittable_param = []
2726        self.fixed_param = []
2727        self.orientation_params = []
2728        self.orientation_params_disp = []
2729       
2730        if model == None:
2731            self.sizer3.Layout()
2732            self.SetupScrolling()
2733            return
2734        ## the panel is drawn using the current value of the fit engine
2735        if self.engine_type == None and self._manager != None:
2736            self.engine_type = self._manager._return_engine_type()
2737
2738        box_description = wx.StaticBox(self, -1, str("Model Parameters"))
2739        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
2740        sizer = wx.GridBagSizer(5, 5)
2741        ## save the current model
2742        self.model = model
2743           
2744        keys = self.model.getParamList()
2745        #list of dispersion paramaters
2746        self.disp_list = self.model.getDispParamList()
2747
2748        def custom_compare(a, b):
2749            """
2750            Custom compare to order, first by alphabets then second by number.
2751            """
2752            # number at the last digit
2753            a_last = a[len(a) - 1]
2754            b_last = b[len(b) - 1]
2755            # default
2756            num_a = None
2757            num_b = None
2758            # split the names
2759            a2 = a.lower().split('_')
2760            b2 = b.lower().split('_')
2761            # check length of a2, b2
2762            len_a2 = len(a2)
2763            len_b2 = len(b2)
2764            # check if it contains a int number(<10)
2765            try:
2766                num_a = int(a_last)
2767            except:
2768                pass
2769            try:
2770                num_b = int(b_last)
2771            except:
2772                pass
2773            # Put 'scale' near the top; happens
2774            # when numbered param name exists
2775            if a == 'scale':
2776                return -1
2777            # both have a number
2778            if num_a != None and num_b != None:
2779                if num_a > num_b:
2780                    return -1
2781                # same number
2782                elif num_a == num_b:
2783                    # different last names
2784                    if a2[len_a2 - 1] != b2[len_b2 - 1] and num_a != 0:
2785                        return -cmp(a2[len_a2 - 1], b2[len_b2 - 1])
2786                    else:
2787                        return cmp(a, b)
2788                else:
2789                    return 1
2790            # one of them has a number
2791            elif num_a != None:
2792                return 1
2793            elif num_b != None:
2794                return -1
2795            # no numbers
2796            else:
2797                return cmp(a.lower(), b.lower())
2798
2799        keys.sort(custom_compare)
2800   
2801        iy = 0
2802        ix = 0
2803        select_text = "Select All"
2804        self.cb1 = wx.CheckBox(self, -1, str(select_text), (10, 10))
2805        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
2806        self.cb1.SetToolTipString("To check/uncheck all the boxes below.")
2807        self.cb1.SetValue(True)
2808       
2809        sizer.Add(self.cb1, (iy, ix), (1, 1), \
2810                             wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
2811        ix += 1
2812        self.text2_2 = wx.StaticText(self, -1, 'Value')
2813        sizer.Add(self.text2_2, (iy, ix), (1, 1), \
2814                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2815        ix += 2
2816        self.text2_3 = wx.StaticText(self, -1, 'Error')
2817        sizer.Add(self.text2_3, (iy, ix), (1, 1), \
2818                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2819        if not self.is_mac:
2820            self.text2_3.Hide()
2821        ix += 1
2822        self.text2_min = wx.StaticText(self, -1, 'Min')
2823        sizer.Add(self.text2_min, (iy, ix), (1, 1), \
2824                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2825        #self.text2_min.Hide()
2826        ix += 1
2827        self.text2_max = wx.StaticText(self, -1, 'Max')
2828        sizer.Add(self.text2_max, (iy, ix), (1, 1), \
2829                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2830        #self.text2_max.Hide()
2831        ix += 1
2832        self.text2_4 = wx.StaticText(self, -1, '[Units]')
2833        sizer.Add(self.text2_4, (iy, ix), (1, 1), \
2834                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2835        self.text2_4.Hide()
2836       
2837        CHECK_STATE = self.cb1.GetValue()
2838        for item in keys:
2839            if not item in self.disp_list and not item in \
2840                    self.model.orientation_params:
2841               
2842                ##prepare a spot to store errors
2843                if not item in self.model.details:
2844                    self.model.details[item] = ["", None, None]
2845         
2846                iy += 1
2847                ix = 0
2848                if (self.model.__class__ in \
2849                    self.model_list_box["Multi-Functions"] or \
2850                    self.temp_multi_functional)\
2851                    and (item in self.model.non_fittable):
2852                    non_fittable_name = wx.StaticText(self, -1, item)
2853                    sizer.Add(non_fittable_name, (iy, ix), (1, 1), \
2854                            wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 21)
2855                    ## add parameter value
2856                    ix += 1
2857                    value = self.model.getParam(item)
2858                    if len(self.model.fun_list) > 0:
2859                        #num = item.split('_')[1][5:7]
2860                        fun_box = wx.ComboBox(self, -1, size=(100, -1),
2861                                    style=wx.CB_READONLY, name='%s' % item)
2862                        self._set_fun_box_list(fun_box)
2863                        fun_box.SetSelection(0)
2864                        #self.fun_box.SetToolTipString("A function
2865                        #    describing the interface")
2866                        wx.EVT_COMBOBOX(fun_box, -1, self._on_fun_box)
2867                    else:
2868                        fun_box = self.ModelTextCtrl(self, -1,
2869                                                     size=(_BOX_WIDTH, 20),
2870                                style=wx.TE_PROCESS_ENTER, name='%s' % item)
2871                        fun_box.SetToolTipString(\
2872                                "Hit 'Enter' after typing to update the plot.")
2873                        fun_box.SetValue(format_number(value, True))
2874                    sizer.Add(fun_box, (iy, ix), (1, 1), wx.EXPAND)
2875                    self.str_parameters.append([None, item, fun_box,
2876                                                None, None, None,
2877                                                None, None])
2878                else:
2879                    ## add parameters name with checkbox for selecting to fit
2880                    cb = wx.CheckBox(self, -1, item)
2881                    cb.SetValue(CHECK_STATE)
2882                    cb.SetToolTipString(" Check mark to fit.")
2883                    #cb.SetValue(True)
2884                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
2885                   
2886                    sizer.Add(cb, (iy, ix), (1, 1),
2887                              wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
2888
2889                    ## add parameter value
2890                    ix += 1
2891                    value = self.model.getParam(item)
2892                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
2893                                        style=wx.TE_PROCESS_ENTER)
2894                    ctl1.SetToolTipString(\
2895                                "Hit 'Enter' after typing to update the plot.")
2896                    ctl1.SetValue(format_number(value, True))
2897                    sizer.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
2898                    ## text to show error sign
2899                    ix += 1
2900                    text2 = wx.StaticText(self, -1, '+/-')
2901                    sizer.Add(text2, (iy, ix), (1, 1), \
2902                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2903                    if not self.is_mac:
2904                        text2.Hide()
2905                    ix += 1
2906                    ctl2 = wx.TextCtrl(self, -1,
2907                                       size=(_BOX_WIDTH / 1.2, 20), style=0)
2908                    sizer.Add(ctl2, (iy, ix), (1, 1),
2909                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2910                    if not self.is_mac:
2911                        ctl2.Hide()
2912                   
2913                    ix += 1
2914                    ctl3 = self.ModelTextCtrl(self, -1,
2915                                              size=(_BOX_WIDTH / 1.9, 20),
2916                                              style=wx.TE_PROCESS_ENTER,
2917                                text_enter_callback=self._onparamRangeEnter)
2918         
2919                    sizer.Add(ctl3, (iy, ix), (1, 1),
2920                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2921           
2922                    ix += 1
2923                    ctl4 = self.ModelTextCtrl(self, -1,
2924                                              size=(_BOX_WIDTH / 1.9, 20),
2925                                              style=wx.TE_PROCESS_ENTER,
2926                                text_enter_callback=self._onparamRangeEnter)
2927                    sizer.Add(ctl4, (iy, ix), (1, 1),
2928                              wx.EXPAND | wx.FIXED_MINSIZE, 0)
2929   
2930                    ix += 1
2931                    # Units
2932                    if item in self.model.details:
2933                        units = wx.StaticText(self, -1,
2934                            self.model.details[item][0], style=wx.ALIGN_LEFT)
2935                    else:
2936                        units = wx.StaticText(self, -1, "",
2937                                              style=wx.ALIGN_LEFT)
2938                    sizer.Add(units, (iy, ix), (1, 1),
2939                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
2940                       
2941                    self.parameters.append([cb, item, ctl1,
2942                                            text2, ctl2, ctl3, ctl4, units])
2943                                 
2944        iy += 1
2945        sizer.Add((10, 10), (iy, ix), (1, 1),
2946                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
2947       
2948        # type can be either Guassian or Array
2949        if len(self.model.dispersion.values()) > 0:
2950            type = self.model.dispersion.values()[0]["type"]
2951        else:
2952            type = "Gaussian"
2953           
2954        iy += 1
2955        ix = 0
2956        #Add tile for orientational angle
2957        for item in keys:
2958            if item in self.model.orientation_params:
2959                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
2960                mag_on_button = wx.Button(self, -1, "Magnetic ON" )
2961                mag_on_button.Bind(wx.EVT_BUTTON, self._on_mag_on)
2962                mag_help_button = wx.Button(self, -1,"Magnetic angles?" )
2963                mag_help_button.Bind(wx.EVT_BUTTON,self._on_mag_help)
2964                sizer.Add(orient_angle, (iy, ix), (1, 1),
2965                          wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15)
2966                iy += 1
2967                sizer.Add(mag_on_button,(iy, ix ),(1,1), 
2968                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
2969                sizer.Add(mag_help_button,(iy, ix + 1),(1,1), 
2970                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
2971               
2972                #handle the magnetic buttons
2973                if not self._has_magnetic:
2974                    mag_on_button.Show(False)
2975                elif not self.data.__class__.__name__ == "Data2D":
2976                    mag_on_button.Show(False)
2977                else:
2978                    mag_on_button.Show(True)
2979                mag_help_button.Show(False)
2980                if mag_on_button.IsShown():
2981                    if self.magnetic_on:
2982                        mag_on_button.SetLabel("Magnetic OFF")
2983                        mag_help_button.Show(True) 
2984                    else:
2985                        mag_on_button.SetLabel("Magnetic ON")
2986                        mag_help_button.Show(False)
2987                       
2988                if not self.data.__class__.__name__ == "Data2D" and \
2989                        not self.enable2D:
2990                    orient_angle.Hide()
2991                else:
2992                    orient_angle.Show(True)
2993                break
2994     
2995        #For Gaussian only
2996        if type.lower() != "array":
2997            for item in self.model.orientation_params:
2998                if not self.magnetic_on:
2999                    if item in self.model.magnetic_params:
3000                        continue
3001                if not item in self.disp_list:
3002                    ##prepare a spot to store min max
3003                    if not item in self.model.details:
3004                        self.model.details[item] = ["", None, None]
3005                         
3006                    iy += 1
3007                    ix = 0
3008                    ## add parameters name with checkbox for selecting to fit
3009                    cb = wx.CheckBox(self, -1, item)
3010                    cb.SetValue(CHECK_STATE)
3011                    cb.SetToolTipString("Check mark to fit")
3012                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
3013                    if self.data.__class__.__name__ == "Data2D" or \
3014                            self.enable2D:
3015                        cb.Show(True)
3016                    else:
3017                        cb.Hide()
3018                    sizer.Add(cb, (iy, ix), (1, 1),
3019                              wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
3020   
3021                    ## add parameter value
3022                    ix += 1
3023                    value = self.model.getParam(item)
3024                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
3025                                        style=wx.TE_PROCESS_ENTER)
3026                    ctl1.SetToolTipString(\
3027                                "Hit 'Enter' after typing to update the plot.")
3028                    ctl1.SetValue(format_number(value, True))
3029                    if self.data.__class__.__name__ == "Data2D" or \
3030                            self.enable2D:
3031                        ctl1.Show(True)
3032                    else:
3033                        ctl1.Hide()
3034                    sizer.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND)
3035                    ## text to show error sign
3036                    ix += 1
3037                    text2 = wx.StaticText(self, -1, '+/-')
3038                    sizer.Add(text2, (iy, ix), (1, 1), \
3039                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3040
3041                    text2.Hide()
3042                    ix += 1
3043                    ctl2 = wx.TextCtrl(self, -1,
3044                                       size=(_BOX_WIDTH / 1.2, 20), style=0)
3045                    sizer.Add(ctl2, (iy, ix), (1, 1),
3046                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3047
3048                    ctl2.Hide()
3049                   
3050                    ix += 1
3051                    ctl3 = self.ModelTextCtrl(self, -1,
3052                                              size=(_BOX_WIDTH / 1.8, 20),
3053                                              style=wx.TE_PROCESS_ENTER,
3054                                text_enter_callback=self._onparamRangeEnter)
3055                   
3056                    sizer.Add(ctl3, (iy, ix), (1, 1),
3057                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3058                    ctl3.Hide()
3059                 
3060                    ix += 1
3061                    ctl4 = self.ModelTextCtrl(self, -1,
3062                                              size=(_BOX_WIDTH / 1.8, 20),
3063                                              style=wx.TE_PROCESS_ENTER,
3064                            text_enter_callback=self._onparamRangeEnter)
3065                    sizer.Add(ctl4, (iy, ix), (1, 1),
3066                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3067                   
3068                    ctl4.Hide()
3069                   
3070                    if self.data.__class__.__name__ == "Data2D" or \
3071                            self.enable2D:
3072                        if self.is_mac:
3073                            text2.Show(True)
3074                            ctl2.Show(True)
3075                        ctl3.Show(True)
3076                        ctl4.Show(True)
3077                   
3078                    ix += 1
3079                    # Units
3080                    if item in self.model.details:
3081                        units = wx.StaticText(self, -1,
3082                                              self.model.details[item][0],
3083                                              style=wx.ALIGN_LEFT)
3084                    else:
3085                        units = wx.StaticText(self, -1, "",
3086                                              style=wx.ALIGN_LEFT)
3087                    if self.data.__class__.__name__ == "Data2D" or \
3088                            self.enable2D:
3089                        units.Show(True)
3090                    else:
3091                        units.Hide()
3092                   
3093                    sizer.Add(units, (iy, ix), (1, 1),
3094                              wx.EXPAND | wx.ADJUST_MINSIZE, 0)
3095                                         
3096                    self.parameters.append([cb, item, ctl1,
3097                                            text2, ctl2, ctl3, ctl4, units])
3098                    self.orientation_params.append([cb, item, ctl1,
3099                                            text2, ctl2, ctl3, ctl4, units])
3100             
3101        iy += 1
3102        box_description.SetForegroundColour(wx.BLUE)
3103        #Display units text on panel
3104        for item in keys:
3105            if item in self.model.details:
3106                self.text2_4.Show()
3107        #Fill the list of fittable parameters
3108        self.get_all_checked_params()
3109        self.save_current_state_fit()
3110        boxsizer1.Add(sizer)
3111        self.sizer3.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
3112        self.sizer3.Layout()
3113        self.Layout()
3114
3115    def on_right_down(self, event):
3116        """
3117        Get key stroke event
3118        """
3119        if self.data == None:
3120            return
3121        # Figuring out key combo: Cmd for copy, Alt for paste
3122        if event.AltDown() and event.ShiftDown():
3123            self._manager.show_ftol_dialog()
3124            flag = True
3125        elif event.AltDown() or event.ShiftDown():
3126            flag = False
3127        else:
3128            return
3129        # make event free
3130        event.Skip()
3131        # messages depending on the flag
3132        if not flag:
3133            msg = " Could not open ftol dialog;"
3134            msg += " Check if the Scipy fit engine is selected in the menubar."
3135            infor = 'warning'
3136            # inform msg to wx
3137            wx.PostEvent(self.parent.parent,
3138                        StatusEvent(status=msg, info=infor))
3139       
3140    def _onModel2D(self, event):
3141        """
3142        toggle view of model from 1D to 2D  or 2D from 1D
3143        """
3144        if self.model_view.GetLabelText() == "Show 2D":
3145            self.model_view.SetLabel("Show 1D")
3146            self.enable2D = True
3147             
3148        else:
3149            self.model_view.SetLabel("Show 2D")
3150            self.enable2D = False
3151        self.Show(False)
3152        self.create_default_data()
3153        self._manager.store_data(self.uid, data_list=[self.data])
3154
3155        self.set_model_param_sizer(self.model)
3156        self._set_sizer_dispersion()
3157        self._set_weight(is_2D=self.enable2D)
3158        self._set_smear_buttons()
3159        self.Show(True)
3160        self.SetupScrolling()
3161        self._draw_model()
3162       
3163        self.state.enable2D = copy.deepcopy(self.enable2D)
3164   
3165    def _set_smear_buttons(self):
3166        """
3167        Set semarer radio buttons
3168        """
3169        # more disables for 2D
3170        if self.data.__class__.__name__ == "Data2D" or \
3171                    self.enable2D:
3172            self.slit_smearer.Disable()
3173            self.pinhole_smearer.Enable(True)
3174            self.default_mask = copy.deepcopy(self.data.mask)
3175        else:
3176            self.slit_smearer.Enable(True)
3177            self.pinhole_smearer.Enable(True)
3178           
3179           
3180class BGTextCtrl(wx.TextCtrl):
3181    """
3182    Text control used to display outputs.
3183    No editing allowed. The background is
3184    grayed out. User can't select text.
3185    """
3186    def __init__(self, *args, **kwds):
3187        wx.TextCtrl.__init__(self, *args, **kwds)
3188        self.SetEditable(False)
3189        self.SetBackgroundColour(self.GetParent().parent.GetBackgroundColour())
3190       
3191        # Bind to mouse event to avoid text highlighting
3192        # The event will be skipped once the call-back
3193        # is called.
3194        self.Bind(wx.EVT_MOUSE_EVENTS, self._click)
3195       
3196    def _click(self, event):
3197        """
3198        Prevent further handling of the mouse event
3199        by not calling Skip().
3200        """
3201        pass
Note: See TracBrowser for help on using the repository browser.