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

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 df7a7e3 was df7a7e3, checked in by Mathieu Doucet <doucetm@…>, 12 years ago

merging category branch

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