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

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

fixed the paste problem

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