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

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

fixed polydisp. array bug

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