source: sasview/fittingview/src/sans/perspectives/fitting/basepage.py @ be1ec9f

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

base_page: pylint cleanup#2

  • Property mode set to 100644
File size: 136.6 KB
Line 
1"""
2Base Page for fitting
3"""
4import sys
5import os
6import wx
7import numpy
8import time
9import copy
10import math
11import string
12from wx.lib.scrolledpanel import ScrolledPanel
13from sans.guiframe.panel_base import PanelBase
14from sans.guiframe.utils import format_number, check_float
15from sans.guiframe.events import PanelOnFocusEvent
16from sans.guiframe.events import StatusEvent
17from sans.guiframe.events import AppendBookmarkEvent
18from sans.guiframe.dataFitting import Data2D
19from sans.guiframe.dataFitting import Data1D
20from sans.guiframe.dataFitting import check_data_validity
21from sans.dataloader.data_info import Detector
22from sans.dataloader.data_info import Source
23from sans.perspectives.fitting.pagestate import PageState
24
25(PageInfoEvent, EVT_PAGE_INFO) = wx.lib.newevent.NewEvent()
26(PreviousStateEvent, EVT_PREVIOUS_STATE) = wx.lib.newevent.NewEvent()
27(NextStateEvent, EVT_NEXT_STATE) = wx.lib.newevent.NewEvent()
28
29_BOX_WIDTH = 76
30_QMIN_DEFAULT = 0.0005
31_QMAX_DEFAULT = 0.5
32_NPTS_DEFAULT = 50
33#Control panel width
34if sys.platform.count("win32") > 0:
35    PANEL_WIDTH = 450
36    FONT_VARIANT = 0
37    ON_MAC = False
38else:
39    PANEL_WIDTH = 500
40    FONT_VARIANT = 1
41    ON_MAC = True
42
43
44class BasicPage(ScrolledPanel, PanelBase):
45    """
46    This class provide general structure of  fitpanel page
47    """
48    ## Internal name for the AUI manager
49    window_name = "Fit Page"
50    ## Title to appear on top of the window
51    window_caption = "Fit Page "
52   
53    def __init__(self, parent, color='blue', **kwargs):
54        """
55        """
56        ScrolledPanel.__init__(self, parent, **kwargs)
57        PanelBase.__init__(self, parent)
58        self.SetupScrolling()
59        #Set window's font size
60        self.SetWindowVariant(variant=FONT_VARIANT)
61     
62        self.SetBackgroundColour(color)
63        ## parent of the page
64        self.parent = parent
65        ## manager is the fitting plugin
66        ## owner of the page (fitting plugin)
67        self.event_owner = None
68        ## current model
69        self.model = None
70        self.m_name = None
71        self.index_model = None
72        self.panel = None
73        ## data
74        self.data = None
75        #list of available data
76        self.data_list = []
77        self.mask = None
78        self.uid = wx.NewId()
79        self.graph_id = None
80        #Q range for data set
81        self.qmin_data_set = numpy.inf
82        self.qmax_data_set = None
83        self.npts_data_set = 0
84        ## Q range
85        self.qmin = None
86        self.qmax = None
87        self.qmax_x = _QMAX_DEFAULT
88        self.qmin_x = _QMIN_DEFAULT
89        self.npts_x = _NPTS_DEFAULT
90        ## total number of point: float
91        self.npts = None
92        self.num_points = None
93        ## default fitengine type
94        self.engine_type = 'scipy'
95        ## smear default
96        self.current_smearer = None
97        ## 2D smear accuracy default
98        self.smear2d_accuracy = 'Low'
99        ## slit smear:
100        self.dxl = None
101        self.dxw = None
102        ## pinhole smear
103        self.dx_min = None
104        self.dx_max = None
105        ##semar attrbs
106        self.enable_smearer = None
107        self.disable_smearer = None
108        self.pinhole_smearer = None
109        self.slit_smearer = None
110        ##weigth attrbs
111        self.dI_noweight = None
112        self.dI_didata = None
113        self.dI_sqrdata = None
114        self.dI_idata = None
115        ##other attrbs
116        self.dq_l = None
117        self.dq_r = None
118        self.tcChi = None
119        self.disp_box = None
120        self.model_disp = None
121        self.Npts_fit = None
122        self.Npts_total = None
123        self.theory_qmin = None 
124        self.theory_qmax = None
125        self.theory_qmin_x = None
126        self.theory_qmax_x = None
127        self.cb1 = None
128        self.btEditMask = None
129        self.btFit = None
130        self.sld_axes = None
131        self.multi_factor = None
132       
133        self.disp_cb_dict = {}
134   
135        #self.state = PageState(parent=parent)
136        ## dictionary containing list of models
137        self.model_list_box = {}
138       
139        ## Data member to store the dispersion object created
140        self._disp_obj_dict = {}
141        ## selected parameters to apply dispersion
142        self.disp_cb_dict = {}
143        ## smearer object
144        self.enable2D = False
145        self.is_mac = ON_MAC
146        self.formfactorbox = None
147        self.structurebox = None
148        ##list of model parameters. each item must have same length
149        ## each item related to a given parameters
150        ##[cb state, name, value, "+/-", error of fit, min, max , units]
151        self.parameters = []
152        # non-fittable parameter whose value is astring
153        self.str_parameters = []
154        ## list of parameters to fit , must be like self.parameters
155        self.param_toFit = []
156        ## list of looking like parameters but with non fittable parameters info
157        self.fixed_param = []
158        ## list of looking like parameters but with  fittable parameters info
159        self.fittable_param = []
160        ##list of dispersion parameters
161        self.disp_list = []
162        self.disp_name = ""
163       
164        ## list of orientation parameters
165        self.orientation_params = []
166        self.orientation_params_disp = []
167        if self.model != None:
168            self.disp_list = self.model.getDispParamList()
169        self.temp_multi_functional = False
170        ##enable model 2D draw
171        self.enable2D = False
172        ## check that the fit range is correct to plot the model again
173        self.fitrange = True
174        ## Create memento to save the current state
175        self.state = PageState(parent=self.parent,
176                               model=self.model, data=self.data)
177        ## flag to determine if state has change
178        self.state_change = False
179        ## save customized array
180        self.values = []
181        self.weights = []
182        ## retrieve saved state
183        self.number_saved_state = 0
184        ## dictionary of saved state
185        self.saved_states = {}
186        ## Create context menu for page
187        self.popUpMenu = wx.Menu()
188   
189        id = wx.NewId()
190        self._keep = wx.MenuItem(self.popUpMenu, id, "Add bookmark",
191                                 " Keep the panel status to recall it later")
192        self.popUpMenu.AppendItem(self._keep)
193        self._keep.Enable(False)
194        self._set_bookmark_flag(False)
195        self._set_save_flag(False)
196        wx.EVT_MENU(self, id, self.on_bookmark)
197        self.popUpMenu.AppendSeparator()
198   
199        ## Default locations
200        self._default_save_location = os.getcwd()
201        ## save initial state on context menu
202        #self.onSave(event=None)
203        self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
204       
205        # bind key event
206        self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
207       
208        ## create the basic structure of the panel with empty sizer
209        self.define_page_structure()
210        ## drawing Initial dispersion parameters sizer
211        self.set_dispers_sizer()
212       
213        ## layout
214        self.set_layout()
215   
216    def set_index_model(self, index):
217        """
218        Index related to this page
219        """
220        self.index_model = index
221       
222    def create_default_data(self):
223        """
224        Given the user selection, creates a 1D or 2D data
225        Only when the page is on theory mode.
226        """
227        if not hasattr(self, "model_view"):
228            return
229        toggle_mode_on = self.model_view.IsEnabled()
230        if toggle_mode_on:
231            if self.enable2D and not check_data_validity(self.data):
232                self._create_default_2d_data()
233            else:
234                self._create_default_1d_data()
235            if self.model != None:
236                if not self.data.is_data:
237                    self._manager.page_finder[self.uid].set_fit_data(data=\
238                                                                [self.data])
239            self.on_smear_helper(update=True)
240            self.state.enable_smearer = self.enable_smearer.GetValue()
241            self.state.disable_smearer = self.disable_smearer.GetValue()
242            self.state.pinhole_smearer = self.pinhole_smearer.GetValue()
243            self.state.slit_smearer = self.slit_smearer.GetValue()
244       
245    def _create_default_1d_data(self):
246        """
247        Create default data for fitting perspective
248        Only when the page is on theory mode.
249        :warning: This data is never plotted.
250       
251        """
252        x = numpy.linspace(start=self.qmin_x, stop=self.qmax_x,
253                           num=self.npts_x, endpoint=True)
254        self.data = Data1D(x=x)
255        self.data.xaxis('\\rm{Q}', "A^{-1}")
256        self.data.yaxis('\\rm{Intensity}', "cm^{-1}")
257        self.data.is_data = False
258        self.data.id = str(self.uid) + " data"
259        self.data.group_id = str(self.uid) + " Model1D"
260       
261    def _create_default_2d_data(self):
262        """
263        Create 2D data by default
264        Only when the page is on theory mode.
265        :warning: This data is never plotted.
266        """
267        self.data = Data2D()
268        qmax = self.qmax_x / math.sqrt(2)
269        self.data.xaxis('\\rm{Q_{x}}', 'A^{-1}')
270        self.data.yaxis('\\rm{Q_{y}}', 'A^{-1}')
271        self.data.is_data = False
272        self.data.id = str(self.uid) + " data"
273        self.data.group_id = str(self.uid) + " Model2D"
274        ## Default values
275        self.data.detector.append(Detector())
276        index = len(self.data.detector) - 1
277        self.data.detector[index].distance = 8000   # mm
278        self.data.source.wavelength = 6             # A
279        self.data.detector[index].pixel_size.x = 5  # mm
280        self.data.detector[index].pixel_size.y = 5  # mm
281        self.data.detector[index].beam_center.x = qmax
282        self.data.detector[index].beam_center.y = qmax
283        ## create x_bins and y_bins of the model 2D
284        #pixel_width_x = self.data.detector[index].pixel_size.x
285        #pixel_width_y = self.data.detector[index].pixel_size.y
286        #center_x = self.data.detector[index].beam_center.x/pixel_width_x
287        #center_y = self.data.detector[index].beam_center.y/pixel_width_y
288        # theory default: assume the beam
289        #center is located at the center of sqr detector
290        xmax = qmax
291        xmin = -qmax
292        ymax = qmax
293        ymin = -qmax
294        qstep = self.npts_x
295
296        x = numpy.linspace(start=xmin, stop=xmax, num=qstep, endpoint=True)
297        y = numpy.linspace(start=ymin, stop=ymax, num=qstep, endpoint=True)
298        ## use data info instead
299        new_x = numpy.tile(x, (len(y), 1))
300        new_y = numpy.tile(y, (len(x), 1))
301        new_y = new_y.swapaxes(0, 1)
302        # all data reuire now in 1d array
303        qx_data = new_x.flatten()
304        qy_data = new_y.flatten()
305        q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
306        # set all True (standing for unmasked) as default
307        mask = numpy.ones(len(qx_data), dtype=bool)
308        # calculate the range of qx and qy: this way,
309        # it is a little more independent
310        #x_size = xmax - xmin
311        #y_size = ymax - ymin
312        # store x and y bin centers in q space
313        x_bins = x
314        y_bins = y
315        # bin size: x- & y-directions
316        #xstep = x_size / len(x_bins - 1)
317        #ystep = y_size / len(y_bins - 1)
318 
319        self.data.source = Source()
320        self.data.data = numpy.ones(len(mask))
321        self.data.err_data = numpy.ones(len(mask))
322        self.data.qx_data = qx_data
323        self.data.qy_data = qy_data
324        self.data.q_data = q_data
325        self.data.mask = mask
326        self.data.x_bins = x_bins
327        self.data.y_bins = y_bins
328        # max and min taking account of the bin sizes
329        self.data.xmin = xmin
330        self.data.xmax = xmax
331        self.data.ymin = ymin
332        self.data.ymax = ymax
333
334    def on_set_focus(self, event):
335        """
336        On Set Focus, update guimanger and menu
337        """
338        if self._manager is not None:
339            wx.PostEvent(self._manager.parent, PanelOnFocusEvent(panel=self))
340            self.on_tap_focus()
341               
342    def on_tap_focus(self):
343        """
344        Update menu1 on cliking the page tap
345        """
346        if self._manager.menu1 != None:
347            chain_menu = self._manager.menu1.FindItemById(\
348                                                   self._manager.id_reset_flag)
349            chain_menu.Enable(self.batch_on)
350            sim_menu = self._manager.menu1.FindItemById(self._manager.id_simfit)
351            flag = self.data.is_data\
352                            and (self.model != None)
353            sim_menu.Enable(not self.batch_on and flag)
354            batch_menu = \
355                    self._manager.menu1.FindItemById(self._manager.id_batchfit)
356            batch_menu.Enable(self.batch_on and flag)
357   
358    class ModelTextCtrl(wx.TextCtrl):
359        """
360        Text control for model and fit parameters.
361        Binds the appropriate events for user interactions.
362        Default callback methods can be overwritten on initialization
363       
364        :param kill_focus_callback: callback method for EVT_KILL_FOCUS event
365        :param set_focus_callback:  callback method for EVT_SET_FOCUS event
366        :param mouse_up_callback:   callback method for EVT_LEFT_UP event
367        :param text_enter_callback: callback method for EVT_TEXT_ENTER event
368       
369        """
370        ## Set to True when the mouse is clicked while whole string is selected
371        full_selection = False
372        ## Call back for EVT_SET_FOCUS events
373        _on_set_focus_callback = None
374       
375        def __init__(self, parent, id=-1,
376                     value=wx.EmptyString,
377                     pos=wx.DefaultPosition,
378                     size=wx.DefaultSize,
379                     style=0,
380                     validator=wx.DefaultValidator,
381                     name=wx.TextCtrlNameStr,
382                     kill_focus_callback=None,
383                     set_focus_callback=None,
384                     mouse_up_callback=None,
385                     text_enter_callback=None):
386             
387            wx.TextCtrl.__init__(self, parent, id, value, pos,
388                                  size, style, validator, name)
389           
390            # Bind appropriate events
391            self._on_set_focus_callback = parent.onSetFocus \
392                      if set_focus_callback is None else set_focus_callback
393            self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus)
394            self.Bind(wx.EVT_KILL_FOCUS, self._silent_kill_focus \
395                      if kill_focus_callback is None else kill_focus_callback)
396            self.Bind(wx.EVT_TEXT_ENTER, parent._onparamEnter \
397                      if text_enter_callback is None else text_enter_callback)
398            if not ON_MAC:
399                self.Bind(wx.EVT_LEFT_UP, self._highlight_text \
400                          if mouse_up_callback is None else mouse_up_callback)
401           
402        def _on_set_focus(self, event):
403            """
404            Catch when the text control is set in focus to highlight the whole
405            text if necessary
406           
407            :param event: mouse event
408           
409            """
410            event.Skip()
411            self.full_selection = True
412            return self._on_set_focus_callback(event)
413       
414        def _highlight_text(self, event):
415            """
416            Highlight text of a TextCtrl only of no text has be selected
417           
418            :param event: mouse event
419           
420            """
421            # Make sure the mouse event is available to other listeners
422            event.Skip()
423            control = event.GetEventObject()
424            if self.full_selection:
425                self.full_selection = False
426                # Check that we have a TextCtrl
427                if issubclass(control.__class__, wx.TextCtrl):
428                    # Check whether text has been selected,
429                    # if not, select the whole string
430                    (start, end) = control.GetSelection()
431                    if start == end:
432                        control.SetSelection(-1, -1)
433                       
434        def _silent_kill_focus(self, event):
435            """
436            Save the state of the page
437            """
438           
439            event.Skip()
440            #pass
441   
442    def set_page_info(self, page_info):
443        """
444        set some page important information at once
445        """
446        ##window_name
447        self.window_name = page_info.window_name
448        ##window_caption
449        self.window_caption = page_info.window_caption
450        ## manager is the fitting plugin
451        self._manager = page_info.manager
452        ## owner of the page (fitting plugin)
453        self.event_owner = page_info.event_owner
454        ## current model
455        self.model = page_info.model
456        ## data
457        self.data = page_info.data
458        ## dictionary containing list of models
459        self.model_list_box = page_info.model_list_box
460        ## Data member to store the dispersion object created
461        self.populate_box(dict=self.model_list_box)
462       
463    def onContextMenu(self, event):
464        """
465        Retrieve the state selected state
466        """
467        # Skipping the save state functionality for release 0.9.0
468        #return
469   
470        pos = event.GetPosition()
471        pos = self.ScreenToClient(pos)
472       
473        self.PopupMenu(self.popUpMenu, pos)
474     
475    def onUndo(self, event):
476        """
477        Cancel the previous action
478        """
479        event = PreviousStateEvent(page=self)
480        wx.PostEvent(self.parent, event)
481       
482    def onRedo(self, event):
483        """
484        Restore the previous action cancelled
485        """
486        event = NextStateEvent(page=self)
487        wx.PostEvent(self.parent, event)
488   
489    def define_page_structure(self):
490        """
491        Create empty sizer for a panel
492        """
493        self.vbox = wx.BoxSizer(wx.VERTICAL)
494        self.sizer0 = wx.BoxSizer(wx.VERTICAL)
495        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
496        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
497        self.sizer3 = wx.BoxSizer(wx.VERTICAL)
498        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
499        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
500        self.sizer6 = wx.BoxSizer(wx.VERTICAL)
501       
502        self.sizer0.SetMinSize((PANEL_WIDTH, -1))
503        self.sizer1.SetMinSize((PANEL_WIDTH, -1))
504        self.sizer2.SetMinSize((PANEL_WIDTH, -1))
505        self.sizer3.SetMinSize((PANEL_WIDTH, -1))
506        self.sizer4.SetMinSize((PANEL_WIDTH, -1))
507        self.sizer5.SetMinSize((PANEL_WIDTH, -1))
508        self.sizer6.SetMinSize((PANEL_WIDTH, -1))
509       
510        self.vbox.Add(self.sizer0)
511        self.vbox.Add(self.sizer1)
512        self.vbox.Add(self.sizer2)
513        self.vbox.Add(self.sizer3)
514        self.vbox.Add(self.sizer4)
515        self.vbox.Add(self.sizer5)
516        self.vbox.Add(self.sizer6)
517       
518    def set_layout(self):
519        """
520        layout
521        """
522        self.vbox.Layout()
523        self.vbox.Fit(self)
524        self.SetSizer(self.vbox)
525        self.Centre()
526 
527    def set_owner(self, owner):
528        """
529        set owner of fitpage
530       
531        :param owner: the class responsible of plotting
532       
533        """
534        self.event_owner = owner
535        self.state.event_owner = owner
536       
537    def get_state(self):
538        """
539        """
540        return self.state
541   
542    def get_data(self):
543        """
544        return the current data
545        """
546        return self.data
547   
548    def get_data_list(self):
549        """
550        return the current data
551        """
552        return self.data_list
553   
554    def set_manager(self, manager):
555        """
556        set panel manager
557       
558        :param manager: instance of plugin fitting
559       
560        """
561        self._manager = manager
562        self.state.manager = manager
563       
564    def populate_box(self, dict):
565        """
566        Store list of model
567       
568        :param dict: dictionary containing list of models
569       
570        """
571        self.model_list_box = dict
572        self.state.model_list_box = self.model_list_box
573        self.initialize_combox()
574       
575    def initialize_combox(self):
576        """
577        put default value in the combobox
578        """ 
579        ## fill combox box
580        if self.model_list_box is None:
581            return
582        if len(self.model_list_box) > 0:
583            self._populate_box(self.formfactorbox,
584                               self.model_list_box["Shapes"])
585       
586        if len(self.model_list_box) > 0:
587            self._populate_box(self.structurebox,
588                                self.model_list_box["Structure Factors"])
589            self.structurebox.Insert("None", 0, None)
590            self.structurebox.SetSelection(0)
591            self.structurebox.Hide()
592            self.text2.Hide()
593            self.structurebox.Disable()
594            self.text2.Disable()
595             
596            if self.model.__class__ in self.model_list_box["P(Q)*S(Q)"]:
597                self.structurebox.Show()
598                self.text2.Show()
599                self.structurebox.Enable()
600                self.text2.Enable()
601               
602    def set_dispers_sizer(self):
603        """
604        fill sizer containing dispersity info
605        """
606        self.sizer4.Clear(True)
607        name = "Polydispersity and Orientational Distribution"
608        box_description = wx.StaticBox(self, -1, name)
609        box_description.SetForegroundColour(wx.BLUE)
610        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
611        #----------------------------------------------------
612        self.disable_disp = wx.RadioButton(self, -1, 'Off', (10, 10),
613                                            style=wx.RB_GROUP)
614        self.enable_disp = wx.RadioButton(self, -1, 'On', (10, 30))
615        # best size for MAC and PC
616        if ON_MAC:
617            size_q = (30, 20)
618        else:
619            size_q = (20, 15)
620        self.disp_help_bt = wx.Button(self, wx.NewId(), '?',
621                                      style=wx.BU_EXACTFIT,
622                                      size=size_q)
623        self.disp_help_bt.Bind(wx.EVT_BUTTON,
624                        self.on_pd_help_clicked, id=self.disp_help_bt.GetId())
625        self.disp_help_bt.SetToolTipString("Helps for Polydispersion.")
626       
627        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param,
628                     id=self.disable_disp.GetId())
629        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param,
630                   id=self.enable_disp.GetId())
631        #MAC needs SetValue
632        self.disable_disp.SetValue(True)
633        sizer_dispersion = wx.BoxSizer(wx.HORIZONTAL)
634        sizer_dispersion.Add((20, 20))
635        name = ""  # Polydispersity and \nOrientational Distribution "
636        sizer_dispersion.Add(wx.StaticText(self, -1, name))
637        sizer_dispersion.Add(self.enable_disp)
638        sizer_dispersion.Add((20, 20))
639        sizer_dispersion.Add(self.disable_disp)
640        sizer_dispersion.Add((25, 20))
641        sizer_dispersion.Add(self.disp_help_bt)
642       
643        ## fill a sizer for dispersion
644        boxsizer1.Add(sizer_dispersion, 0,
645                wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE,
646                border=5)
647        self.sizer4_4 = wx.GridBagSizer(6, 5)
648
649        boxsizer1.Add(self.sizer4_4)
650        #-----------------------------------------------------
651        self.sizer4.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
652        self.sizer4_4.Layout()
653        self.sizer4.Layout()
654        self.Layout()
655     
656        self.Refresh()
657        ## saving the state of enable dispersity button
658        self.state.enable_disp = self.enable_disp.GetValue()
659        self.state.disable_disp = self.disable_disp.GetValue()
660        self.SetupScrolling()
661   
662    def onResetModel(self, event):
663        """
664        Reset model state
665        """
666        menu = event.GetEventObject()
667        ## post help message for the selected model
668        msg = menu.GetHelpString(event.GetId())
669        msg += " reloaded"
670        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
671        self.Show(False)
672        name = menu.GetLabel(event.GetId())
673        self._on_select_model_helper()
674        if self.model != None:
675            self.m_name = self.model.name
676        if name in self.saved_states.keys():
677            previous_state = self.saved_states[name]
678            ## reset state of checkbox,textcrtl  and  regular parameters value
679           
680            self.reset_page(previous_state)
681        self.state.m_name = self.m_name
682        self.Show(True)
683               
684    def on_preview(self, event):
685        """
686        Report the current fit results
687        """
688        # Get plot image from plotpanel
689        images, canvases = self.get_images()
690        # get the report dialog
691        self.state.report(images, canvases)
692       
693    def on_save(self, event):
694        """
695        Save the current state into file
696        """
697        self.save_current_state()
698        new_state = self.state.clone()
699        # Ask the user the location of the file to write to.
700        path = None
701        if self.parent != None:
702            self._default_save_location = \
703                        self.parent.parent._default_save_location
704        dlg = wx.FileDialog(self, "Choose a file", self._default_save_location,
705                                        self.window_caption, "*.fitv", wx.SAVE)
706
707        if dlg.ShowModal() == wx.ID_OK:
708            path = dlg.GetPath()
709            self._default_save_location = os.path.dirname(path)
710            self.parent.parent._default_save_location =\
711                                 self._default_save_location
712        else:
713            return None
714        # MAC always needs the extension for saving
715        extens = ".fitv"
716        # Make sure the ext included in the file name
717        fName = os.path.splitext(path)[0] + extens
718        #the manager write the state into file
719        self._manager.save_fit_state(filepath=fName, fitstate=new_state)
720        return new_state
721   
722    def on_copy(self, event):
723        """
724        Copy Parameter values to the clipboad
725        """
726        if event != None:
727            event.Skip()
728        # It seems MAC needs wxCallAfter
729        wx.CallAfter(self.get_copy)
730       
731    def on_paste(self, event):
732        """
733        Paste Parameter values to the panel if possible
734        """
735        if event != None:
736            event.Skip()
737        # It seems MAC needs wxCallAfter for the setvalues
738        # for multiple textctrl items, otherwise it tends to crash once a while
739        wx.CallAfter(self.get_paste)
740        # messages depending on the flag
741        #self._copy_info(True)
742       
743    def _copy_info(self, flag):
744        """
745        Send event dpemding on flag
746       
747        : Param flag: flag that distinguish event
748        """
749        # messages depending on the flag
750        if flag == None:
751            msg = " Parameter values are copied to the clipboard..."
752            infor = 'warning'
753        elif flag:
754            msg = " Parameter values are pasted from the clipboad..."
755            infor = "warning"
756        else:
757            msg = "Error was occured "
758            msg += ": No valid parameter values to paste from the clipboard..."
759            infor = "error"
760        # inform msg to wx
761        wx.PostEvent(self.parent.parent,
762                    StatusEvent(status=msg, info=infor))
763       
764    def _get_time_stamp(self):
765        """
766        return time and date stings
767        """
768        # date and time
769        year, month, day, hour, minute, second, _, _, _ = time.localtime()
770        current_time = str(hour) + ":" + str(minute) + ":" + str(second)
771        current_date = str(month) + "/" + str(day) + "/" + str(year)
772        return current_time, current_date
773     
774    def on_bookmark(self, event):
775        """
776        save history of the data and model
777        """
778        if self.model == None:
779            msg = "Can not bookmark; Please select Data and Model first..."
780            wx.MessageBox(msg, 'Info')
781            return
782        self.save_current_state()
783        new_state = self.state.clone()
784        ##Add model state on context menu
785        self.number_saved_state += 1
786        current_time, current_date = self._get_time_stamp()
787        #name= self.model.name+"[%g]"%self.number_saved_state
788        name = "Fitting: %g]" % self.number_saved_state
789        name += self.model.__class__.__name__
790        name += "bookmarked at %s on %s" % (current_time, current_date)
791        self.saved_states[name] = new_state
792       
793        ## Add item in the context menu
794        msg = "Model saved at %s on %s" % (current_time, current_date)
795        ## post help message for the selected model
796        msg += " Saved! right click on this page to retrieve this model"
797        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
798       
799        id = wx.NewId()
800        self.popUpMenu.Append(id, name, str(msg))
801        wx.EVT_MENU(self, id, self.onResetModel)
802        wx.PostEvent(self.parent.parent,
803                     AppendBookmarkEvent(title=name,
804                                         hint=str(msg),
805                                         handler=self._back_to_bookmark))
806   
807    def _back_to_bookmark(self, event):
808        """
809        Back to bookmark
810        """
811        self._manager.on_perspective(event)
812        self.onResetModel(event)
813        self._draw_model()
814               
815    def onSetFocus(self, evt):
816        """
817        highlight the current textcrtl and hide the error text control shown
818        after fitting
819        """
820        return
821   
822    def read_file(self, path):
823        """
824        Read two columns file
825       
826        :param path: the path to the file to read
827       
828        """
829        try:
830            if path == None:
831                wx.PostEvent(self.parent.parent,
832                            StatusEvent(status= \
833                            " Selected Distribution was not loaded: %s" % path))
834                return None, None
835            input_f = open(path, 'r')
836            buff = input_f.read()
837            lines = buff.split('\n')
838            input_f.close()
839            angles = []
840            weights = []
841            for line in lines:
842                toks = line.split()
843                try:
844                    angle = float(toks[0])
845                    weight = float(toks[1])
846                    angles.append(angle)
847                    weights.append(weight)
848                except:
849                    # Skip non-data lines
850                    pass
851            return numpy.array(angles), numpy.array(weights)
852        except:
853            raise
854
855    def createMemento(self):
856        """
857        return the current state of the page
858        """
859        return self.state.clone()
860   
861    def save_current_state(self):
862        """
863        Store current state
864        """
865        self.state.engine_type = copy.deepcopy(self.engine_type)
866        ## save model option
867        if self.model != None:
868            self.disp_list = self.model.getDispParamList()
869            self.state.disp_list = copy.deepcopy(self.disp_list)
870            self.state.model = self.model.clone()
871           
872            #model combobox: complex code because of mac's silent error
873            if self.structurebox != None:
874                if self.structurebox.IsShown():
875                    self.state.structurecombobox = 'None'
876                    s_select = self.structurebox.GetSelection()
877                    if s_select > 0:
878                        self.state.structurecombobox = self.structurebox.\
879                        GetString(s_select)
880            if self.formfactorbox != None:
881                f_select = self.formfactorbox.GetSelection()
882                if f_select > 0:
883                        self.state.formfactorcombobox = self.formfactorbox.\
884                        GetString(f_select)
885                       
886        #save radiobutton state for model selection
887        self.state.shape_rbutton = self.shape_rbutton.GetValue()
888        self.state.shape_indep_rbutton = self.shape_indep_rbutton.GetValue()
889        self.state.struct_rbutton = self.struct_rbutton.GetValue()
890        self.state.plugin_rbutton = self.plugin_rbutton.GetValue()
891       
892        self.state.enable2D = copy.deepcopy(self.enable2D)
893        self.state.values = copy.deepcopy(self.values)
894        self.state.weights = copy.deepcopy(self.weights)
895        ## save data
896        self.state.data = copy.deepcopy(self.data)
897        self.state.qmax_x = self.qmax_x
898        self.state.qmin_x = self.qmin_x
899        self.state.dI_noweight = copy.deepcopy(self.dI_noweight.GetValue())
900        self.state.dI_didata = copy.deepcopy(self.dI_didata.GetValue())
901        self.state.dI_sqrdata = copy.deepcopy(self.dI_sqrdata.GetValue())
902        self.state.dI_idata = copy.deepcopy(self.dI_idata.GetValue())
903        self.state.dq_l = self.dq_l
904        self.state.dq_r = self.dq_r
905        if hasattr(self, "enable_disp"):
906            self.state.enable_disp = self.enable_disp.GetValue()
907            self.state.disable_disp = self.disable_disp.GetValue()
908           
909        self.state.smearer = copy.deepcopy(self.current_smearer)
910        if hasattr(self, "enable_smearer"):
911            self.state.enable_smearer = \
912                                copy.deepcopy(self.enable_smearer.GetValue())
913            self.state.disable_smearer = \
914                                copy.deepcopy(self.disable_smearer.GetValue())
915
916        self.state.pinhole_smearer = \
917                                copy.deepcopy(self.pinhole_smearer.GetValue())
918        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue())
919                 
920        if len(self._disp_obj_dict) > 0:
921            for k, v in self._disp_obj_dict.iteritems():
922                self.state._disp_obj_dict[k] = v
923
924            self.state.values = copy.deepcopy(self.values)
925            self.state.weights = copy.deepcopy(self.weights)
926        ## save plotting range
927        self._save_plotting_range()
928       
929        self.state.orientation_params = []
930        self.state.orientation_params_disp = []
931        self.state.parameters = []
932        self.state.fittable_param = []
933        self.state.fixed_param = []
934        self.state.str_parameters = []
935
936        ## save checkbutton state and txtcrtl values
937        self._copy_parameters_state(self.str_parameters,
938                                    self.state.str_parameters)
939        self._copy_parameters_state(self.orientation_params,
940                                     self.state.orientation_params)
941        self._copy_parameters_state(self.orientation_params_disp,
942                                     self.state.orientation_params_disp)
943       
944        self._copy_parameters_state(self.parameters, self.state.parameters)
945        self._copy_parameters_state(self.fittable_param,
946                                     self.state.fittable_param)
947        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
948        #save chisqr
949        self.state.tcChi = self.tcChi.GetValue()
950       
951    def save_current_state_fit(self):
952        """
953        Store current state for fit_page
954        """
955        ## save model option
956        if self.model != None:
957            self.disp_list = self.model.getDispParamList()
958            self.state.disp_list = copy.deepcopy(self.disp_list)
959            self.state.model = self.model.clone()
960        if hasattr(self, "engine_type"):
961            self.state.engine_type = copy.deepcopy(self.engine_type)
962           
963        self.state.enable2D = copy.deepcopy(self.enable2D)
964        self.state.values = copy.deepcopy(self.values)
965        self.state.weights = copy.deepcopy(self.weights)
966        ## save data
967        self.state.data = copy.deepcopy(self.data)
968       
969        if hasattr(self, "enable_disp"):
970            self.state.enable_disp = self.enable_disp.GetValue()
971            self.state.disable_disp = self.disable_disp.GetValue()
972           
973        self.state.smearer = copy.deepcopy(self.current_smearer)
974        if hasattr(self, "enable_smearer"):
975            self.state.enable_smearer = \
976                                copy.deepcopy(self.enable_smearer.GetValue())
977            self.state.disable_smearer = \
978                                copy.deepcopy(self.disable_smearer.GetValue())
979           
980        self.state.pinhole_smearer = \
981                                copy.deepcopy(self.pinhole_smearer.GetValue())
982        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue())
983        self.state.dI_noweight = copy.deepcopy(self.dI_noweight.GetValue())
984        self.state.dI_didata = copy.deepcopy(self.dI_didata.GetValue())
985        self.state.dI_sqrdata = copy.deepcopy(self.dI_sqrdata.GetValue())
986        self.state.dI_idata = copy.deepcopy(self.dI_idata.GetValue())
987        if hasattr(self, "disp_box") and self.disp_box != None:
988            self.state.disp_box = self.disp_box.GetCurrentSelection()
989
990            if len(self.disp_cb_dict) > 0:
991                for k, v in self.disp_cb_dict.iteritems():
992         
993                    if v == None:
994                        self.state.disp_cb_dict[k] = v
995                    else:
996                        try:
997                            self.state.disp_cb_dict[k] = v.GetValue()
998                        except:
999                            self.state.disp_cb_dict[k] = None
1000           
1001            if len(self._disp_obj_dict) > 0:
1002                for k, v in self._disp_obj_dict.iteritems():
1003                    self.state._disp_obj_dict[k] = v
1004                       
1005            self.state.values = copy.deepcopy(self.values)
1006            self.state.weights = copy.deepcopy(self.weights)
1007           
1008        ## save plotting range
1009        self._save_plotting_range()
1010       
1011        ## save checkbutton state and txtcrtl values
1012        self._copy_parameters_state(self.orientation_params,
1013                                     self.state.orientation_params)
1014        self._copy_parameters_state(self.orientation_params_disp,
1015                                     self.state.orientation_params_disp)
1016        self._copy_parameters_state(self.parameters, self.state.parameters)
1017        self._copy_parameters_state(self.fittable_param,
1018                                             self.state.fittable_param)
1019        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
1020   
1021    def check_invalid_panel(self):
1022        """
1023        check if the user can already perform some action with this panel
1024        """
1025        if self.data is None:
1026            self.disable_smearer.SetValue(True)
1027            self.disable_disp.SetValue(True)
1028            msg = "Please load Data and select Model to start..."
1029            wx.MessageBox(msg, 'Info')
1030            return  True
1031       
1032    def set_model_state(self, state):
1033        """
1034        reset page given a model state
1035        """
1036        self.disp_cb_dict = state.disp_cb_dict
1037        self.disp_list = state.disp_list
1038     
1039        ## set the state of the radio box
1040        self.shape_rbutton.SetValue(state.shape_rbutton)
1041        self.shape_indep_rbutton.SetValue(state.shape_indep_rbutton)
1042        self.struct_rbutton.SetValue(state.struct_rbutton)
1043        self.plugin_rbutton.SetValue(state.plugin_rbutton)
1044       
1045        ## fill model combobox
1046        self._show_combox_helper()
1047        #select the current model
1048        try:
1049            # to support older version
1050            formfactor_pos = int(state.formfactorcombobox)
1051        except:
1052            formfactor_pos = 0
1053            for ind_form in range(self.formfactorbox.GetCount()):
1054                if self.formfactorbox.GetString(ind_form) == \
1055                                        state.formfactorcombobox:
1056                    formfactor_pos = int(ind_form)
1057                    break
1058           
1059        self.formfactorbox.Select(formfactor_pos)
1060       
1061        try:
1062            # to support older version
1063            structfactor_pos = int(state.structurecombobox)
1064        except:
1065            structfactor_pos = 0
1066            for ind_struct in range(self.structurebox.GetCount()):
1067                if self.structurebox.GetString(ind_struct) == \
1068                                        state.structurecombobox:
1069                    structfactor_pos = int(ind_struct)
1070                    break
1071               
1072        self.structurebox.SetSelection(structfactor_pos)
1073       
1074        if state.multi_factor != None:
1075            self.multifactorbox.SetSelection(state.multi_factor)
1076           
1077        ## reset state of checkbox,textcrtl  and  regular parameters value
1078        self._reset_parameters_state(self.orientation_params_disp,
1079                                     state.orientation_params_disp)
1080        self._reset_parameters_state(self.orientation_params,
1081                                     state.orientation_params)
1082        self._reset_parameters_state(self.str_parameters,
1083                                     state.str_parameters)
1084        self._reset_parameters_state(self.parameters, state.parameters)
1085        ## display dispersion info layer
1086        self.enable_disp.SetValue(state.enable_disp)
1087        self.disable_disp.SetValue(state.disable_disp)
1088       
1089        if hasattr(self, "disp_box") and self.disp_box != None:
1090            self.disp_box.SetSelection(state.disp_box)
1091            n = self.disp_box.GetCurrentSelection()
1092            dispersity = self.disp_box.GetClientData(n)
1093            name = dispersity.__name__
1094
1095            self._set_dipers_Param(event=None)
1096       
1097            if name == "ArrayDispersion":
1098               
1099                for item in self.disp_cb_dict.keys():
1100                   
1101                    if hasattr(self.disp_cb_dict[item], "SetValue"):
1102                        self.disp_cb_dict[item].SetValue(\
1103                                                    state.disp_cb_dict[item])
1104                        # Create the dispersion objects
1105                        from sans.models.dispersion_models import ArrayDispersion
1106                        disp_model = ArrayDispersion()
1107                        if hasattr(state, "values") and \
1108                                 self.disp_cb_dict[item].GetValue() == True:
1109                            if len(state.values) > 0:
1110                                self.values = state.values
1111                                self.weights = state.weights
1112                                disp_model.set_weights(self.values,
1113                                                       state.weights)
1114                            else:
1115                                self._reset_dispersity()
1116                       
1117                        self._disp_obj_dict[item] = disp_model
1118                        # Set the new model as the dispersion object
1119                        #for the selected parameter
1120                        self.model.set_dispersion(item, disp_model)
1121                   
1122                        self.model._persistency_dict[item] = \
1123                                                [state.values, state.weights]
1124                   
1125            else:
1126                keys = self.model.getParamList()
1127                for item in keys:
1128                    if item in self.disp_list and \
1129                        not item in self.model.details:
1130                        self.model.details[item] = ["", None, None]
1131                self.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
1132                self.state.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
1133        ## smearing info  restore
1134        if hasattr(self, "enable_smearer"):
1135            ## set smearing value whether or not the data
1136            #contain the smearing info
1137            self.enable_smearer.SetValue(state.enable_smearer)
1138            self.disable_smearer.SetValue(state.disable_smearer)
1139            self.onSmear(event=None)
1140        self.pinhole_smearer.SetValue(state.pinhole_smearer)
1141        self.slit_smearer.SetValue(state.slit_smearer)
1142       
1143        self.dI_noweight.SetValue(state.dI_noweight)
1144        self.dI_didata.SetValue(state.dI_didata)
1145        self.dI_sqrdata.SetValue(state.dI_sqrdata)
1146        self.dI_idata.SetValue(state.dI_idata)
1147       
1148        ## we have two more options for smearing
1149        if self.pinhole_smearer.GetValue():
1150            self.onPinholeSmear(event=None)
1151        elif self.slit_smearer.GetValue():
1152            self.onSlitSmear(event=None)
1153       
1154        ## reset state of checkbox,textcrtl  and dispersity parameters value
1155        self._reset_parameters_state(self.fittable_param, state.fittable_param)
1156        self._reset_parameters_state(self.fixed_param, state.fixed_param)
1157       
1158        ## draw the model with previous parameters value
1159        self._onparamEnter_helper()
1160        self.select_param(event=None)
1161        #Save state_fit
1162        self.save_current_state_fit()
1163        self._lay_out()
1164        self.Refresh()
1165       
1166    def reset_page_helper(self, state):
1167        """
1168        Use page_state and change the state of existing page
1169       
1170        :precondition: the page is already drawn or created
1171       
1172        :postcondition: the state of the underlying data change as well as the
1173            state of the graphic interface
1174        """
1175        if state == None:
1176            return
1177        # set data, etc. from the state
1178        # reset page between theory and fitting from bookmarking
1179        #if state.data == None:
1180        #    data = None
1181        #else:
1182        data = state.data
1183
1184        if data == None:
1185            data_min = state.qmin
1186            data_max = state.qmax
1187            self.qmin_x = data_min
1188            self.qmax_x = data_max
1189            self.qmin.SetValue(str(data_min))
1190            self.qmax.SetValue(str(data_max))
1191
1192            self.state.data = data
1193            self.state.qmin = self.qmin_x
1194            self.state.qmax = self.qmax_x
1195        else:
1196            self.set_data(data)
1197           
1198        self.enable2D = state.enable2D
1199        self.engine_type = state.engine_type
1200
1201        self.disp_cb_dict = state.disp_cb_dict
1202        self.disp_list = state.disp_list
1203     
1204        ## set the state of the radio box
1205        self.shape_rbutton.SetValue(state.shape_rbutton)
1206        self.shape_indep_rbutton.SetValue(state.shape_indep_rbutton)
1207        self.struct_rbutton.SetValue(state.struct_rbutton)
1208        self.plugin_rbutton.SetValue(state.plugin_rbutton)
1209       
1210        ## fill model combobox
1211        self._show_combox_helper()
1212        #select the current model
1213        try:
1214            # to support older version
1215            formfactor_pos = int(state.formfactorcombobox)
1216        except:
1217            formfactor_pos = 0
1218            for ind_form in range(self.formfactorbox.GetCount()):
1219                if self.formfactorbox.GetString(ind_form) == \
1220                                                    (state.formfactorcombobox):
1221                    formfactor_pos = int(ind_form)
1222                    break
1223           
1224        self.formfactorbox.Select(formfactor_pos)
1225       
1226        try:
1227            # to support older version
1228            structfactor_pos = int(state.structurecombobox)
1229        except:
1230            structfactor_pos = 0
1231            for ind_struct in range(self.structurebox.GetCount()):
1232                if self.structurebox.GetString(ind_struct) == \
1233                                                    (state.structurecombobox):
1234                    structfactor_pos = int(ind_struct)
1235                    break
1236           
1237        self.structurebox.SetSelection(structfactor_pos)
1238
1239        if state.multi_factor != None:
1240            self.multifactorbox.SetSelection(state.multi_factor)
1241
1242        #reset the fitting engine type
1243        self.engine_type = state.engine_type
1244        #draw the pnael according to the new model parameter
1245        self._on_select_model(event=None)
1246           
1247        # take care of 2D button
1248        if data == None and self.model_view.IsEnabled():
1249            if self.enable2D:
1250                self.model_view.SetLabel("2D Mode")
1251            else:
1252                self.model_view.SetLabel("1D Mode")
1253        # else:
1254               
1255        if self._manager != None and self.engine_type != None:
1256            self._manager._on_change_engine(engine=self.engine_type)
1257        ## set the select all check box to the a given state
1258        self.cb1.SetValue(state.cb1)
1259     
1260        ## reset state of checkbox,textcrtl  and  regular parameters value
1261        self._reset_parameters_state(self.orientation_params_disp,
1262                                     state.orientation_params_disp)
1263        self._reset_parameters_state(self.orientation_params,
1264                                     state.orientation_params)
1265        self._reset_parameters_state(self.str_parameters,
1266                                     state.str_parameters)
1267        self._reset_parameters_state(self.parameters, state.parameters)
1268        ## display dispersion info layer
1269        self.enable_disp.SetValue(state.enable_disp)
1270        self.disable_disp.SetValue(state.disable_disp)
1271        # If the polydispersion is ON
1272        if state.enable_disp:
1273            # reset dispersion according the state
1274            self._set_dipers_Param(event=None)
1275            self._reset_page_disp_helper(state)
1276        ##plotting range restore
1277        self._reset_plotting_range(state)
1278        ## smearing info  restore
1279        if hasattr(self, "enable_smearer"):
1280            ## set smearing value whether or not the data
1281            #contain the smearing info
1282            self.enable_smearer.SetValue(state.enable_smearer)
1283            self.disable_smearer.SetValue(state.disable_smearer)
1284            self.onSmear(event=None)
1285        self.pinhole_smearer.SetValue(state.pinhole_smearer)
1286        self.slit_smearer.SetValue(state.slit_smearer)
1287        try:
1288            self.dI_noweight.SetValue(state.dI_noweight)
1289            self.dI_didata.SetValue(state.dI_didata)
1290            self.dI_sqrdata.SetValue(state.dI_sqrdata)
1291            self.dI_idata.SetValue(state.dI_idata)
1292        except:
1293            # to support older state file formats
1294            self.dI_noweight.SetValue(False)
1295            self.dI_didata.SetValue(True)
1296            self.dI_sqrdata.SetValue(False)
1297            self.dI_idata.SetValue(False)
1298 
1299        ## we have two more options for smearing
1300        if self.pinhole_smearer.GetValue():
1301            self.onPinholeSmear(event=None)
1302        elif self.slit_smearer.GetValue():
1303            self.onSlitSmear(event=None)
1304       
1305        ## reset state of checkbox,textcrtl  and dispersity parameters value
1306        self._reset_parameters_state(self.fittable_param, state.fittable_param)
1307        self._reset_parameters_state(self.fixed_param, state.fixed_param)
1308       
1309        ## draw the model with previous parameters value
1310        self._onparamEnter_helper()
1311        #reset the value of chisqr when not consistent with the value computed
1312        self.tcChi.SetValue(str(self.state.tcChi))
1313        ## reset context menu items
1314        self._reset_context_menu()
1315       
1316        ## set the value of the current state to the state given as parameter
1317        self.state = state.clone()
1318        self.state.m_name = self.m_name
1319   
1320    def _reset_page_disp_helper(self, state):
1321        """
1322        Help to rest page for dispersions
1323        """
1324        keys = self.model.getParamList()
1325        for item in keys:
1326            if item in self.disp_list and \
1327                not item in self.model.details:
1328                self.model.details[item] = ["", None, None]
1329        #for k,v in self.state.disp_cb_dict.iteritems():
1330        self.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
1331        self.state.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
1332        self.values = copy.deepcopy(state.values)
1333        self.weights = copy.deepcopy(state.weights)
1334       
1335        for key, disp in state._disp_obj_dict.iteritems():
1336            # From saved file, disp_model can not be sent in model obj.
1337            # it will be sent as a string here, then converted to model object.
1338            if disp.__class__.__name__ == 'str':
1339                disp_model = None
1340                com_str = "from sans.models.dispersion_models "
1341                com_str += "import %s as disp_func \ndisp_model = disp_func()"
1342                exec com_str % disp
1343            else:
1344                disp_model = disp
1345            self._disp_obj_dict[key] = disp_model
1346            param_name = key.split('.')[0]
1347            # Try to set dispersion only when available
1348            # for eg., pass the orient. angles for 1D Cal
1349            try:
1350                self.model.set_dispersion(param_name, disp_model)
1351                self.model._persistency_dict[key] = \
1352                                 [state.values, state.weights]
1353            except:
1354                pass
1355            selection = self._find_polyfunc_selection(disp_model)
1356            for list in self.fittable_param:
1357                if list[1] == key and list[7] != None:
1358                    list[7].SetSelection(selection)
1359                    # For the array disp_model, set the values and weights
1360                    if selection == 1:
1361                        disp_model.set_weights(self.values[key],
1362                                               self.weights[key])
1363                        try:
1364                            # Diables all fittable params for array
1365                            list[0].SetValue(False)
1366                            list[0].Disable()
1367                            list[2].Disable()
1368                            list[5].Disable()
1369                            list[6].Disable()
1370                        except:
1371                            pass
1372            # For array, disable all fixed params
1373            if selection == 1:
1374                for item in self.fixed_param:
1375                    if item[1].split(".")[0] == key.split(".")[0]:
1376                        # try it and pass it for the orientation for 1D
1377                        try:
1378                            item[2].Disable()
1379                        except:
1380                            pass
1381   
1382        # Make sure the check box updated when all checked
1383        if self.cb1.GetValue():
1384            self.select_all_param(None)
1385     
1386    def _selectDlg(self):
1387        """
1388        open a dialog file to selected the customized dispersity
1389        """
1390        if self.parent != None:
1391            self._default_save_location = \
1392                        self.parent.parent.get_save_location()
1393        dlg = wx.FileDialog(self, "Choose a weight file",
1394                                self._default_save_location, "",
1395                                "*.*", wx.OPEN)
1396        path = None
1397        if dlg.ShowModal() == wx.ID_OK:
1398            path = dlg.GetPath()
1399        dlg.Destroy()
1400        return path
1401
1402    def _reset_context_menu(self):
1403        """
1404        reset the context menu
1405        """
1406        for name, _ in self.state.saved_states.iteritems():
1407            self.number_saved_state += 1
1408            ## Add item in the context menu
1409            id = wx.NewId()
1410            msg = 'Save model and state %g' % self.number_saved_state
1411            self.popUpMenu.Append(id, name, msg)
1412            wx.EVT_MENU(self, id, self.onResetModel)
1413   
1414    def _reset_plotting_range(self, state):
1415        """
1416        Reset the plotting range to a given state
1417        """
1418        self.qmin.SetValue(str(state.qmin))
1419        self.qmax.SetValue(str(state.qmax))
1420
1421    def _save_typeOfmodel(self):
1422        """
1423        save radiobutton containing the type model that can be selected
1424        """
1425        self.state.shape_rbutton = self.shape_rbutton.GetValue()
1426        self.state.shape_indep_rbutton = self.shape_indep_rbutton.GetValue()
1427        self.state.struct_rbutton = self.struct_rbutton.GetValue()
1428        self.state.plugin_rbutton = self.plugin_rbutton.GetValue()
1429        self.state.structurecombobox = self.structurebox.GetLabel()
1430        self.state.formfactorcombobox = self.formfactorbox.GetLabel()
1431       
1432        ## post state to fit panel
1433        event = PageInfoEvent(page=self)
1434        wx.PostEvent(self.parent, event)
1435       
1436    def _save_plotting_range(self):
1437        """
1438        save the state of plotting range
1439        """
1440        self.state.qmin = self.qmin_x
1441        self.state.qmax = self.qmax_x
1442        self.state.npts = self.npts_x
1443           
1444    def _onparamEnter_helper(self):
1445        """
1446        check if values entered by the user are changed and valid to replot
1447        model
1448        """
1449        # Flag to register when a parameter has changed.
1450        is_modified = False
1451        self.fitrange = True
1452        is_2Ddata = False
1453        #self._undo.Enable(True)
1454        # check if 2d data
1455        if self.data.__class__.__name__ == "Data2D":
1456            is_2Ddata = True
1457        if self.model != None:
1458            try:
1459                is_modified = self._check_value_enter(self.fittable_param,
1460                                                     is_modified)
1461                is_modified = self._check_value_enter(self.fixed_param,
1462                                                      is_modified)
1463                is_modified = self._check_value_enter(self.parameters,
1464                                                      is_modified)
1465            except:
1466                pass
1467
1468            # Here we should check whether the boundaries have been modified.
1469            # If qmin and qmax have been modified, update qmin and qmax and
1470            # set the is_modified flag to True
1471            if self._validate_qrange(self.qmin, self.qmax):
1472                tempmin = float(self.qmin.GetValue())
1473                if tempmin != self.qmin_x:
1474                    self.qmin_x = tempmin
1475                    is_modified = True
1476                tempmax = float(self.qmax.GetValue())
1477                if tempmax != self.qmax_x:
1478                    self.qmax_x = tempmax
1479                    is_modified = True
1480           
1481                if is_2Ddata:
1482                    # set mask
1483                    is_modified = self._validate_Npts()
1484                   
1485            else:
1486                self.fitrange = False
1487               
1488            if not self.data.is_data:
1489                is_modified = True
1490
1491            ## if any value is modify draw model with new value
1492            if not self.fitrange:
1493                #self.btFit.Disable()
1494                if is_2Ddata:
1495                    self.btEditMask.Disable()
1496            else:
1497                if is_2Ddata and self.data.is_data and not self.batch_on:
1498                    self.btEditMask.Enable(True)
1499            if is_modified and self.fitrange:
1500                # Theory case: need to get npts value to draw
1501                self.npts_x = float(self.Npts_total.GetValue())
1502                self.create_default_data()
1503                self.state_change = True
1504                self._draw_model()
1505                self.Refresh()
1506        return is_modified
1507   
1508    def _update_paramv_on_fit(self):
1509        """
1510        make sure that update param values just before the fitting
1511        """
1512        #flag for qmin qmax check values
1513        flag = True
1514        self.fitrange = True
1515        is_modified = False
1516
1517        #wx.PostEvent(self._manager.parent, StatusEvent(status=" \
1518        #updating ... ",type="update"))
1519
1520        ##So make sure that update param values on_Fit.
1521        #self._undo.Enable(True)
1522        if self.model != None:
1523            if self.Npts_total.GetValue() != self.Npts_fit.GetValue():
1524                if not self.data.is_data:
1525                    self._manager.page_finder[self.uid].set_fit_data(data=\
1526                                                                [self.data])
1527            ##Check the values
1528            self._check_value_enter(self.fittable_param, is_modified)
1529            self._check_value_enter(self.fixed_param, is_modified)
1530            self._check_value_enter(self.parameters, is_modified)
1531
1532            # If qmin and qmax have been modified, update qmin and qmax and
1533            # Here we should check whether the boundaries have been modified.
1534            # If qmin and qmax have been modified, update qmin and qmax and
1535            # set the is_modified flag to True
1536            self.fitrange = self._validate_qrange(self.qmin, self.qmax)
1537            if self.fitrange:
1538                tempmin = float(self.qmin.GetValue())
1539                if tempmin != self.qmin_x:
1540                    self.qmin_x = tempmin
1541                tempmax = float(self.qmax.GetValue())
1542                if tempmax != self.qmax_x:
1543                    self.qmax_x = tempmax
1544                if tempmax == tempmin:
1545                    flag = False
1546                temp_smearer = None
1547                if not self.disable_smearer.GetValue():
1548                    temp_smearer = self.current_smearer
1549                    if self.slit_smearer.GetValue():
1550                        flag = self.update_slit_smear()
1551                    elif self.pinhole_smearer.GetValue():
1552                        flag = self.update_pinhole_smear()
1553                    else:
1554                        self._manager.set_smearer(smearer=temp_smearer,
1555                                                  uid=self.uid,
1556                                                  fid=self.data.id,
1557                                                  qmin=float(self.qmin_x),
1558                                                  qmax=float(self.qmax_x),
1559                            enable_smearer=not self.disable_smearer.GetValue(),
1560                                                      draw=False)
1561                elif not self._is_2D():
1562                    self._manager.set_smearer(smearer=temp_smearer,
1563                                              qmin=float(self.qmin_x),
1564                                              uid=self.uid,
1565                                              fid=self.data.id,
1566                                              qmax=float(self.qmax_x),
1567                            enable_smearer=not self.disable_smearer.GetValue(),
1568                                                 draw=False)
1569                    if self.data != None:
1570                        index_data = ((self.qmin_x <= self.data.x) & \
1571                                      (self.data.x <= self.qmax_x))
1572                        val = str(len(self.data.x[index_data == True]))
1573                        self.Npts_fit.SetValue(val)
1574                    else:
1575                        # No data in the panel
1576                        try:
1577                            self.npts_x = float(self.Npts_total.GetValue())
1578                        except:
1579                            flag = False
1580                            return flag
1581                    flag = True
1582                if self._is_2D():
1583                    # only 2D case set mask
1584                    flag = self._validate_Npts()
1585                    if not flag:
1586                        return flag
1587            else:
1588                flag = False
1589        else:
1590            flag = False
1591
1592        #For invalid q range, disable the mask editor and fit button, vs.
1593        if not self.fitrange:
1594            if self._is_2D():
1595                self.btEditMask.Disable()
1596        else:
1597            if self._is_2D() and  self.data.is_data and not self.batch_on:
1598                self.btEditMask.Enable(True)
1599
1600        if not flag:
1601            msg = "Cannot Plot or Fit :Must select a "
1602            msg += " model or Fitting range is not valid!!!  "
1603            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1604       
1605        try:
1606            self.save_current_state()
1607        except:
1608            pass
1609   
1610        return flag
1611               
1612    def _is_modified(self, is_modified):
1613        """
1614        return to self._is_modified
1615        """
1616        return is_modified
1617                       
1618    def _reset_parameters_state(self, listtorestore, statelist):
1619        """
1620        Reset the parameters at the given state
1621        """
1622        if len(statelist) == 0 or len(listtorestore) == 0:
1623            return
1624        if len(statelist) != len(listtorestore):
1625            return
1626
1627        for j in range(len(listtorestore)):
1628            item_page = listtorestore[j]
1629            item_page_info = statelist[j]
1630            ##change the state of the check box for simple parameters
1631            if item_page[0] != None:
1632                item_page[0].SetValue(item_page_info[0])
1633            if item_page[2] != None:
1634                item_page[2].SetValue(item_page_info[2])
1635                if item_page[2].__class__.__name__ == "ComboBox":
1636                    if item_page_info[2] in self.model.fun_list:
1637                        fun_val = self.model.fun_list[item_page_info[2]]
1638                        self.model.setParam(item_page_info[1], fun_val)
1639            if item_page[3] != None:
1640                ## show or hide text +/-
1641                if item_page_info[2]:
1642                    item_page[3].Show(True)
1643                else:
1644                    item_page[3].Hide()
1645            if item_page[4] != None:
1646                ## show of hide the text crtl for fitting error
1647                if item_page_info[4][0]:
1648                    item_page[4].Show(True)
1649                    item_page[4].SetValue(item_page_info[4][1])
1650                else:
1651                    item_page[3].Hide()
1652            if item_page[5] != None:
1653                ## show of hide the text crtl for fitting error
1654                item_page[5].Show(item_page_info[5][0])
1655                item_page[5].SetValue(item_page_info[5][1])
1656               
1657            if item_page[6] != None:
1658                ## show of hide the text crtl for fitting error
1659                item_page[6].Show(item_page_info[6][0])
1660                item_page[6].SetValue(item_page_info[6][1])
1661                   
1662    def _reset_strparam_state(self, listtorestore, statelist):
1663        """
1664        Reset the string parameters at the given state
1665        """
1666        if len(statelist) == 0:
1667            return
1668
1669        listtorestore = copy.deepcopy(statelist)
1670       
1671        for j in range(len(listtorestore)):
1672            item_page = listtorestore[j]
1673            item_page_info = statelist[j]
1674            ##change the state of the check box for simple parameters
1675           
1676            if item_page[0] != None:
1677                item_page[0].SetValue(format_number(item_page_info[0], True))
1678
1679            if item_page[2] != None:
1680                param_name = item_page_info[1]
1681                value = item_page_info[2]
1682                selection = value
1683                if value in self.model.fun_list:
1684                    selection = self.model.fun_list[value]
1685                item_page[2].SetValue(selection)
1686                self.model.setParam(param_name, selection)
1687                                     
1688    def _copy_parameters_state(self, listtocopy, statelist):
1689        """
1690        copy the state of button
1691       
1692        :param listtocopy: the list of check button to copy
1693        :param statelist: list of state object to store the current state
1694       
1695        """
1696        if len(listtocopy) == 0:
1697            return
1698       
1699        for item in listtocopy:
1700 
1701            checkbox_state = None
1702            if item[0] != None:
1703                checkbox_state = item[0].GetValue()
1704            parameter_name = item[1]
1705            parameter_value = None
1706            if item[2] != None:
1707                parameter_value = item[2].GetValue()
1708            static_text = None
1709            if item[3] != None:
1710                static_text = item[3].IsShown()
1711            error_value = None
1712            error_state = None
1713            if item[4] != None:
1714                error_value = item[4].GetValue()
1715                error_state = item[4].IsShown()
1716               
1717            min_value = None
1718            min_state = None
1719            if item[5] != None:
1720                min_value = item[5].GetValue()
1721                min_state = item[5].IsShown()
1722               
1723            max_value = None
1724            max_state = None
1725            if item[6] != None:
1726                max_value = item[6].GetValue()
1727                max_state = item[6].IsShown()
1728            unit = None
1729            if item[7] != None:
1730                unit = item[7].GetLabel()
1731               
1732            statelist.append([checkbox_state, parameter_name, parameter_value,
1733                              static_text, [error_state, error_value],
1734                              [min_state, min_value],
1735                              [max_state, max_value], unit])
1736           
1737    def _set_model_sizer_selection(self, model):
1738        """
1739        Display the sizer according to the type of the current model
1740        """
1741        if model == None:
1742            return
1743        if hasattr(model, "s_model"):
1744           
1745            class_name = model.s_model.__class__
1746            name = model.s_model.name
1747            flag = (name != "NoStructure")
1748            if flag and \
1749                (class_name in self.model_list_box["Structure Factors"]):
1750                self.structurebox.Show()
1751                self.text2.Show()
1752                self.structurebox.Enable()
1753                self.text2.Enable()
1754                items = self.structurebox.GetItems()
1755                self.sizer1.Layout()
1756               
1757                for i in range(len(items)):
1758                    if items[i] == str(name):
1759                        self.structurebox.SetSelection(i)
1760                        break
1761                   
1762        if hasattr(model, "p_model"):
1763            class_name = model.p_model.__class__
1764            name = model.p_model.name
1765            self.formfactorbox.Clear()
1766           
1767            for k, list in self.model_list_box.iteritems():
1768                if k in["P(Q)*S(Q)", "Shapes"] and \
1769                    class_name in self.model_list_box["Shapes"]:
1770                    self.shape_rbutton.SetValue(True)
1771                    ## fill the form factor list with new model
1772                    self._populate_box(self.formfactorbox,
1773                                       self.model_list_box["Shapes"])
1774                    items = self.formfactorbox.GetItems()
1775                    ## set comboxbox to the selected item
1776                    for i in range(len(items)):
1777                        if items[i] == str(name):
1778                            self.formfactorbox.SetSelection(i)
1779                            break
1780                    return
1781                elif k == "Shape-Independent":
1782                    self.shape_indep_rbutton.SetValue(True)
1783                elif k == "Structure Factors":
1784                    self.struct_rbutton.SetValue(True)
1785                elif k == "Multi-Functions":
1786                    continue
1787                else:
1788                    self.plugin_rbutton.SetValue(True)
1789               
1790                if class_name in list:
1791                    ## fill the form factor list with new model
1792                    self._populate_box(self.formfactorbox, list)
1793                    items = self.formfactorbox.GetItems()
1794                    ## set comboxbox to the selected item
1795                    for i in range(len(items)):
1796                        if items[i] == str(name):
1797                            self.formfactorbox.SetSelection(i)
1798                            break
1799                    break
1800        else:
1801            ## Select the model from the menu
1802            class_name = model.__class__
1803            name = model.name
1804            self.formfactorbox.Clear()
1805            items = self.formfactorbox.GetItems()
1806   
1807            for k, list in self.model_list_box.iteritems():
1808                if k in["P(Q)*S(Q)", "Shapes"] and \
1809                    class_name in self.model_list_box["Shapes"]:
1810                    if class_name in self.model_list_box["P(Q)*S(Q)"]:
1811                        self.structurebox.Show()
1812                        self.text2.Show()
1813                        self.structurebox.Enable()
1814                        self.structurebox.SetSelection(0)
1815                        self.text2.Enable()
1816                    else:
1817                        self.structurebox.Hide()
1818                        self.text2.Hide()
1819                        self.structurebox.Disable()
1820                        self.structurebox.SetSelection(0)
1821                        self.text2.Disable()
1822                       
1823                    self.shape_rbutton.SetValue(True)
1824                    ## fill the form factor list with new model
1825                    self._populate_box(self.formfactorbox,
1826                                       self.model_list_box["Shapes"])
1827                    items = self.formfactorbox.GetItems()
1828                    ## set comboxbox to the selected item
1829                    for i in range(len(items)):
1830                        if items[i] == str(name):
1831                            self.formfactorbox.SetSelection(i)
1832                            break
1833                    return
1834                elif k == "Shape-Independent":
1835                    self.shape_indep_rbutton.SetValue(True)
1836                elif k == "Structure Factors":
1837                    self.struct_rbutton.SetValue(True)
1838                elif k == "Multi-Functions":
1839                    continue
1840                else:
1841                    self.plugin_rbutton.SetValue(True)
1842                if class_name in list:
1843                    self.structurebox.SetSelection(0)
1844                    self.structurebox.Disable()
1845                    self.text2.Disable()
1846                    ## fill the form factor list with new model
1847                    self._populate_box(self.formfactorbox, list)
1848                    items = self.formfactorbox.GetItems()
1849                    ## set comboxbox to the selected item
1850                    for i in range(len(items)):
1851                        if items[i] == str(name):
1852                            self.formfactorbox.SetSelection(i)
1853                            break
1854                    break
1855               
1856    def _draw_model(self, update_chisqr=True, source='model'):
1857        """
1858        Method to draw or refresh a plotted model.
1859        The method will use the data member from the model page
1860        to build a call to the fitting perspective manager.
1861       
1862        :param chisqr: update chisqr value [bool]
1863        """
1864        wx.CallAfter(self._draw_model_after, update_chisqr, source)
1865       
1866    def _draw_model_after(self, update_chisqr=True, source='model'):
1867        """
1868        Method to draw or refresh a plotted model.
1869        The method will use the data member from the model page
1870        to build a call to the fitting perspective manager.
1871       
1872        :param chisqr: update chisqr value [bool]
1873        """
1874        #if self.check_invalid_panel():
1875        #    return
1876        if self.model != None:
1877            temp_smear = None
1878            if hasattr(self, "enable_smearer"):
1879                if not self.disable_smearer.GetValue():
1880                    temp_smear = self.current_smearer
1881            # compute weight for the current data
1882            from .utils import get_weight
1883            flag = self.get_weight_flag()
1884            weight = get_weight(data=self.data, is2d=self._is_2D(), flag=flag)
1885            toggle_mode_on = self.model_view.IsEnabled()
1886            is_2d = self._is_2D()
1887            self._manager.draw_model(self.model,
1888                                    data=self.data,
1889                                    smearer=temp_smear,
1890                                    qmin=float(self.qmin_x),
1891                                    qmax=float(self.qmax_x),
1892                                    page_id=self.uid,
1893                                    toggle_mode_on=toggle_mode_on,
1894                                    state=self.state,
1895                                    enable2D=is_2d,
1896                                    update_chisqr=update_chisqr,
1897                                    source='model',
1898                                    weight=weight)
1899       
1900    def _on_show_sld(self, event=None):
1901        """
1902        Plot SLD profile
1903        """
1904        # get profile data
1905        x, y = self.model.getProfile()
1906
1907        from danse.common.plottools import Data1D as pf_data1d
1908        #from sans.perspectives.theory.profile_dialog import SLDPanel
1909        from sans.guiframe.local_perspectives.plotting.profile_dialog \
1910        import SLDPanel
1911        sld_data = pf_data1d(x, y)
1912        sld_data.name = 'SLD'
1913        sld_data.axes = self.sld_axes
1914        self.panel = SLDPanel(self, data=sld_data, axes=self.sld_axes, id=-1)
1915        self.panel.ShowModal()
1916       
1917    def _set_multfactor_combobox(self, multiplicity=10):
1918        """
1919        Set comboBox for muitfactor of CoreMultiShellModel
1920        :param multiplicit: no. of multi-functionality
1921        """
1922        # build content of the combobox
1923        for idx in range(0, multiplicity):
1924            self.multifactorbox.Append(str(idx), int(idx))
1925        self._hide_multfactor_combobox()
1926       
1927    def _show_multfactor_combobox(self):
1928        """
1929        Show the comboBox of muitfactor of CoreMultiShellModel
1930        """
1931        if not self.mutifactor_text.IsShown():
1932            self.mutifactor_text.Show(True)
1933            self.mutifactor_text1.Show(True)
1934        if not self.multifactorbox.IsShown():
1935            self.multifactorbox.Show(True)
1936             
1937    def _hide_multfactor_combobox(self):
1938        """
1939        Hide the comboBox of muitfactor of CoreMultiShellModel
1940        """
1941        if self.mutifactor_text.IsShown():
1942            self.mutifactor_text.Hide()
1943            self.mutifactor_text1.Hide()
1944        if self.multifactorbox.IsShown():
1945            self.multifactorbox.Hide()
1946
1947    def _show_combox_helper(self):
1948        """
1949        Fill panel's combo box according to the type of model selected
1950        """
1951        if self.shape_rbutton.GetValue():
1952            ##fill the combobox with form factor list
1953            self.structurebox.SetSelection(0)
1954            self.structurebox.Disable()
1955            self.formfactorbox.Clear()
1956            self._populate_box(self.formfactorbox,
1957                               self.model_list_box["Shapes"])
1958        if self.shape_indep_rbutton.GetValue():
1959            ##fill the combobox with shape independent  factor list
1960            self.structurebox.SetSelection(0)
1961            self.structurebox.Disable()
1962            self.formfactorbox.Clear()
1963            self._populate_box(self.formfactorbox,
1964                             self.model_list_box["Shape-Independent"])
1965        if self.struct_rbutton.GetValue():
1966            ##fill the combobox with structure factor list
1967            self.structurebox.SetSelection(0)
1968            self.structurebox.Disable()
1969            self.formfactorbox.Clear()
1970            self._populate_box(self.formfactorbox,
1971                               self.model_list_box["Structure Factors"])
1972        if self.plugin_rbutton.GetValue():
1973            ##fill the combobox with form factor list
1974            self.structurebox.Disable()
1975            self.formfactorbox.Clear()
1976            self._populate_box(self.formfactorbox,
1977                               self.model_list_box["Customized Models"])
1978       
1979    def _show_combox(self, event=None):
1980        """
1981        Show combox box associate with type of model selected
1982        """
1983        self.Show(False)
1984        self._show_combox_helper()
1985        self._on_select_model(event=None)
1986        self.Show(True)
1987        self._save_typeOfmodel()
1988        self.sizer4_4.Layout()
1989        self.sizer4.Layout()
1990        self.Layout()
1991        self.Refresh()
1992 
1993    def _populate_box(self, combobox, list):
1994        """
1995        fill combox box with dict item
1996       
1997        :param list: contains item to fill the combox
1998            item must model class
1999        """
2000        mlist = []
2001        for models in list:
2002            model = models()
2003            name = model.__class__.__name__
2004            if models.__name__ != "NoStructure":
2005                if hasattr(model, "name"):
2006                    name = model.name
2007                mlist.append((name, models))
2008               
2009        # Sort the models
2010        mlist_sorted = sorted(mlist)
2011        for item in mlist_sorted:
2012            combobox.Append(item[0], item[1])
2013        return 0
2014   
2015    def _onQrangeEnter(self, event):
2016        """
2017        Check validity of value enter in the Q range field
2018       
2019        """
2020        tcrtl = event.GetEventObject()
2021        #Clear msg if previously shown.
2022        msg = ""
2023        wx.PostEvent(self.parent, StatusEvent(status=msg))
2024        # Flag to register when a parameter has changed.
2025        #is_modified = False
2026        if tcrtl.GetValue().lstrip().rstrip() != "":
2027            try:
2028                float(tcrtl.GetValue())
2029                tcrtl.SetBackgroundColour(wx.WHITE)
2030                # If qmin and qmax have been modified, update qmin and qmax
2031                if self._validate_qrange(self.qmin, self.qmax):
2032                    tempmin = float(self.qmin.GetValue())
2033                    if tempmin != self.qmin_x:
2034                        self.qmin_x = tempmin
2035                    tempmax = float(self.qmax.GetValue())
2036                    if tempmax != self.qmax_x:
2037                        self.qmax_x = tempmax
2038                else:
2039                    tcrtl.SetBackgroundColour("pink")
2040                    msg = "Model Error:wrong value entered: %s" % sys.exc_value
2041                    wx.PostEvent(self.parent, StatusEvent(status=msg))
2042                    return
2043            except:
2044                tcrtl.SetBackgroundColour("pink")
2045                msg = "Model Error:wrong value entered: %s" % sys.exc_value
2046                wx.PostEvent(self.parent, StatusEvent(status=msg))
2047                return
2048            #Check if # of points for theory model are valid(>0).
2049            if self.npts != None:
2050                if check_float(self.npts):
2051                    temp_npts = float(self.npts.GetValue())
2052                    if temp_npts != self.num_points:
2053                        self.num_points = temp_npts
2054                        #is_modified = True
2055                else:
2056                    msg = "Cannot Plot :No npts in that Qrange!!!  "
2057                    wx.PostEvent(self.parent, StatusEvent(status=msg))
2058        else:
2059            tcrtl.SetBackgroundColour("pink")
2060            msg = "Model Error:wrong value entered!!!"
2061            wx.PostEvent(self.parent, StatusEvent(status=msg))
2062        self.save_current_state()
2063        event = PageInfoEvent(page=self)
2064        wx.PostEvent(self.parent, event)
2065        self.state_change = False
2066        #Draw the model for a different range
2067        if not self.data.is_data:
2068            self.create_default_data()
2069        self._draw_model()
2070                   
2071    def _theory_qrange_enter(self, event):
2072        """
2073        Check validity of value enter in the Q range field
2074        """
2075       
2076        tcrtl = event.GetEventObject()
2077        #Clear msg if previously shown.
2078        msg = ""
2079        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2080        # Flag to register when a parameter has changed.
2081        is_modified = False
2082        if tcrtl.GetValue().lstrip().rstrip() != "":
2083            try:
2084                value = float(tcrtl.GetValue())
2085                tcrtl.SetBackgroundColour(wx.WHITE)
2086
2087                # If qmin and qmax have been modified, update qmin and qmax
2088                if self._validate_qrange(self.theory_qmin, self.theory_qmax):
2089                    tempmin = float(self.theory_qmin.GetValue())
2090                    if tempmin != self.theory_qmin_x:
2091                        self.theory_qmin_x = tempmin
2092                    tempmax = float(self.theory_qmax.GetValue())
2093                    if tempmax != self.qmax_x:
2094                        self.theory_qmax_x = tempmax
2095                else:
2096                    tcrtl.SetBackgroundColour("pink")
2097                    msg = "Model Error:wrong value entered: %s" % sys.exc_value
2098                    wx.PostEvent(self._manager.parent, StatusEvent(status=msg))
2099                    return
2100            except:
2101                tcrtl.SetBackgroundColour("pink")
2102                msg = "Model Error:wrong value entered: %s" % sys.exc_value
2103                wx.PostEvent(self._manager.parent, StatusEvent(status=msg))
2104                return
2105            #Check if # of points for theory model are valid(>0).
2106            if self.Npts_total.IsEditable():
2107                if check_float(self.Npts_total):
2108                    temp_npts = float(self.Npts_total.GetValue())
2109                    if temp_npts != self.num_points:
2110                        self.num_points = temp_npts
2111                        is_modified = True
2112                else:
2113                    msg = "Cannot Plot :No npts in that Qrange!!!  "
2114                    wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2115        else:
2116            tcrtl.SetBackgroundColour("pink")
2117            msg = "Model Error:wrong value entered!!!"
2118            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2119        self.save_current_state()
2120        event = PageInfoEvent(page=self)
2121        wx.PostEvent(self.parent, event)
2122        self.state_change = False
2123        #Draw the model for a different range
2124        self.create_default_data()
2125        self._draw_model()
2126                   
2127    def _on_select_model_helper(self):
2128        """
2129        call back for model selection
2130        """
2131        ## reset dictionary containing reference to dispersion
2132        self._disp_obj_dict = {}
2133        self.disp_cb_dict = {}
2134        self.temp_multi_functional = False
2135        f_id = self.formfactorbox.GetCurrentSelection()
2136        #For MAC
2137        form_factor = None
2138        if f_id >= 0:
2139            form_factor = self.formfactorbox.GetClientData(f_id)
2140
2141        if not form_factor in  self.model_list_box["multiplication"]:
2142            self.structurebox.Hide()
2143            self.text2.Hide()
2144            self.structurebox.Disable()
2145            self.structurebox.SetSelection(0)
2146            self.text2.Disable()
2147        else:
2148            self.structurebox.Show()
2149            self.text2.Show()
2150            self.structurebox.Enable()
2151            self.text2.Enable()
2152           
2153        if form_factor != None:
2154            # set multifactor for Mutifunctional models
2155            if form_factor().__class__ in \
2156                                        self.model_list_box["Multi-Functions"]:
2157                m_id = self.multifactorbox.GetCurrentSelection()
2158                multiplicity = form_factor().multiplicity_info[0]
2159                self.multifactorbox.Clear()
2160                self._set_multfactor_combobox(multiplicity)
2161                self._show_multfactor_combobox()
2162                #ToDo:  this info should be called directly from the model
2163                text = form_factor().multiplicity_info[1]  # 'No. of Shells: '
2164
2165                self.mutifactor_text.SetLabel(text)
2166                if m_id > multiplicity - 1:
2167                    # default value
2168                    m_id = 1
2169                   
2170                self.multi_factor = self.multifactorbox.GetClientData(m_id)
2171                if self.multi_factor == None:
2172                    self.multi_factor = 0
2173                form_factor = form_factor(int(self.multi_factor))
2174                self.multifactorbox.SetSelection(m_id)
2175                # Check len of the text1 and max_multiplicity
2176                text = ''
2177                if form_factor.multiplicity_info[0] == \
2178                                        len(form_factor.multiplicity_info[2]):
2179                    text = form_factor.multiplicity_info[2][self.multi_factor]
2180                self.mutifactor_text1.SetLabel(text)
2181                # Check if model has  get sld profile.
2182                if len(form_factor.multiplicity_info[3]) > 0:
2183                    self.sld_axes = form_factor.multiplicity_info[3]
2184                    self.show_sld_button.Show(True)
2185                else:
2186                    self.sld_axes = ""
2187
2188            else:
2189                self._hide_multfactor_combobox()
2190                self.show_sld_button.Hide()
2191                form_factor = form_factor()
2192                self.multi_factor = None
2193        else:
2194            self._hide_multfactor_combobox()
2195            self.show_sld_button.Hide()
2196            self.multi_factor = None
2197             
2198        s_id = self.structurebox.GetCurrentSelection()
2199        struct_factor = self.structurebox.GetClientData(s_id)
2200       
2201        if  struct_factor != None:
2202            from sans.models.MultiplicationModel import MultiplicationModel
2203            self.model = MultiplicationModel(form_factor, struct_factor())
2204            # multifunctional form factor
2205            if len(form_factor.non_fittable) > 0:
2206                self.temp_multi_functional = True
2207        else:
2208            if form_factor != None:
2209                self.model = form_factor
2210            else:
2211                self.model = None
2212                return self.model
2213           
2214        ## post state to fit panel
2215        self.state.parameters = []
2216        self.state.model = self.model
2217        self.state.qmin = self.qmin_x
2218        self.state.multi_factor = self.multi_factor
2219        self.disp_list = self.model.getDispParamList()
2220        self.state.disp_list = self.disp_list
2221        self.on_set_focus(None)
2222        self.Layout()
2223       
2224    def _validate_qrange(self, qmin_ctrl, qmax_ctrl):
2225        """
2226        Verify that the Q range controls have valid values
2227        and that Qmin < Qmax.
2228       
2229        :param qmin_ctrl: text control for Qmin
2230        :param qmax_ctrl: text control for Qmax
2231       
2232        :return: True is the Q range is value, False otherwise
2233       
2234        """
2235        qmin_validity = check_float(qmin_ctrl)
2236        qmax_validity = check_float(qmax_ctrl)
2237        if not (qmin_validity and qmax_validity):
2238            return False
2239        else:
2240            qmin = float(qmin_ctrl.GetValue())
2241            qmax = float(qmax_ctrl.GetValue())
2242            if qmin < qmax:
2243                #Make sure to set both colours white.
2244                qmin_ctrl.SetBackgroundColour(wx.WHITE)
2245                qmin_ctrl.Refresh()
2246                qmax_ctrl.SetBackgroundColour(wx.WHITE)
2247                qmax_ctrl.Refresh()
2248            else:
2249                qmin_ctrl.SetBackgroundColour("pink")
2250                qmin_ctrl.Refresh()
2251                qmax_ctrl.SetBackgroundColour("pink")
2252                qmax_ctrl.Refresh()
2253                msg = "Invalid Q range: Q min must be smaller than Q max"
2254                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2255                return False
2256        return True
2257   
2258    def _validate_Npts(self):
2259        """
2260        Validate the number of points for fitting is more than 10 points.
2261        If valid, setvalues Npts_fit otherwise post msg.
2262        """
2263        #default flag
2264        flag = True
2265        # Theory
2266        if self.data == None and self.enable2D:
2267            return flag
2268        for data in self.data_list:
2269            # q value from qx and qy
2270            radius = numpy.sqrt(data.qx_data * data.qx_data +
2271                                data.qy_data * data.qy_data)
2272            #get unmasked index
2273            index_data = (float(self.qmin.GetValue()) <= radius) & \
2274                            (radius <= float(self.qmax.GetValue()))
2275            index_data = (index_data) & (data.mask)
2276            index_data = (index_data) & (numpy.isfinite(data.data))
2277
2278            if len(index_data[index_data]) < 10:
2279                # change the color pink.
2280                self.qmin.SetBackgroundColour("pink")
2281                self.qmin.Refresh()
2282                self.qmax.SetBackgroundColour("pink")
2283                self.qmax.Refresh()
2284                msg = "Npts of Data Error :"
2285                msg += "No or too little npts of %s." % data.name
2286                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2287                self.fitrange = False
2288                flag = False
2289            else:
2290                self.Npts_fit.SetValue(str(len(index_data[index_data == True])))
2291                self.fitrange = True
2292           
2293        return flag
2294
2295    def _validate_Npts_1D(self):
2296        """
2297        Validate the number of points for fitting is more than 5 points.
2298        If valid, setvalues Npts_fit otherwise post msg.
2299        """
2300        #default flag
2301        flag = True
2302        # Theory
2303        if self.data == None:
2304            return flag
2305        for data in self.data_list:
2306            # q value from qx and qy
2307            radius = data.x
2308            #get unmasked index
2309            index_data = (float(self.qmin.GetValue()) <= radius) & \
2310                            (radius <= float(self.qmax.GetValue()))
2311            index_data = (index_data) & (numpy.isfinite(data.y))
2312
2313            if len(index_data[index_data]) < 5:
2314                # change the color pink.
2315                self.qmin.SetBackgroundColour("pink")
2316                self.qmin.Refresh()
2317                self.qmax.SetBackgroundColour("pink")
2318                self.qmax.Refresh()
2319                msg = "Npts of Data Error :"
2320                msg += "No or too little npts of %s." % data.name
2321                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2322                self.fitrange = False
2323                flag = False
2324            else:
2325                self.Npts_fit.SetValue(str(len(index_data[index_data == True])))
2326                self.fitrange = True
2327           
2328        return flag
2329   
2330    def _check_value_enter(self, list, modified):
2331        """
2332        :param list: model parameter and panel info
2333        :Note: each item of the list should be as follow:
2334            item=[check button state, parameter's name,
2335                paramater's value, string="+/-",
2336                parameter's error of fit,
2337                parameter's minimum value,
2338                parrameter's maximum value ,
2339                parameter's units]
2340        """
2341        is_modified = modified
2342        if len(list) == 0:
2343            return is_modified
2344        for item in list:
2345            #skip angle parameters for 1D
2346            if not self.enable2D:
2347                if item in self.orientation_params:
2348                    continue
2349            #try:
2350            name = str(item[1])
2351           
2352            if string.find(name, ".npts") == -1 and \
2353                                        string.find(name, ".nsigmas") == -1:
2354                ## check model parameters range
2355                param_min = None
2356                param_max = None
2357               
2358                ## check minimun value
2359                if item[5] != None and item[5] != "":
2360                    if item[5].GetValue().lstrip().rstrip() != "":
2361                        try:
2362                            param_min = float(item[5].GetValue())
2363                            if not self._validate_qrange(item[5], item[2]):
2364                                if numpy.isfinite(param_min):
2365                                    item[2].SetValue(format_number(param_min))
2366                           
2367                            item[5].SetBackgroundColour(wx.WHITE)
2368                            item[2].SetBackgroundColour(wx.WHITE)
2369                                           
2370                        except:
2371                            msg = "Wrong Fit parameter range entered "
2372                            wx.PostEvent(self.parent.parent,
2373                                         StatusEvent(status=msg))
2374                            raise ValueError, msg
2375                        is_modified = True
2376                ## check maximum value
2377                if item[6] != None and item[6] != "":
2378                    if item[6].GetValue().lstrip().rstrip() != "":
2379                        try:
2380                            param_max = float(item[6].GetValue())
2381                            if not self._validate_qrange(item[2], item[6]):
2382                                if numpy.isfinite(param_max):
2383                                    item[2].SetValue(format_number(param_max))
2384                           
2385                            item[6].SetBackgroundColour(wx.WHITE)
2386                            item[2].SetBackgroundColour(wx.WHITE)
2387                        except:
2388                            msg = "Wrong Fit parameter range entered "
2389                            wx.PostEvent(self.parent.parent,
2390                                         StatusEvent(status=msg))
2391                            raise ValueError, msg
2392                        is_modified = True
2393               
2394                if param_min != None and param_max != None:
2395                    if not self._validate_qrange(item[5], item[6]):
2396                        msg = "Wrong Fit range entered for parameter "
2397                        msg += "name %s of model %s " % (name, self.model.name)
2398                        wx.PostEvent(self.parent.parent,
2399                                     StatusEvent(status=msg))
2400               
2401                if name in self.model.details.keys():
2402                    self.model.details[name][1:3] = param_min, param_max
2403                    is_modified = True
2404                else:
2405                    self.model.details[name] = ["", param_min, param_max]
2406                    is_modified = True
2407            try:
2408                # Check if the textctr is enabled
2409                if item[2].IsEnabled():
2410                    value = float(item[2].GetValue())
2411                    item[2].SetBackgroundColour("white")
2412                    # If the value of the parameter has changed,
2413                    # +update the model and set the is_modified flag
2414                    if value != self.model.getParam(name) and \
2415                                                numpy.isfinite(value):
2416                        self.model.setParam(name, value)
2417            except:
2418                item[2].SetBackgroundColour("pink")
2419                msg = "Wrong Fit parameter value entered "
2420                wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2421               
2422        return is_modified
2423       
2424    def _set_dipers_Param(self, event):
2425        """
2426        respond to self.enable_disp and self.disable_disp radio box.
2427        The dispersity object is reset inside the model into Gaussian.
2428        When the user select yes , this method display a combo box for
2429        more selection when the user selects No,the combo box disappears.
2430        Redraw the model with the default dispersity (Gaussian)
2431        """
2432        ## On selction if no model exists.
2433        if self.model == None:
2434            self.disable_disp.SetValue(True)
2435            msg = "Please select a Model first..."
2436            wx.MessageBox(msg, 'Info')
2437            wx.PostEvent(self._manager.parent,
2438                         StatusEvent(status="Polydispersion: %s" % msg))
2439            return
2440
2441        self._reset_dispersity()
2442   
2443        if self.model == None:
2444            self.model_disp.Hide()
2445            self.sizer4_4.Clear(True)
2446            return
2447
2448        if self.enable_disp.GetValue():
2449            ## layout for model containing no dispersity parameters
2450           
2451            self.disp_list = self.model.getDispParamList()
2452             
2453            if len(self.disp_list) == 0 and len(self.disp_cb_dict) == 0:
2454                self._layout_sizer_noDipers()
2455            else:
2456                ## set gaussian sizer
2457                self._on_select_Disp(event=None)
2458        else:
2459            self.sizer4_4.Clear(True)
2460           
2461        ## post state to fit panel
2462        self.save_current_state()
2463        if event != None:
2464            event = PageInfoEvent(page=self)
2465            wx.PostEvent(self.parent, event)
2466        #draw the model with the current dispersity
2467        self._draw_model()
2468        self.sizer4_4.Layout()
2469        self.sizer5.Layout()
2470        self.Layout()
2471        self.Refresh()
2472         
2473    def _layout_sizer_noDipers(self):
2474        """
2475        Draw a sizer with no dispersity info
2476        """
2477        ix = 0
2478        iy = 1
2479        self.fittable_param = []
2480        self.fixed_param = []
2481        self.orientation_params_disp = []
2482       
2483        self.sizer4_4.Clear(True)
2484        text = "No polydispersity available for this model"
2485        model_disp = wx.StaticText(self, -1, text)
2486        self.sizer4_4.Add(model_disp, (iy, ix), (1, 1),
2487                          wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10)
2488        self.sizer4_4.Layout()
2489        self.sizer4.Layout()
2490   
2491    def _reset_dispersity(self):
2492        """
2493        put gaussian dispersity into current model
2494        """
2495        if len(self.param_toFit) > 0:
2496            for item in self.fittable_param:
2497                if item in self.param_toFit:
2498                    self.param_toFit.remove(item)
2499
2500            for item in self.orientation_params_disp:
2501                if item in self.param_toFit:
2502                    self.param_toFit.remove(item)
2503         
2504        self.fittable_param = []
2505        self.fixed_param = []
2506        self.orientation_params_disp = []
2507        self.values = {}
2508        self.weights = {}
2509     
2510        from sans.models.dispersion_models import GaussianDispersion
2511        if len(self.disp_cb_dict) == 0:
2512            self.save_current_state()
2513            self.sizer4_4.Clear(True)
2514            self.Layout()
2515            return
2516        if (len(self.disp_cb_dict) > 0):
2517            for p in self.disp_cb_dict:
2518                # The parameter was un-selected.
2519                # Go back to Gaussian model (with 0 pts)
2520                disp_model = GaussianDispersion()
2521               
2522                self._disp_obj_dict[p] = disp_model
2523                # Set the new model as the dispersion object
2524                # for the selected parameter
2525                try:
2526                    self.model.set_dispersion(p, disp_model)
2527                except:
2528
2529                    pass
2530
2531        ## save state into
2532        self.save_current_state()
2533        self.Layout()
2534        self.Refresh()
2535                 
2536    def _on_select_Disp(self, event):
2537        """
2538        allow selecting different dispersion
2539        self.disp_list should change type later .now only gaussian
2540        """
2541        self._set_sizer_dispersion()
2542
2543        ## Redraw the model
2544        self._draw_model()
2545        #self._undo.Enable(True)
2546        event = PageInfoEvent(page=self)
2547        wx.PostEvent(self.parent, event)
2548       
2549        self.sizer4_4.Layout()
2550        self.sizer4.Layout()
2551        self.SetupScrolling()
2552   
2553    def _on_disp_func(self, event=None):
2554        """
2555        Select a distribution function for the polydispersion
2556       
2557        :Param event: ComboBox event
2558        """
2559        # get ready for new event
2560        if event != None:
2561            event.Skip()
2562        # Get event object
2563        disp_box = event.GetEventObject()
2564
2565        # Try to select a Distr. function
2566        try:
2567            disp_box.SetBackgroundColour("white")
2568            selection = disp_box.GetCurrentSelection()
2569            param_name = disp_box.Name.split('.')[0]
2570            disp_name = disp_box.GetValue()
2571            dispersity = disp_box.GetClientData(selection)
2572   
2573            #disp_model =  GaussianDispersion()
2574            disp_model = dispersity()
2575            # Get param names to reset the values of the param
2576            name1 = param_name + ".width"
2577            name2 = param_name + ".npts"
2578            name3 = param_name + ".nsigmas"
2579            # Check Disp. function whether or not it is 'array'
2580            if disp_name.lower() == "array":
2581                value2 = ""
2582                value3 = ""
2583                value1 = self._set_array_disp(name=name1, disp=disp_model)
2584            else:
2585                self._del_array_values(name1)
2586                #self._reset_array_disp(param_name)
2587                self._disp_obj_dict[name1] = disp_model
2588                self.model.set_dispersion(param_name, disp_model)
2589                self.state._disp_obj_dict[name1] = disp_model
2590 
2591                value1 = str(format_number(self.model.getParam(name1), True))
2592                value2 = str(format_number(self.model.getParam(name2)))
2593                value3 = str(format_number(self.model.getParam(name3)))
2594            # Reset fittable polydispersin parameter value
2595            for item in self.fittable_param:
2596                if item[1] == name1:
2597                    item[2].SetValue(value1)
2598                    item[5].SetValue("")
2599                    item[6].SetValue("")
2600                    # Disable for array
2601                    if disp_name.lower() == "array":
2602                        item[0].SetValue(False)
2603                        item[0].Disable()
2604                        item[2].Disable()
2605                        item[3].Show(False)
2606                        item[4].Show(False)
2607                        item[5].Disable()
2608                        item[6].Disable()
2609                    else:
2610                        item[0].Enable()
2611                        item[2].Enable()
2612                        item[5].Enable()
2613                        item[6].Enable()
2614                    break
2615            # Reset fixed polydispersion params
2616            for item in self.fixed_param:
2617                if item[1] == name2:
2618                    item[2].SetValue(value2) 
2619                    # Disable Npts for array
2620                    if disp_name.lower() == "array":
2621                        item[2].Disable()
2622                    else:
2623                        item[2].Enable()
2624                if item[1] == name3:
2625                    item[2].SetValue(value3)
2626                    # Disable Nsigs for array
2627                    if disp_name.lower() == "array":
2628                        item[2].Disable()
2629                    else:
2630                        item[2].Enable()
2631               
2632            # Make sure the check box updated when all checked
2633            if self.cb1.GetValue():
2634                #self.select_all_param(None)
2635                self.get_all_checked_params()
2636
2637            # update params
2638            self._update_paramv_on_fit()
2639            # draw
2640            self._draw_model()
2641            self.Refresh()
2642        except:
2643            # Error msg
2644            msg = "Error occurred:"
2645            msg += " Could not select the distribution function..."
2646            msg += " Please select another distribution function."
2647            disp_box.SetBackgroundColour("pink")
2648            # Focus on Fit button so that users can see the pinky box
2649            self.btFit.SetFocus()
2650            wx.PostEvent(self.parent.parent,
2651                         StatusEvent(status=msg, info="error"))
2652       
2653    def _set_array_disp(self, name=None, disp=None):
2654        """
2655        Set array dispersion
2656       
2657        :param name: name of the parameter for the dispersion to be set
2658        :param disp: the polydisperion object
2659        """
2660        # The user wants this parameter to be averaged.
2661        # Pop up the file selection dialog.
2662        path = self._selectDlg()
2663        # Array data
2664        values = []
2665        weights = []
2666        # If nothing was selected, just return
2667        if path is None:
2668            self.disp_cb_dict[name].SetValue(False)
2669            #self.noDisper_rbox.SetValue(True)
2670            return
2671        self._default_save_location = os.path.dirname(path)
2672        if self.parent != None:
2673            self.parent.parent._default_save_location =\
2674                             self._default_save_location
2675
2676        basename = os.path.basename(path)
2677        values, weights = self.read_file(path)
2678       
2679        # If any of the two arrays is empty, notify the user that we won't
2680        # proceed
2681        if len(self.param_toFit) > 0:
2682            if name in self.param_toFit:
2683                self.param_toFit.remove(name)
2684
2685        # Tell the user that we are about to apply the distribution
2686        msg = "Applying loaded %s distribution: %s" % (name, path)
2687        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2688        self._set_array_disp_model(name=name, disp=disp,
2689                                    values=values, weights=weights)
2690        return basename
2691   
2692    def _set_array_disp_model(self, name=None, disp=None,
2693                              values=[], weights=[]):
2694        """
2695        Set array dispersion model
2696       
2697        :param name: name of the parameter for the dispersion to be set
2698        :param disp: the polydisperion object
2699        """
2700        disp.set_weights(values, weights)
2701        self._disp_obj_dict[name] = disp
2702        self.model.set_dispersion(name.split('.')[0], disp)
2703        self.state._disp_obj_dict[name] = disp
2704        self.values[name] = values
2705        self.weights[name] = weights
2706        # Store the object to make it persist outside the
2707        # scope of this method
2708        #TODO: refactor model to clean this up?
2709        self.state.values = {}
2710        self.state.weights = {}
2711        self.state.values = copy.deepcopy(self.values)
2712        self.state.weights = copy.deepcopy(self.weights)
2713
2714        # Set the new model as the dispersion object for the
2715        #selected parameter
2716        #self.model.set_dispersion(p, disp_model)
2717        # Store a reference to the weights in the model object
2718        #so that
2719        # it's not lost when we use the model within another thread.
2720        self.state.model = self.model.clone()
2721        self.model._persistency_dict[name.split('.')[0]] = \
2722                                        [values, weights]
2723        self.state.model._persistency_dict[name.split('.')[0]] = \
2724                                        [values, weights]
2725                                       
2726    def _del_array_values(self, name=None):
2727        """
2728        Reset array dispersion
2729       
2730        :param name: name of the parameter for the dispersion to be set
2731        """
2732        # Try to delete values and weight of the names array dic if exists
2733        try:
2734            del self.values[name]
2735            del self.weights[name]
2736            # delete all other dic
2737            del self.state.values[name]
2738            del self.state.weights[name]
2739            del self.model._persistency_dict[name.split('.')[0]]
2740            del self.state.model._persistency_dict[name.split('.')[0]]
2741        except:
2742            pass
2743                                           
2744    def _lay_out(self):
2745        """
2746        returns self.Layout
2747       
2748        :Note: Mac seems to like this better when self.
2749            Layout is called after fitting.
2750        """
2751        self._sleep4sec()
2752        self.Layout()
2753        return
2754   
2755    def _sleep4sec(self):
2756        """
2757            sleep for 1 sec only applied on Mac
2758            Note: This 1sec helps for Mac not to crash on self.
2759            Layout after self._draw_model
2760        """
2761        if ON_MAC == True:
2762            time.sleep(1)
2763           
2764    def _find_polyfunc_selection(self, disp_func=None):
2765        """
2766        FInd Comboox selection from disp_func
2767       
2768        :param disp_function: dispersion distr. function
2769        """
2770        # List of the poly_model name in the combobox
2771        list = ["RectangleDispersion", "ArrayDispersion",
2772                "LogNormalDispersion", "GaussianDispersion",
2773                "SchulzDispersion"]
2774
2775        # Find the selection
2776        try:
2777            selection = list.index(disp_func.__class__.__name__)
2778            return selection
2779        except:
2780            return 3
2781                           
2782    def on_reset_clicked(self, event):
2783        """
2784        On 'Reset' button  for Q range clicked
2785        """
2786        flag = True
2787        ##For 3 different cases: Data2D, Data1D, and theory
2788        if self.model == None:
2789            msg = "Please select a model first..."
2790            wx.MessageBox(msg, 'Info')
2791            flag = False
2792            return
2793           
2794        elif self.data.__class__.__name__ == "Data2D":
2795            data_min = 0
2796            x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax))
2797            y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
2798            self.qmin_x = data_min
2799            self.qmax_x = math.sqrt(x*x + y*y)
2800            #self.data.mask = numpy.ones(len(self.data.data),dtype=bool)
2801            # check smearing
2802            if not self.disable_smearer.GetValue():
2803                ## set smearing value whether or
2804                # not the data contain the smearing info
2805                if self.pinhole_smearer.GetValue():
2806                    flag = self.update_pinhole_smear()
2807                else:
2808                    flag = True
2809                   
2810        elif self.data == None:
2811            self.qmin_x = _QMIN_DEFAULT
2812            self.qmax_x = _QMAX_DEFAULT
2813            self.num_points = _NPTS_DEFAULT
2814            self.state.npts = self.num_points
2815           
2816        elif self.data.__class__.__name__ != "Data2D":
2817            self.qmin_x = min(self.data.x)
2818            self.qmax_x = max(self.data.x)
2819            # check smearing
2820            if not self.disable_smearer.GetValue():
2821                ## set smearing value whether or
2822                # not the data contain the smearing info
2823                if self.slit_smearer.GetValue():
2824                    flag = self.update_slit_smear()
2825                elif self.pinhole_smearer.GetValue():
2826                    flag = self.update_pinhole_smear()
2827                else:
2828                    flag = True
2829        else:
2830            flag = False
2831           
2832        if flag == False:
2833            msg = "Cannot Plot :Must enter a number!!!  "
2834            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
2835        else:
2836            # set relative text ctrs.
2837            self.qmin.SetValue(str(self.qmin_x))
2838            self.qmax.SetValue(str(self.qmax_x))
2839            self.set_npts2fit()
2840            # At this point, some button and variables satatus (disabled?)
2841            # should be checked such as color that should be reset to
2842            # white in case that it was pink.
2843            self._onparamEnter_helper()
2844
2845        self.save_current_state()
2846        self.state.qmin = self.qmin_x
2847        self.state.qmax = self.qmax_x
2848       
2849        #reset the q range values
2850        self._reset_plotting_range(self.state)
2851        self._draw_model()
2852       
2853    def get_images(self):
2854        """
2855        Get the images of the plots corresponding this panel for report
2856       
2857        : return graphs: list of figures
2858        : Need Move to guiframe
2859        """
2860        # set list of graphs
2861        graphs = []
2862        canvases = []
2863        # call gui_manager
2864        gui_manager = self.parent.parent
2865        # loops through the panels [dic]
2866        for _, item2 in gui_manager.plot_panels.iteritems():
2867            data_title = self.data.group_id
2868            # try to get all plots belonging to this control panel
2869            try:
2870                if item2.group_id == data_title or \
2871                        item2.group_id.count("res" + str(self.graph_id)) or \
2872                        item2.group_id.count(str(self.uid)) > 0:
2873                    # append to the list
2874                    graphs.append(item2.figure)
2875                    canvases.append(item2.canvas)
2876            except:
2877                # Not for control panels
2878                pass
2879        # return the list of graphs
2880        return graphs, canvases
2881
2882    def on_model_help_clicked(self, event):
2883        """
2884        on 'More details' button
2885        """
2886        from sans.perspectives.fitting.help_panel import  HelpWindow
2887        from sans.models import get_data_path
2888       
2889        # Get models help model_function path
2890        path = get_data_path(media='media')
2891        model_path = os.path.join(path, "model_functions.html")
2892        if self.model == None:
2893            name = 'FuncHelp'
2894        else:
2895            name = self.formfactorbox.GetValue()
2896        frame = HelpWindow(None, -1, pageToOpen=model_path)
2897        # If model name exists and model is not a custom model
2898        if frame.rhelp.HasAnchor(name) and not self.plugin_rbutton.GetValue():
2899            frame.Show(True)
2900            frame.rhelp.ScrollToAnchor(name)
2901        else:
2902            if self.model != None:
2903                frame.Destroy()
2904                msg = 'Model description:\n'
2905                if str(self.model.description).rstrip().lstrip() == '':
2906                    msg += "Sorry, no information is available for this model."
2907                else:
2908                    msg += self.model.description + '\n'
2909                info = "Info"
2910                wx.MessageBox(msg, info)
2911            else:
2912                frame.Show(True)
2913   
2914    def on_pd_help_clicked(self, event):
2915        """
2916        Button event for PD help
2917        """
2918        from help_panel import  HelpWindow
2919        import sans.models as models
2920       
2921        # Get models help model_function path
2922        path = models.get_data_path(media='media')
2923        pd_path = os.path.join(path, "pd_help.html")
2924
2925        frame = HelpWindow(None, -1, pageToOpen=pd_path)
2926        frame.Show(True)
2927       
2928    def on_left_down(self, event):
2929        """
2930        Get key stroke event
2931        """
2932        # Figuring out key combo: Cmd for copy, Alt for paste
2933        if event.CmdDown() and event.ShiftDown():
2934            self.get_paste()
2935        elif event.CmdDown():
2936            self.get_copy()
2937        else:
2938            event.Skip()
2939            return
2940        # make event free
2941        event.Skip()
2942       
2943    def get_copy(self):
2944        """
2945        Get copy params to clipboard
2946        """
2947        content = self.get_copy_params()
2948        flag = self.set_clipboard(content)
2949        self._copy_info(flag)
2950        return flag
2951           
2952    def get_copy_params(self):
2953        """
2954        Get the string copies of the param names and values in the tap
2955        """
2956        content = 'sansview_parameter_values:'
2957        # Do it if params exist
2958        if  self.parameters != []:
2959           
2960            # go through the parameters
2961            strings = self._get_copy_helper(self.parameters,
2962                                           self.orientation_params)
2963            content += strings
2964           
2965            # go through the fittables
2966            strings = self._get_copy_helper(self.fittable_param,
2967                                           self.orientation_params_disp)
2968            content += strings
2969
2970            # go through the fixed params
2971            strings = self._get_copy_helper(self.fixed_param,
2972                                           self.orientation_params_disp)
2973            content += strings
2974               
2975            # go through the str params
2976            strings = self._get_copy_helper(self.str_parameters,
2977                                           self.orientation_params)
2978            content += strings
2979            return content
2980        else:
2981            return False
2982   
2983    def set_clipboard(self, content=None):
2984        """
2985        Put the string to the clipboard
2986        """
2987        if not content:
2988            return False
2989        if wx.TheClipboard.Open():
2990            wx.TheClipboard.SetData(wx.TextDataObject(str(content)))
2991            wx.TheClipboard.Close()
2992            return True
2993        return None
2994   
2995    def _get_copy_helper(self, param, orient_param):
2996        """
2997        Helping get value and name of the params
2998       
2999        : param param:  parameters
3000        : param orient_param = oritational params
3001        : return content: strings [list] [name,value:....]
3002        """
3003        content = ''
3004        # go through the str params
3005        for item in param:
3006            # copy only the params shown
3007            if not item[2].IsShown():
3008                continue
3009            disfunc = ''
3010            try:
3011                if item[7].__class__.__name__ == 'ComboBox':
3012                    disfunc = str(item[7].GetValue())
3013            except:
3014                pass
3015           
3016            # 2D
3017            if self.data.__class__.__name__ == "Data2D":
3018                try:
3019                    check = item[0].GetValue()
3020                except:
3021                    check = None
3022                name = item[1]
3023                value = item[2].GetValue()
3024            # 1D
3025            else:
3026                ## for 1D all parameters except orientation
3027                if not item[1] in orient_param:
3028                    try:
3029                        check = item[0].GetValue()
3030                    except:
3031                        check = None
3032                    name = item[1]
3033                    value = item[2].GetValue()
3034
3035            # add to the content
3036            if disfunc != '':
3037               
3038                disfunc = ',' + disfunc
3039            # Need to support array func for copy/paste
3040            try:
3041                if disfunc.count('array') > 0:
3042                    disfunc += ','
3043                    for val in self.values[name]:
3044                        disfunc += ' ' + str(val)
3045                    disfunc += ','
3046                    for weight in self.weights[name]:
3047                        disfunc += ' ' + str(weight)
3048            except:
3049                pass
3050            content += name + ',' + str(check) + ',' + value + disfunc + ':'
3051
3052        return content
3053   
3054    def get_clipboard(self):
3055        """
3056        Get strings in the clipboard
3057        """
3058        text = ""
3059        # Get text from the clip board
3060        if wx.TheClipboard.Open():
3061            if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
3062                data = wx.TextDataObject()
3063                # get wx dataobject
3064                #success = wx.TheClipboard.GetData(data)
3065                # get text
3066                text = data.GetText()
3067            # close clipboard
3068            wx.TheClipboard.Close()
3069        return text
3070   
3071    def get_paste(self):
3072        """
3073        Paste params from the clipboard
3074        """
3075        text = self.get_clipboard()
3076        flag = self.get_paste_params(text)
3077        self._copy_info(flag)
3078        return flag
3079       
3080    def get_paste_params(self, text=''):
3081        """
3082        Get the string copies of the param names and values in the tap
3083        """
3084        context = {}
3085        # put the text into dictionary
3086        lines = text.split(':')
3087        if lines[0] != 'sansview_parameter_values':
3088            self._copy_info(False)
3089            return False
3090        for line in lines[1:-1]:
3091            if len(line) != 0:
3092                item = line.split(',')
3093                check = item[1]
3094                name = item[0]
3095                value = item[2]
3096                # Transfer the text to content[dictionary]
3097                context[name] = [check, value]
3098            # ToDo: PlugIn this poly disp function for pasting
3099            try:
3100                poly_func = item[3]
3101                context[name].append(poly_func)
3102                try:
3103                    # take the vals and weights for  array
3104                    array_values = item[4].split(' ')
3105                    array_weights = item[5].split(' ')
3106                    val = [float(a_val) for a_val in array_values[1:]]
3107                    weit = [float(a_weit) for a_weit in array_weights[1:]]
3108                   
3109                    context[name].append(val)
3110                    context[name].append(weit)
3111                except:
3112                    raise
3113            except:
3114                poly_func = ''
3115                context[name].append(poly_func)
3116
3117        # Do it if params exist
3118        if  self.parameters != []:
3119            # go through the parameters
3120            self._get_paste_helper(self.parameters,
3121                                   self.orientation_params, context)
3122
3123            # go through the fittables
3124            self._get_paste_helper(self.fittable_param,
3125                                   self.orientation_params_disp,
3126                                   context)
3127
3128            # go through the fixed params
3129            self._get_paste_helper(self.fixed_param,
3130                                   self.orientation_params_disp, context)
3131           
3132            # go through the str params
3133            self._get_paste_helper(self.str_parameters,
3134                                   self.orientation_params, context)
3135               
3136            return True
3137        return None
3138   
3139    def _get_paste_helper(self, param, orient_param, content):
3140        """
3141        Helping set values of the params
3142       
3143        : param param:  parameters
3144        : param orient_param: oritational params
3145        : param content: dictionary [ name, value: name1.value1,...]
3146        """
3147        # go through the str params
3148        for item in param:
3149            # 2D
3150            if self.data.__class__.__name__ == "Data2D":
3151                name = item[1]
3152                if name in content.keys():
3153                    check = content[name][0]
3154                    pd = content[name][1]
3155                    if name.count('.') > 0:
3156                        try:
3157                            float(pd)
3158                        except:
3159                            #continue
3160                            if not pd and pd != '':
3161                                continue
3162                    item[2].SetValue(str(pd))
3163                    if item in self.fixed_param and pd == '':
3164                        # Only array func has pd == '' case.
3165                        item[2].Enable(False)
3166                    if item[2].__class__.__name__ == "ComboBox":
3167                        if content[name][1] in self.model.fun_list:
3168                            fun_val = self.model.fun_list[content[name][1]]
3169                            self.model.setParam(name, fun_val)
3170                   
3171                    value = content[name][1:]
3172                    self._paste_poly_help(item, value)
3173                    if check == 'True':
3174                        is_true = True
3175                    elif check == 'False':
3176                        is_true = False
3177                    else:
3178                        is_true = None
3179                    if is_true != None:
3180                        item[0].SetValue(is_true)
3181            # 1D
3182            else:
3183                ## for 1D all parameters except orientation
3184                if not item[1] in orient_param:
3185                    name = item[1]
3186                    if name in content.keys():
3187                        check = content[name][0]
3188                        # Avoid changing combox content
3189                        value = content[name][1:]
3190                        pd = value[0]
3191                        if name.count('.') > 0:
3192                            try:
3193                                pd = float(pd)
3194                            except:
3195                                #continue
3196                                if not pd and pd != '':
3197                                    continue
3198                        item[2].SetValue(str(pd))
3199                        if item in self.fixed_param and pd == '':
3200                            # Only array func has pd == '' case.
3201                            item[2].Enable(False)
3202                        if item[2].__class__.__name__ == "ComboBox":
3203                            if value[0] in self.model.fun_list:
3204                                fun_val = self.model.fun_list[value[0]]
3205                                self.model.setParam(name, fun_val)
3206                                # save state
3207                        self._paste_poly_help(item, value)
3208                        if check == 'True':
3209                            is_true = True
3210                        elif check == 'False':
3211                            is_true = False
3212                        else:
3213                            is_true = None
3214                        if is_true != None:
3215                            item[0].SetValue(is_true)
3216                       
3217    def _paste_poly_help(self, item, value):
3218        """
3219        Helps get paste for poly function
3220       
3221        :param item: Gui param items
3222        :param value: the values for parameter ctrols
3223        """
3224        is_array = False
3225        if len(value[1]) > 0:
3226            # Only for dispersion func.s
3227            try:
3228                item[7].SetValue(value[1])
3229                selection = item[7].GetCurrentSelection()
3230                name = item[7].Name
3231                param_name = name.split('.')[0]
3232                dispersity = item[7].GetClientData(selection)
3233                disp_model = dispersity()
3234                # Only for array disp
3235                try:
3236                    pd_vals = numpy.array(value[2])
3237                    pd_weights = numpy.array(value[3])
3238                    if len(pd_vals) > 0 and len(pd_vals) > 0:
3239                        if len(pd_vals) == len(pd_weights):
3240                            self._set_disp_array_cb(item=item)
3241                            self._set_array_disp_model(name=name,
3242                                                       disp=disp_model,
3243                                                       values=pd_vals,
3244                                                       weights=pd_weights)
3245                            is_array = True
3246                except:
3247                    pass
3248                if not is_array:
3249                    self._disp_obj_dict[name] = disp_model
3250                    self.model.set_dispersion(name,
3251                                              disp_model)
3252                    self.state._disp_obj_dict[name] = \
3253                                              disp_model
3254                    self.model.set_dispersion(param_name, disp_model)
3255                    self.state.values = self.values
3256                    self.state.weights = self.weights
3257                    self.model._persistency_dict[param_name] = \
3258                                            [self.state.values,
3259                                             self.state.weights]
3260                         
3261            except:
3262                print "Error in BasePage._paste_poly_help: %s" % sys.exc_value
3263   
3264    def _set_disp_array_cb(self, item):
3265        """
3266        Set cb for array disp
3267        """
3268        item[0].SetValue(False)
3269        item[0].Enable(False)
3270        item[2].Enable(False)
3271        item[3].Show(False)
3272        item[4].Show(False)
3273        item[5].SetValue('')
3274        item[5].Enable(False)
3275        item[6].SetValue('')
3276        item[6].Enable(False)
3277       
3278    def update_pinhole_smear(self):
3279        """
3280            Method to be called by sub-classes
3281            Moveit; This method doesn't belong here
3282        """
3283        print "BasicPage.update_pinhole_smear was called: skipping"
3284        return
3285
3286    def _fill_model_sizer(self, sizer):
3287        """
3288        fill sizer containing model info
3289        """
3290        ##Add model function Details button in fitpanel.
3291        ##The following 3 lines are for Mac. Let JHC know before modifying...
3292        title = "Model"
3293        self.formfactorbox = None
3294        self.multifactorbox = None
3295        self.mbox_description = wx.StaticBox(self, -1, str(title))
3296        boxsizer1 = wx.StaticBoxSizer(self.mbox_description, wx.VERTICAL)
3297        self.mbox_description.SetForegroundColour(wx.RED)
3298        id = wx.NewId()
3299        self.model_help = wx.Button(self, id, 'Details', size=(80, 23))
3300        self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked, id=id)
3301        self.model_help.SetToolTipString("Model Function Help")
3302        id = wx.NewId()
3303        self.model_view = wx.Button(self, id, "Show 2D", size=(80, 23))
3304        self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D, id=id)
3305        hint = "toggle view of model from 1D to 2D  or 2D to 1D"
3306        self.model_view.SetToolTipString(hint)
3307     
3308        self.shape_rbutton = wx.RadioButton(self, -1, 'Shapes',
3309                                             style=wx.RB_GROUP)
3310        self.shape_indep_rbutton = wx.RadioButton(self, -1,
3311                                                  "Shape-Independent")
3312        self.struct_rbutton = wx.RadioButton(self, -1, "Structure Factor ")
3313        self.plugin_rbutton = wx.RadioButton(self, -1, "Customized Models")
3314               
3315        self.Bind(wx.EVT_RADIOBUTTON, self._show_combox,
3316                            id=self.shape_rbutton.GetId())
3317        self.Bind(wx.EVT_RADIOBUTTON, self._show_combox,
3318                            id=self.shape_indep_rbutton.GetId())
3319        self.Bind(wx.EVT_RADIOBUTTON, self._show_combox,
3320                            id=self.struct_rbutton.GetId())
3321        self.Bind(wx.EVT_RADIOBUTTON, self._show_combox,
3322                            id=self.plugin_rbutton.GetId())
3323        #MAC needs SetValue
3324        self.shape_rbutton.SetValue(True)
3325     
3326        sizer_radiobutton = wx.GridSizer(2, 3, 5, 5)
3327        sizer_radiobutton.Add(self.shape_rbutton)
3328        sizer_radiobutton.Add(self.shape_indep_rbutton)
3329        sizer_radiobutton.Add(self.model_view, 1, wx.LEFT, 20)
3330        sizer_radiobutton.Add(self.plugin_rbutton)
3331        sizer_radiobutton.Add(self.struct_rbutton)
3332        sizer_radiobutton.Add(self.model_help, 1, wx.LEFT, 20)
3333       
3334        sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
3335        mutifactor_selection = wx.BoxSizer(wx.HORIZONTAL)
3336       
3337        self.text1 = wx.StaticText(self, -1, "")
3338        self.text2 = wx.StaticText(self, -1, "P(Q)*S(Q)")
3339        self.mutifactor_text = wx.StaticText(self, -1, "No. of Shells: ")
3340        self.mutifactor_text1 = wx.StaticText(self, -1, "")
3341        self.show_sld_button = wx.Button(self, -1, "Show SLD Profile")
3342        self.show_sld_button.Bind(wx.EVT_BUTTON, self._on_show_sld)
3343
3344        self.formfactorbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
3345        if self.model != None:
3346            self.formfactorbox.SetValue(self.model.name)
3347        self.structurebox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
3348        self.multifactorbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)
3349        self.initialize_combox()
3350        wx.EVT_COMBOBOX(self.formfactorbox, -1, self._on_select_model)
3351
3352        wx.EVT_COMBOBOX(self.structurebox, -1, self._on_select_model)
3353        wx.EVT_COMBOBOX(self.multifactorbox, -1, self._on_select_model)
3354        ## check model type to show sizer
3355        if self.model != None:
3356            self._set_model_sizer_selection(self.model)
3357       
3358        sizer_selection.Add(self.text1)
3359        sizer_selection.Add((5, 5))
3360        sizer_selection.Add(self.formfactorbox)
3361        sizer_selection.Add((5, 5))
3362        sizer_selection.Add(self.text2)
3363        sizer_selection.Add((5, 5))
3364        sizer_selection.Add(self.structurebox)
3365       
3366        mutifactor_selection.Add((10, 5))
3367        mutifactor_selection.Add(self.mutifactor_text)
3368        mutifactor_selection.Add(self.multifactorbox)
3369        mutifactor_selection.Add((5, 5))
3370        mutifactor_selection.Add(self.mutifactor_text1)
3371        mutifactor_selection.Add((10, 5))
3372        mutifactor_selection.Add(self.show_sld_button)
3373
3374        boxsizer1.Add(sizer_radiobutton)
3375        boxsizer1.Add((10, 10))
3376        boxsizer1.Add(sizer_selection)
3377        boxsizer1.Add((10, 10))
3378        boxsizer1.Add(mutifactor_selection)
3379       
3380        self._set_multfactor_combobox()
3381        self.multifactorbox.SetSelection(1)
3382        self.show_sld_button.Hide()
3383        sizer.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
3384        sizer.Layout()
3385       
3386    def on_smear_helper(self, update=False):
3387        """
3388        Help for onSmear if implemented
3389       
3390        :param update: force or not to update
3391        """
3392    def reset_page(self, state, first=False):
3393        """
3394        reset the state  if implemented
3395        """
3396    def onSmear(self, event):
3397        """
3398        Create a smear object if implemented
3399        """
3400    def onPinholeSmear(self, event):
3401        """
3402        Create a custom pinhole smear object if implemented
3403        """
3404    def onSlitSmear(self, event):
3405        """
3406        Create a custom slit smear object if implemented
3407        """
3408    def update_slit_smear(self):
3409        """
3410        called by kill_focus on pinhole TextCntrl
3411        to update the changes if implemented
3412        """
3413    def select_param(self, event):
3414        """
3415        Select TextCtrl  checked if implemented
3416        """
3417    def set_data(self, data=None):
3418        """
3419        Sets data if implemented
3420        """
3421    def _is_2D(self):
3422        """
3423        Check if data_name is Data2D if implemented
3424        """
3425    def _on_select_model(self, event=None):
3426        """
3427        call back for model selection if implemented
3428        """
3429    def select_all_param(self, event):
3430        """
3431        set to true or false all checkBox if implemented
3432        """
3433    def get_weight_flag(self):
3434        """
3435        Get flag corresponding to a given weighting dI data if implemented
3436        """
3437    def _set_sizer_dispersion(self):
3438        """
3439        draw sizer for dispersity if implemented
3440        """
3441    def get_all_checked_params(self):
3442        """
3443        Found all parameters current check and add them to list of parameters
3444        to fit if implemented
3445        """
3446    def set_npts2fit(self):
3447        """
3448        setValue Npts for fitting if implemented
3449        """
3450    def _onModel2D(self, event):
3451        """
3452        toggle view of model from 1D to 2D  or 2D from 1D if implemented
3453        """
Note: See TracBrowser for help on using the repository browser.