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

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

category stuffs start working in interp. environment

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