source: sasview/sansview/perspectives/fitting/basepage.py @ 1b43306

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 1b43306 was 1b43306, checked in by Gervaise Alina <gervyh@…>, 14 years ago

disable save option

  • Property mode set to 100644
File size: 89.3 KB
RevLine 
[c77d859]1
[60132ef]2import sys, os
[c77d859]3import wx
4import numpy
[a074145]5import time
[3370922]6import copy 
[904168e1]7import math
[edd166b]8import string
[85b3971]9from sans.guiframe.utils import format_number,check_float
[7975f2b]10from sans.guicomm.events import StatusEvent
[cfc0913]11import pagestate
12from pagestate import PageState
13(PageInfoEvent, EVT_PAGE_INFO)   = wx.lib.newevent.NewEvent()
[330573d]14(PreviousStateEvent, EVT_PREVIOUS_STATE)   = wx.lib.newevent.NewEvent()
15(NextStateEvent, EVT_NEXT_STATE)   = wx.lib.newevent.NewEvent()
[f72333f]16
[e7b1ccf]17_BOX_WIDTH = 76
[d4bb639]18_QMIN_DEFAULT = 0.001
19_QMAX_DEFAULT = 0.13
20_NPTS_DEFAULT = 50
[9170547]21#Control panel width
[6e9976b]22if sys.platform.count("darwin")==0:
[b421b1a]23    PANEL_WIDTH = 450
[f1aa385]24    FONT_VARIANT = 0
[35c9d31]25    ON_MAC = False
[9170547]26else:
[c99a6c5]27    PANEL_WIDTH = 500
[f1aa385]28    FONT_VARIANT = 1
[35c9d31]29    ON_MAC = True
[9170547]30   
[c77d859]31class BasicPage(wx.ScrolledWindow):
32    """
[5062bbf]33    This class provide general structure of  fitpanel page
[c77d859]34    """
[b787e68c]35     ## Internal name for the AUI manager
36    window_name = "Basic Page"
37    ## Title to appear on top of the window
38    window_caption = "Basic page "
[59a7f2d]39   
[cfc0913]40    def __init__(self,parent, page_info):
[5062bbf]41        """
42        """
[e814734]43        wx.ScrolledWindow.__init__(self, parent,
44                 style= wx.FULL_REPAINT_ON_RESIZE )
[f1aa385]45        #Set window's font size
46        self.SetWindowVariant(variant=FONT_VARIANT)
[cfc0913]47        ##window_name
[ffa69b6]48       
[c77d859]49        ## parent of the page
50        self.parent = parent
[77e23a2]51        ## manager is the fitting plugin
[ffa69b6]52        self.manager= None
[c77d859]53        ## owner of the page (fitting plugin)
[ffa69b6]54        self.event_owner= None
[cfc0913]55         ## current model
[ffa69b6]56        self.model = None
[cfc0913]57        ## data
[ffa69b6]58        self.data = None
[e575db9]59        self.mask = None
[f72333f]60        self.theory = None
[ffa69b6]61        self.state = PageState(parent=parent)
[c77d859]62        ## dictionary containing list of models
[ffa69b6]63        self.model_list_box = None
64        self.set_page_info(page_info=page_info)
[c77d859]65        ## Data member to store the dispersion object created
66        self._disp_obj_dict = {}
[cfc0913]67        ## selected parameters to apply dispersion
[c77d859]68        self.disp_cb_dict ={}
[b421b1a]69
[997131a]70        ## smearer object
71        self.smearer = None
[330573d]72       
[c77d859]73        ##list of model parameters. each item must have same length
74        ## each item related to a given parameters
75        ##[cb state, name, value, "+/-", error of fit, min, max , units]
76        self.parameters=[]
77        ## list of parameters to fit , must be like self.parameters
78        self.param_toFit=[]
79        ## list of looking like parameters but with non fittable parameters info
80        self.fixed_param=[]
81        ## list of looking like parameters but with  fittable parameters info
82        self.fittable_param=[]
83        ##list of dispersion parameters
84        self.disp_list=[]
[f20767b]85        self.disp_name=""
[ffa69b6]86       
[780d095]87        ## list of orientation parameters
88        self.orientation_params=[]
[60132ef]89        self.orientation_params_disp=[]
[cfc0913]90        if self.model !=None:
91            self.disp_list= self.model.getDispParamList()
[70c57ebf]92       
[c77d859]93        ##enable model 2D draw
94        self.enable2D= False
95        ## check that the fit range is correct to plot the model again
96        self.fitrange= True
[d4bb639]97
[c77d859]98        ## Q range
[d4bb639]99        self.qmin_x= _QMIN_DEFAULT
100        self.qmax_x= _QMAX_DEFAULT
101        self.num_points= _NPTS_DEFAULT
[cfc0913]102       
[1b69256]103        ## Create memento to save the current state
[cfc0913]104        self.state= PageState(parent= self.parent,model=self.model, data=self.data)
[240b9966]105        ## flag to determine if state has change
106        self.state_change= False
[71f0373]107        ## save customized array
108        self.values=[]
109        self.weights=[]
[a074145]110        ## retrieve saved state
111        self.number_saved_state= 0
112        ## dictionary of saved state
[330573d]113        self.saved_states={} 
[1b69256]114       
115        ## Create context menu for page
116        self.popUpMenu = wx.Menu()
[3a37fe0]117        #id = wx.NewId()
118        #self._undo = wx.MenuItem(self.popUpMenu,id, "Undo","cancel the previous action")
119        #self.popUpMenu.AppendItem(self._undo)
120        #self._undo.Enable(False)
121        #wx.EVT_MENU(self, id, self.onUndo)
122       
123        #id = wx.NewId()
124        #self._redo = wx.MenuItem(self.popUpMenu,id,"Redo"," Restore the previous action")
125        #self.popUpMenu.AppendItem(self._redo)
126        #self._redo.Enable(False)
127        #wx.EVT_MENU(self, id, self.onRedo)       
128        #self.popUpMenu.AppendSeparator()
[6d91073]129        #if sys.platform.count("win32")>0:       
130        id = wx.NewId()
131        self._keep = wx.MenuItem(self.popUpMenu,id,"BookMark"," Keep the panel status to recall it later")
132        self.popUpMenu.AppendItem(self._keep)
133        self._keep.Enable(True)
[9bc499b6]134        wx.EVT_MENU(self, id, self.on_bookmark)
[6d91073]135        self.popUpMenu.AppendSeparator()
136   
[60132ef]137        ## Default locations
138        self._default_save_location = os.getcwd()     
[a074145]139        ## save initial state on context menu
[1b69256]140        #self.onSave(event=None)
[a074145]141        self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
[f72333f]142
[cfc0913]143        ## create the basic structure of the panel with empty sizer
144        self.define_page_structure()
[c77d859]145        ## drawing Initial dispersion parameters sizer
146        self.set_dispers_sizer()
[00c3aac]147        self._fill_save_sizer()
[c77d859]148        ## layout
149        self.set_layout()
150       
[6f2c919]151    class ModelTextCtrl(wx.TextCtrl):
152        """
[5062bbf]153        Text control for model and fit parameters.
154        Binds the appropriate events for user interactions.
155        Default callback methods can be overwritten on initialization
156       
157        :param kill_focus_callback: callback method for EVT_KILL_FOCUS event
158        :param set_focus_callback:  callback method for EVT_SET_FOCUS event
159        :param mouse_up_callback:   callback method for EVT_LEFT_UP event
160        :param text_enter_callback: callback method for EVT_TEXT_ENTER event
161       
[6f2c919]162        """
[39b7019]163        ## Set to True when the mouse is clicked while the whole string is selected
164        full_selection = False
165        ## Call back for EVT_SET_FOCUS events
166        _on_set_focus_callback = None
167       
[6f2c919]168        def __init__(self, parent, id=-1, value=wx.EmptyString, pos=wx.DefaultPosition, 
169                     size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.TextCtrlNameStr,
170                     kill_focus_callback = None, set_focus_callback  = None,
171                     mouse_up_callback   = None, text_enter_callback = None):
[7975f2b]172             
[6f2c919]173            wx.TextCtrl.__init__(self, parent, id, value, pos, size, style, validator, name)
174           
[156a0b2]175            # Bind appropriate events
176            self._on_set_focus_callback = parent.onSetFocus \
177                      if set_focus_callback is None else set_focus_callback
178            self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus)
[7609f1a]179            self.Bind(wx.EVT_KILL_FOCUS, self._silent_kill_focus \
[156a0b2]180                      if kill_focus_callback is None else kill_focus_callback)               
[6f2c919]181            self.Bind(wx.EVT_TEXT_ENTER, parent._onparamEnter \
182                      if text_enter_callback is None else text_enter_callback)
[35c9d31]183            if not ON_MAC :
184                self.Bind(wx.EVT_LEFT_UP,    self._highlight_text \
185                          if mouse_up_callback is None else mouse_up_callback)
[39b7019]186           
187        def _on_set_focus(self, event):
188            """
[5062bbf]189            Catch when the text control is set in focus to highlight the whole
190            text if necessary
191           
192            :param event: mouse event
193           
[39b7019]194            """
[35c9d31]195           
[39b7019]196            event.Skip()
197            self.full_selection = True
198            return self._on_set_focus_callback(event)
199       
[35c9d31]200 
201           
[39b7019]202        def _highlight_text(self, event):
203            """
[5062bbf]204            Highlight text of a TextCtrl only of no text has be selected
205           
206            :param event: mouse event
207           
[39b7019]208            """
209            # Make sure the mouse event is available to other listeners
210            event.Skip()
211            control  = event.GetEventObject()
212            if self.full_selection:
213                self.full_selection = False
214                # Check that we have a TextCtrl
215                if issubclass(control.__class__, wx.TextCtrl):
216                    # Check whether text has been selected,
217                    # if not, select the whole string
218                    (start, end) = control.GetSelection()
219                    if start==end:
220                        control.SetSelection(-1,-1)
[7609f1a]221                       
222        def _silent_kill_focus(self,event):
223            """
[5062bbf]224            do nothing to kill focus
[7609f1a]225            """
226            event.Skip()
227            pass
228   
[ffa69b6]229    def set_page_info(self, page_info):
230        """
[5062bbf]231        set some page important information at once
[ffa69b6]232        """
233       ##window_name
234        self.window_name = page_info.window_name
235        ##window_caption
236        self.window_caption = page_info.window_caption
237        ## manager is the fitting plugin
238        self.manager= page_info.manager
239        ## owner of the page (fitting plugin)
240        self.event_owner= page_info.event_owner
241         ## current model
242        self.model = page_info.model
243        ## data
244        self.data = page_info.data
245        ## dictionary containing list of models
246        self.model_list_box = page_info.model_list_box
247        ## Data member to store the dispersion object created
248        self.populate_box(dict=self.model_list_box)
249       
[a074145]250    def onContextMenu(self, event): 
251        """
[5062bbf]252        Retrieve the state selected state
[a074145]253        """
[6d1235b]254        # Skipping the save state functionality for release 0.9.0
[dad49a0]255        #return
[6d1235b]256   
[a074145]257        pos = event.GetPosition()
258        pos = self.ScreenToClient(pos)
[1b69256]259       
260        self.PopupMenu(self.popUpMenu, pos) 
261     
[a074145]262       
[1b69256]263    def onUndo(self, event):
264        """
[5062bbf]265        Cancel the previous action
[1b69256]266        """
[30d103a]267        #print "enable undo"
[330573d]268        event = PreviousStateEvent(page = self)
269        wx.PostEvent(self.parent, event)
270       
[1b69256]271    def onRedo(self, event):
272        """
[5062bbf]273        Restore the previous action cancelled
[1b69256]274        """
[abf2d75]275        #print "enable redo"
[fe496eeb]276        event = NextStateEvent(page= self)
[330573d]277        wx.PostEvent(self.parent, event)
[5062bbf]278   
[c77d859]279    def define_page_structure(self):
280        """
[5062bbf]281        Create empty sizer for a panel
[c77d859]282        """
283        self.vbox  = wx.BoxSizer(wx.VERTICAL)
284        self.sizer0 = wx.BoxSizer(wx.VERTICAL)
285        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
286        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
287        self.sizer3 = wx.BoxSizer(wx.VERTICAL)
288        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
289        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
[0a518e4c]290        self.sizer6 = wx.BoxSizer(wx.VERTICAL)
[c77d859]291       
[9170547]292        self.sizer0.SetMinSize((PANEL_WIDTH,-1))
293        self.sizer1.SetMinSize((PANEL_WIDTH,-1))
294        self.sizer2.SetMinSize((PANEL_WIDTH,-1))
295        self.sizer3.SetMinSize((PANEL_WIDTH,-1))
296        self.sizer4.SetMinSize((PANEL_WIDTH,-1))
297        self.sizer5.SetMinSize((PANEL_WIDTH,-1))
[1b43306]298        #self.sizer6.SetMinSize((PANEL_WIDTH,-1))
[8bd4dc0]299       
[c77d859]300        self.vbox.Add(self.sizer0)
301        self.vbox.Add(self.sizer1)
302        self.vbox.Add(self.sizer2)
303        self.vbox.Add(self.sizer3)
304        self.vbox.Add(self.sizer4)
305        self.vbox.Add(self.sizer5)
[1b43306]306        #self.vbox.Add(self.sizer6)
[a074145]307       
[c77d859]308    def set_layout(self):
309        """
[5062bbf]310        layout
[c77d859]311        """
312        self.vbox.Layout()
313        self.vbox.Fit(self) 
314        self.SetSizer(self.vbox)
315       
316        self.set_scroll()
317        self.Centre()
[5062bbf]318   
[c77d859]319    def set_scroll(self):
[5062bbf]320        """
321        """
[08ba57d]322        self.SetScrollbars(20,20,25,65)
[c77d859]323        self.Layout()   
[0a518e4c]324        self.SetAutoLayout(True)
[c77d859]325         
326    def set_owner(self,owner):
327        """
[5062bbf]328        set owner of fitpage
329       
330        :param owner: the class responsible of plotting
331       
[c77d859]332        """
333        self.event_owner = owner   
[cfc0913]334        self.state.event_owner = owner
[7609f1a]335       
[2f189dc]336    def get_data(self):
337        """
[5062bbf]338        return the current data
[2f189dc]339        """
[7609f1a]340        return self.data 
341   
[c77d859]342    def set_manager(self, manager):
343        """
[5062bbf]344        set panel manager
345       
346        :param manager: instance of plugin fitting
347       
[c77d859]348        """
349        self.manager = manager 
[cfc0913]350        self.state.manager = manager
[c77d859]351       
352    def populate_box(self, dict):
353        """
[5062bbf]354        Store list of model
355       
356        :param dict: dictionary containing list of models
357       
[c77d859]358        """
359        self.model_list_box = dict
[cfc0913]360        self.state.model_list_box = self.model_list_box
[c77d859]361       
[ffa69b6]362    def initialize_combox(self): 
363        """
[5062bbf]364        put default value in the combobox
[ffa69b6]365        """ 
366        ## fill combox box
367        if self.model_list_box is None:
368            return
369        if len(self.model_list_box)>0:
370            self._populate_box( self.formfactorbox,self.model_list_box["Shapes"])
371       
372        if len(self.model_list_box)>0:
373            self._populate_box( self.structurebox,
374                                self.model_list_box["Structure Factors"])
375            self.structurebox.Insert("None", 0,None)
376            self.structurebox.SetSelection(0)
377            self.structurebox.Hide()
378            self.text2.Hide()
379            self.structurebox.Disable()
380            self.text2.Disable()
381             
382            if self.model.__class__ in self.model_list_box["P(Q)*S(Q)"]:
383                self.structurebox.Show()
384                self.text2.Show()
385                self.structurebox.Enable()
386                self.text2.Enable()           
387               
[c77d859]388    def set_dispers_sizer(self):
389        """
[5062bbf]390        fill sizer containing dispersity info
[c77d859]391        """
392        self.sizer4.Clear(True)
[87fbc60]393        name="Polydispersity and Orientational Distribution"
394        box_description= wx.StaticBox(self, -1,name)
[c77d859]395        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
396        #----------------------------------------------------
[fa58441]397        self.disable_disp = wx.RadioButton(self, -1, 'Off', (10, 10), style=wx.RB_GROUP)
398        self.enable_disp = wx.RadioButton(self, -1, 'On', (10, 30))
[71f0373]399       
[cfc0913]400       
[c77d859]401        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.disable_disp.GetId())
402        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.enable_disp.GetId())
[ff8f99b]403        #MAC needs SetValue
404        self.disable_disp.SetValue(True)
[c77d859]405        sizer_dispersion = wx.BoxSizer(wx.HORIZONTAL)
406        sizer_dispersion.Add((20,20))
[fa58441]407        name=""#Polydispersity and \nOrientational Distribution "
[a074145]408        sizer_dispersion.Add(wx.StaticText(self,-1,name))
[c77d859]409        sizer_dispersion.Add(self.enable_disp )
410        sizer_dispersion.Add((20,20))
411        sizer_dispersion.Add(self.disable_disp )
412        sizer_dispersion.Add((10,10))
413       
414        ## fill a sizer with the combobox to select dispersion type
415        sizer_select_dispers = wx.BoxSizer(wx.HORIZONTAL) 
[fa58441]416        self.model_disp = wx.StaticText(self, -1, 'Distribution Function ')
[c77d859]417           
418        import sans.models.dispersion_models 
419        self.polydisp= sans.models.dispersion_models.models
[0a518e4c]420        self.disp_box = wx.ComboBox(self, -1)
[f20767b]421
[30d103a]422        for key, value in self.polydisp.iteritems():
423            name = str(key)
424            self.disp_box.Append(name,value)
425        self.disp_box.SetStringSelection("gaussian") 
[c77d859]426        wx.EVT_COMBOBOX(self.disp_box,-1, self._on_select_Disp) 
427             
428        sizer_select_dispers.Add((10,10)) 
429        sizer_select_dispers.Add(self.model_disp) 
[997131a]430        sizer_select_dispers.Add(self.disp_box,0,
431                wx.TOP|wx.BOTTOM|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE,border=5)
[30d103a]432     
[c77d859]433        self.model_disp.Hide()
434        self.disp_box.Hide()
435       
[997131a]436        boxsizer1.Add( sizer_dispersion,0,
437                wx.TOP|wx.BOTTOM|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE,border=5)
438        #boxsizer1.Add( (10,10) )
[c77d859]439        boxsizer1.Add( sizer_select_dispers )
440        self.sizer4_4 = wx.GridBagSizer(5,5)
441        boxsizer1.Add( self.sizer4_4  )
442        #-----------------------------------------------------
443        self.sizer4.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
[3b605bb]444        self.sizer4_4.Layout()
[c77d859]445        self.sizer4.Layout()
[3b605bb]446        self.Layout()
[08ba57d]447        self.SetScrollbars(20,20,25,65)
[3b605bb]448        self.Refresh()
[71f0373]449        ## saving the state of enable dispersity button
450        self.state.enable_disp= self.enable_disp.GetValue()
451        self.state.disable_disp= self.disable_disp.GetValue()
[5062bbf]452
[c77d859]453    def select_disp_angle(self, event): 
454        """
[5062bbf]455        Event for when a user select a parameter to average over.
456       
457        :param event: radiobutton event
458       
[c77d859]459        """
[71f0373]460        self.values=[]
461        self.weights=[]
[6e9150d]462        if event.GetEventObject()==self.noDisper_rbox:
463            if self.noDisper_rbox.GetValue():
464                #No array dispersity apply yet
465                self._reset_dispersity()
466                ## Redraw the model ???
467                self._draw_model()
[c77d859]468        # Go through the list of dispersion check boxes to identify which one has changed
469        for p in self.disp_cb_dict:
[3b9e023]470            self.state.disp_cb_dict[p]=  self.disp_cb_dict[p].GetValue()
[c77d859]471            # Catch which one of the box was just checked or unchecked.
472            if event.GetEventObject() == self.disp_cb_dict[p]:             
473                if self.disp_cb_dict[p].GetValue() == True:
[ad8f0d0]474                   
475                    ##Temp. FIX for V1.0 regarding changing checkbox to radiobutton.
[f5dadd5]476                    ##This (self._reset_dispersity) should be removed when the array dispersion is fixed.               
[ad8f0d0]477                    self._reset_dispersity()
[f5dadd5]478
[c77d859]479                    # The user wants this parameter to be averaged.
480                    # Pop up the file selection dialog.
481                    path = self._selectDlg()
482                   
483                    # If nothing was selected, just return
484                    if path is None:
485                        self.disp_cb_dict[p].SetValue(False)
[b324aa9]486                        self.noDisper_rbox.SetValue(True)
[c77d859]487                        return
[60132ef]488                    try:
489                        self._default_save_location = os.path.dirname(path)
490                    except:
491                        pass 
[c77d859]492                    try:
[71f0373]493                        self.values,self.weights = self.read_file(path)
[c77d859]494                    except:
495                        msg="Could not read input file"
496                        wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
497                        return
498                   
499                    # If any of the two arrays is empty, notify the user that we won't
500                    # proceed
[71f0373]501                    if self.values is None or self.weights is None or \
502                         self.values ==[] or self.weights ==[]:
[c77d859]503                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
504                            "The loaded %s distrubtion is corrupted or empty" % p))
505                        return
506                       
507                    # Tell the user that we are about to apply the distribution
508                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
509                            "Applying loaded %s distribution: %s" % (p, path))) 
510                   
511                    # Create the dispersion objects
512                    from sans.models.dispersion_models import ArrayDispersion
513                    disp_model = ArrayDispersion()
[71f0373]514                    disp_model.set_weights(self.values, self.weights)
515                   
[c77d859]516                    # Store the object to make it persist outside the scope of this method
517                    #TODO: refactor model to clean this up?
518                    self._disp_obj_dict[p] = disp_model
[dad49a0]519                    self.state._disp_obj_dict [p]= disp_model
520                    self.state.values=[]
521                    self.state.weights=[]
[3b9e023]522                    self.state.values = copy.deepcopy(self.values)
523                    self.state.weights = copy.deepcopy(self.weights)
[c77d859]524                    # Set the new model as the dispersion object for the selected parameter
525                    self.model.set_dispersion(p, disp_model)
[9e6c27f]526                    # Store a reference to the weights in the model object so that
527                    # it's not lost when we use the model within another thread.
528                    #TODO: total hack - fix this
[71f0373]529                    self.state.model= self.model.clone()
[7975f2b]530
[0aeabc6]531                    self.model._persistency_dict = {}
[71f0373]532                    self.model._persistency_dict[p] = [self.values, self.weights]
533                    self.state.model._persistency_dict[p] = [self.values, self.weights]
[c77d859]534                else:
535                    self._reset_dispersity()
[dad49a0]536             
[6e9150d]537                ## Redraw the model
[c77d859]538                self._draw_model()
[3b9e023]539       
540        ## post state to fit panel
541        event = PageInfoEvent(page = self)
542        wx.PostEvent(self.parent, event)
543       
[a074145]544   
545    def onResetModel(self, event):
546        """
[5062bbf]547        Reset model state
[a074145]548        """
549        ## post help message for the selected model
[1b69256]550        msg = self.popUpMenu.GetHelpString(event.GetId())
[a074145]551        msg +=" reloaded"
552        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
553       
[1b69256]554        name= self.popUpMenu.GetLabel(event.GetId())
[f20767b]555        self._on_select_model_helper()
556       
[a074145]557        if name in self.saved_states.keys():
558            previous_state = self.saved_states[name]
[f20767b]559            ## reset state of checkbox,textcrtl  and  regular parameters value
560            self.reset_page(previous_state)     
[9bc499b6]561         
562    def on_save_state(self, event):   
563        """
[5062bbf]564        Save the current state into file
[bb70474]565        """ 
566        self.save_current_state()
567        new_state = self.state.clone()
568        # Ask the user the location of the file to write to.
569        path = None
570        dlg = wx.FileDialog(self, "Choose a file", self._default_save_location,
571                                                 "", "*.fitv", wx.SAVE)
572        if dlg.ShowModal() == wx.ID_OK:
573            path = dlg.GetPath()
574            self._default_save_location = os.path.dirname(path)
575        else:
576            return None
577        #the manager write the state into file
578        self.manager.save_fit_state(filepath=path, fitstate=new_state)
579        return new_state 
580     
[9bc499b6]581    def on_bookmark(self, event):
[00c3aac]582        """
[5062bbf]583        save history of the data and model
[00c3aac]584        """
[a074145]585        if self.model==None:
[4470b10]586            msg="Can not bookmark; Please select Data and Model first..."
587            wx.MessageBox(msg, 'Info')
[a074145]588            return 
589        if hasattr(self,"enable_disp"):
[fc6ea43]590            self.state.enable_disp = copy.deepcopy(self.enable_disp.GetValue())
[a074145]591        if hasattr(self, "disp_box"):
[fc6ea43]592            self.state.disp_box = copy.deepcopy(self.disp_box.GetSelection())
[edd166b]593
[f20767b]594        self.state.model.name= self.model.name
[c99a6c5]595       
596        #Remember fit engine_type for fit panel
[edd166b]597        if self.engine_type == None: 
598            self.engine_type = "scipy"
599        if self.manager !=None:
600            self.manager._on_change_engine(engine=self.engine_type)
[c99a6c5]601       
[edd166b]602            self.state.engine_type = self.engine_type
[b421b1a]603
[a074145]604        new_state = self.state.clone()
[f20767b]605        new_state.model.name = self.state.model.name
606       
[c477b31]607        new_state.enable2D = copy.deepcopy(self.enable2D)
[a074145]608        ##Add model state on context menu
609        self.number_saved_state += 1
[cd57979a]610        #name= self.model.name+"[%g]"%self.number_saved_state
611        name= self.model.__class__.__name__+"[%g]"%self.number_saved_state
[a074145]612        self.saved_states[name]= new_state
613       
614        ## Add item in the context menu
[fc6ea43]615       
616        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
617        my_time= str(hour)+" : "+str(minute)+" : "+str(second)+" "
[a074145]618        date= str( month)+"|"+str(day)+"|"+str(year)
619        msg=  "Model saved at %s on %s"%(my_time, date)
620         ## post help message for the selected model
621        msg +=" Saved! right click on this page to retrieve this model"
622        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
623       
624        id = wx.NewId()
[1b69256]625        self.popUpMenu.Append(id,name,str(msg))
[a074145]626        wx.EVT_MENU(self, id, self.onResetModel)
627       
[1328e03]628    def onSetFocus(self, evt):
[77e23a2]629        """
[5062bbf]630        highlight the current textcrtl and hide the error text control shown
631        after fitting
[77e23a2]632        """
[1328e03]633        return
[c77d859]634   
635    def read_file(self, path):
636        """
[5062bbf]637        Read two columns file
638       
639        :param path: the path to the file to read
640       
[c77d859]641        """
642        try:
643            if path==None:
644                wx.PostEvent(self.parent.parent, StatusEvent(status=\
645                            " Selected Distribution was not loaded: %s"%path))
646                return None, None
647            input_f = open(path, 'r')
648            buff = input_f.read()
649            lines = buff.split('\n')
650           
651            angles = []
652            weights=[]
653            for line in lines:
654                toks = line.split()
[502de0a]655                try:
656                    angle = float(toks[0])
657                    weight = float(toks[1])
658                except:
659                    # Skip non-data lines
660                    pass
661                angles.append(angle)
662                weights.append(weight)
[c77d859]663            return numpy.array(angles), numpy.array(weights)
664        except:
665            raise 
[5062bbf]666
[cfc0913]667    def createMemento(self):
668        """
[5062bbf]669        return the current state of the page
[cfc0913]670        """
671        return self.state.clone()
672   
673   
674    def save_current_state(self):
675        """
[5062bbf]676        Store current state
[cfc0913]677        """
[0aeabc6]678        ## save model option
[87fbc60]679        if self.model!= None:
[71f0373]680            self.disp_list= self.model.getDispParamList()
681            self.state.disp_list= copy.deepcopy(self.disp_list)
[87fbc60]682            self.state.model = self.model.clone()
[c99a6c5]683
[c477b31]684        self.state.enable2D = copy.deepcopy(self.enable2D)
[71f0373]685        self.state.values= copy.deepcopy(self.values)
686        self.state.weights = copy.deepcopy( self.weights)
[0aeabc6]687        ## save data   
[240b9966]688        self.state.data= copy.deepcopy(self.data)
[70c57ebf]689        try:
690            n = self.disp_box.GetCurrentSelection()
691            dispersity= self.disp_box.GetClientData(n)
692            name= dispersity.__name__
[f20767b]693            self.disp_name = name
694            if name == "GaussianDispersion" :
[70c57ebf]695               if hasattr(self,"cb1"):
696                   self.state.cb1= self.cb1.GetValue()
697        except:
698            pass
699       
[cfc0913]700        if hasattr(self,"enable_disp"):
701            self.state.enable_disp= self.enable_disp.GetValue()
[fc6ea43]702            self.state.disable_disp = self.disable_disp.GetValue()
703           
[3370922]704        self.state.smearer = copy.deepcopy(self.smearer)
[cfc0913]705        if hasattr(self,"enable_smearer"):
[3370922]706            self.state.enable_smearer = copy.deepcopy(self.enable_smearer.GetValue())
[fc6ea43]707            self.state.disable_smearer = copy.deepcopy(self.disable_smearer.GetValue())
[7609f1a]708
709        self.state.pinhole_smearer = copy.deepcopy(self.pinhole_smearer.GetValue())
710        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 
711                 
[b787e68c]712        if hasattr(self,"disp_box"):
713            self.state.disp_box = self.disp_box.GetCurrentSelection()
[f20767b]714
[c477b31]715            if len(self.disp_cb_dict)>0:
716                for k , v in self.disp_cb_dict.iteritems():
[f20767b]717         
[c477b31]718                    if v ==None :
719                        self.state.disp_cb_dict[k]= v
720                    else:
721                        try:
722                            self.state.disp_cb_dict[k]=v.GetValue()
723                        except:
724                            self.state.disp_cb_dict[k]= None
725           
726            if len(self._disp_obj_dict)>0:
727                for k , v in self._disp_obj_dict.iteritems():
[f20767b]728     
[c477b31]729                    self.state._disp_obj_dict[k]= v
[f20767b]730                       
731           
[71f0373]732            self.state.values = copy.deepcopy(self.values)
733            self.state.weights = copy.deepcopy(self.weights)
[0aeabc6]734        ## save plotting range
[b787e68c]735        self._save_plotting_range()
[d2d0cfdf]736       
737        self.state.orientation_params =[]
738        self.state.orientation_params_disp =[]
739        self.state.parameters =[]
740        self.state.fittable_param =[]
741        self.state.fixed_param =[]
[f20767b]742
[d2d0cfdf]743       
[cfc0913]744        ## save checkbutton state and txtcrtl values
[fc6ea43]745        self._copy_parameters_state(self.orientation_params,
746                                     self.state.orientation_params)
747        self._copy_parameters_state(self.orientation_params_disp,
748                                     self.state.orientation_params_disp)
[f20767b]749       
[d2d0cfdf]750        self._copy_parameters_state(self.parameters, self.state.parameters)
751        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
752        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
[cfc0913]753   
[52cac46]754
755    def save_current_state_fit(self):
756        """
[5062bbf]757        Store current state for fit_page
[52cac46]758        """
759        ## save model option
760        if self.model!= None:
761            self.disp_list= self.model.getDispParamList()
762            self.state.disp_list= copy.deepcopy(self.disp_list)
763            self.state.model = self.model.clone()
[9bc499b6]764        if hasattr(self, "engine_type"):
765            self.state.engine_type = copy.deepcopy(self.engine_type)
766           
[52cac46]767        self.state.enable2D = copy.deepcopy(self.enable2D)
768        self.state.values= copy.deepcopy(self.values)
769        self.state.weights = copy.deepcopy( self.weights)
770        ## save data   
771        self.state.data= copy.deepcopy(self.data)
772        try:
773            n = self.disp_box.GetCurrentSelection()
774            dispersity= self.disp_box.GetClientData(n)
775            name= dispersity.__name__
776            self.disp_name = name
777            if name == "GaussianDispersion" :
778               if hasattr(self,"cb1"):
779                   self.state.cb1= self.cb1.GetValue()
[b421b1a]780
[52cac46]781        except:
782            pass
783       
784        if hasattr(self,"enable_disp"):
785            self.state.enable_disp= self.enable_disp.GetValue()
786            self.state.disable_disp = self.disable_disp.GetValue()
787           
788        self.state.smearer = copy.deepcopy(self.smearer)
789        if hasattr(self,"enable_smearer"):
790            self.state.enable_smearer = copy.deepcopy(self.enable_smearer.GetValue())
791            self.state.disable_smearer = copy.deepcopy(self.disable_smearer.GetValue())
792           
[7609f1a]793        self.state.pinhole_smearer = copy.deepcopy(self.pinhole_smearer.GetValue())
794        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 
795           
[52cac46]796        if hasattr(self,"disp_box"):
797            self.state.disp_box = self.disp_box.GetCurrentSelection()
798
799            if len(self.disp_cb_dict)>0:
800                for k , v in self.disp_cb_dict.iteritems():
801         
802                    if v ==None :
803                        self.state.disp_cb_dict[k]= v
804                    else:
805                        try:
806                            self.state.disp_cb_dict[k]=v.GetValue()
807                        except:
808                            self.state.disp_cb_dict[k]= None
809           
810            if len(self._disp_obj_dict)>0:
811                for k , v in self._disp_obj_dict.iteritems():
812     
813                    self.state._disp_obj_dict[k]= v
814                       
815           
816            self.state.values = copy.deepcopy(self.values)
817            self.state.weights = copy.deepcopy(self.weights)
[b421b1a]818           
[52cac46]819        ## save plotting range
820        self._save_plotting_range()
821       
822        ## save checkbutton state and txtcrtl values
823        self._copy_parameters_state(self.orientation_params,
824                                     self.state.orientation_params)
825        self._copy_parameters_state(self.orientation_params_disp,
826                                     self.state.orientation_params_disp)
827        self._copy_parameters_state(self.parameters, self.state.parameters)
828        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
829        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
[a074145]830   
[ffa69b6]831         
832    def check_invalid_panel(self): 
833        """
[5062bbf]834        check if the user can already perform some action with this panel
[ffa69b6]835        """ 
836        flag = False
[4470b10]837        if self.data is None:
838            self.disable_smearer.SetValue(True)
839            self.disable_disp.SetValue(True)
840            msg = "Please load Data and select Model to start..."
[ffa69b6]841            wx.MessageBox(msg, 'Info')
842            return  True
[5062bbf]843       
[240b9966]844    def reset_page_helper(self, state):
[cfc0913]845        """
[5062bbf]846        Use page_state and change the state of existing page
847       
848        :precondition: the page is already drawn or created
849       
850        :postcondition: the state of the underlying data change as well as the
[71f0373]851            state of the graphic interface
[cfc0913]852        """
[330573d]853        if state ==None:
[3a37fe0]854            #self._undo.Enable(False)
[330573d]855            return 
[f20767b]856       
[0aeabc6]857        self.model= state.model
858        self.data = state.data
[5582a9f1]859        if self.data !=None:
860            from DataLoader.qsmearing import smear_selection
[9bc499b6]861            self.smearer= smear_selection(self.data)
[c477b31]862        self.enable2D= state.enable2D
[c99a6c5]863        self.engine_type = state.engine_type
[edd166b]864
[f20767b]865        self.disp_cb_dict = state.disp_cb_dict
[b421b1a]866        self.disp_list = state.disp_list
[f20767b]867
[240b9966]868        ## set the state of the radio box
869        self.shape_rbutton.SetValue(state.shape_rbutton )
870        self.shape_indep_rbutton.SetValue(state.shape_indep_rbutton)
871        self.struct_rbutton.SetValue(state.struct_rbutton )
872        self.plugin_rbutton.SetValue(state.plugin_rbutton)
[71f0373]873        ##draw sizer containing model parameters value for the current model
874        self._set_model_sizer_selection( self.model )
875        self.set_model_param_sizer(self.model)
[edd166b]876
[240b9966]877        ## reset value of combox box
878        self.structurebox.SetSelection(state.structurecombobox )
879        self.formfactorbox.SetSelection(state.formfactorcombobox)
[f20767b]880       
881       
[71f0373]882        ## enable the view 2d button if this is a modelpage type
[c477b31]883        if hasattr(self,"model_view"):
[f20767b]884            if self.enable2D:
[c477b31]885                self.model_view.Disable()
[f20767b]886            else:
887                self.model_view.Enable()
[71f0373]888        ## set the select all check box to the a given state
[998b6b8]889        if hasattr(self, "cb1"):   
[71f0373]890            self.cb1.SetValue(state.cb1)
[edd166b]891     
[71f0373]892        ## reset state of checkbox,textcrtl  and  regular parameters value
[f20767b]893           
[71f0373]894        self._reset_parameters_state(self.orientation_params_disp,
895                                     state.orientation_params_disp)
896        self._reset_parameters_state(self.orientation_params,
897                                     state.orientation_params)
898        self._reset_parameters_state(self.parameters,state.parameters)   
[f20767b]899         ## display dispersion info layer       
[0aeabc6]900        self.enable_disp.SetValue(state.enable_disp)
901        self.disable_disp.SetValue(state.disable_disp)
[edd166b]902       
[b787e68c]903        if hasattr(self, "disp_box"):
[f20767b]904           
[3b9e023]905            self.disp_box.SetSelection(state.disp_box) 
906            n= self.disp_box.GetCurrentSelection()
907            dispersity= self.disp_box.GetClientData(n)
[f20767b]908            name= dispersity.__name__     
909
[3b9e023]910            self._set_dipers_Param(event=None)
[5582a9f1]911       
[3b9e023]912            if name=="ArrayDispersion":
[f20767b]913               
[3b9e023]914                for item in self.disp_cb_dict.keys():
[f20767b]915                   
916                    if hasattr(self.disp_cb_dict[item],"SetValue") :
917                        self.disp_cb_dict[item].SetValue(state.disp_cb_dict[item])
918                        # Create the dispersion objects
919                        from sans.models.dispersion_models import ArrayDispersion
920                        disp_model = ArrayDispersion()
921                        if hasattr(state,"values")and self.disp_cb_dict[item].GetValue()==True:
922                            if len(state.values)>0:
923                                self.values=state.values
924                                self.weights=state.weights
925                                disp_model.set_weights(self.values, state.weights)
926                            else:
927                                self._reset_dispersity()
928                       
929                        self._disp_obj_dict[item] = disp_model
930                        # Set the new model as the dispersion object for the selected parameter
931                        self.model.set_dispersion(item, disp_model)
932                   
933                        self.model._persistency_dict[item] = [state.values, state.weights]
[3b9e023]934                   
935            else:
[f1aa385]936                keys = self.model.getParamList()
937                for item in keys:
938                    if item in self.disp_list and not self.model.details.has_key(item):
939                        self.model.details[item]=["",None,None]
[f20767b]940                for k,v in self.state.disp_cb_dict.iteritems():
941                    self.disp_cb_dict = copy.deepcopy(state.disp_cb_dict) 
942                    self.state.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
[edd166b]943
[3370922]944        ##plotting range restore   
[0aeabc6]945        self._reset_plotting_range(state)
[edd166b]946
[b787e68c]947        ## smearing info  restore
[cfc0913]948        if hasattr(self,"enable_smearer"):
[3370922]949            ## set smearing value whether or not the data contain the smearing info
[0aeabc6]950            self.enable_smearer.SetValue(state.enable_smearer)
951            self.disable_smearer.SetValue(state.disable_smearer)
[edd166b]952            self.onSmear(event=None)           
[7609f1a]953        self.pinhole_smearer.SetValue(state.pinhole_smearer)
954        self.slit_smearer.SetValue(state.slit_smearer)
955        ## we have two more options for smearing
956        if self.pinhole_smearer.GetValue(): self.onPinholeSmear(event=None)
957        elif self.slit_smearer.GetValue(): self.onSlitSmear(event=None)
[5582a9f1]958       
[71f0373]959        ## reset state of checkbox,textcrtl  and dispersity parameters value
[d2d0cfdf]960        self._reset_parameters_state(self.fittable_param,state.fittable_param)
961        self._reset_parameters_state(self.fixed_param,state.fixed_param)
[edd166b]962       
[dad49a0]963        ## draw the model with previous parameters value
[c477b31]964        self._onparamEnter_helper()
[65b77529]965       
[d2d0cfdf]966        ## reset context menu items
967        self._reset_context_menu()
[5582a9f1]968   
[0aeabc6]969        ## set the value of the current state to the state given as parameter
970        self.state = state.clone() 
[f20767b]971        self._draw_model()
[c99a6c5]972
[c77d859]973    def _selectDlg(self):
974        """
[5062bbf]975        open a dialog file to selected the customized dispersity
[c77d859]976        """
977        import os
[60132ef]978        dlg = wx.FileDialog(self, "Choose a weight file",
979                                self._default_save_location , "", "*.*", wx.OPEN)
[c77d859]980        path = None
981        if dlg.ShowModal() == wx.ID_OK:
982            path = dlg.GetPath()
983        dlg.Destroy()
984        return path
[5062bbf]985
[a074145]986    def _reset_context_menu(self):
987        """
[5062bbf]988        reset the context menu
[a074145]989        """
990        for name, state in self.state.saved_states.iteritems():
991            self.number_saved_state += 1
992            ## Add item in the context menu
993            id = wx.NewId()
[1b69256]994            self.popUpMenu.Append(id,name, 'Save model and state %g'%self.number_saved_state)
[a074145]995            wx.EVT_MENU(self, id, self.onResetModel)
996   
[0aeabc6]997    def _reset_plotting_range(self, state):
[cfc0913]998        """
[5062bbf]999        Reset the plotting range to a given state
[cfc0913]1000        """
[ffa69b6]1001        if self.check_invalid_panel():
1002            return
[0aeabc6]1003        self.qmin.SetValue(str(state.qmin))
1004        self.qmax.SetValue(str(state.qmax)) 
[cfc0913]1005        if self.state.npts!=None:
[0aeabc6]1006            self.npts.SetValue(str(state.npts)) 
[cfc0913]1007           
[240b9966]1008    def _save_typeOfmodel(self):
1009        """
[5062bbf]1010        save radiobutton containing the type model that can be selected
[240b9966]1011        """
1012        self.state.shape_rbutton = self.shape_rbutton.GetValue()
1013        self.state.shape_indep_rbutton = self.shape_indep_rbutton.GetValue()
1014        self.state.struct_rbutton = self.struct_rbutton.GetValue()
1015        self.state.plugin_rbutton = self.plugin_rbutton.GetValue()
[3595309d]1016        self.state.structurebox= self.structurebox.GetCurrentSelection()
1017        self.state.formfactorbox = self.formfactorbox.GetCurrentSelection()
[c99a6c5]1018       
[3a37fe0]1019        #self._undo.Enable(True)
[240b9966]1020        ## post state to fit panel
1021        event = PageInfoEvent(page = self)
1022        wx.PostEvent(self.parent, event)
[3595309d]1023       
[cfc0913]1024    def _save_plotting_range(self ):
1025        """
[5062bbf]1026        save the state of plotting range
[cfc0913]1027        """
[b787e68c]1028        self.state.qmin = self.qmin_x
1029        self.state.qmax = self.qmax_x
[cfc0913]1030        if self.npts!=None:
[b787e68c]1031            self.state.npts= self.num_points
[cfc0913]1032           
1033           
[c77d859]1034    def _onparamEnter_helper(self):
1035        """
[5062bbf]1036        check if values entered by the user are changed and valid to replot
1037        model
[c77d859]1038        """
[51a71a3]1039        # Flag to register when a parameter has changed.   
[7975f2b]1040        is_modified = False
[51a71a3]1041        self.fitrange =True
1042        is_2Ddata = False
[3a37fe0]1043        #self._undo.Enable(True)
[51a71a3]1044        # check if 2d data
[6318298]1045        if self.data.__class__.__name__ =="Data2D":
[51a71a3]1046            is_2Ddata = True
[c77d859]1047        if self.model !=None:
[edd166b]1048            try:
1049                is_modified =self._check_value_enter( self.fittable_param ,is_modified)
1050                is_modified =self._check_value_enter( self.fixed_param ,is_modified)
1051                is_modified =self._check_value_enter( self.parameters ,is_modified) 
1052            except:
1053                pass
1054            #if is_modified:
[c99a6c5]1055
[c77d859]1056            # Here we should check whether the boundaries have been modified.
1057            # If qmin and qmax have been modified, update qmin and qmax and
1058            # set the is_modified flag to True
[85b3971]1059            if self._validate_qrange(self.qmin, self.qmax):
[7975f2b]1060                tempmin = float(self.qmin.GetValue())
1061                if tempmin != self.qmin_x:
1062                    self.qmin_x = tempmin
[c77d859]1063                    is_modified = True
[7975f2b]1064                tempmax = float(self.qmax.GetValue())
1065                if tempmax != self.qmax_x:
1066                    self.qmax_x = tempmax
[c77d859]1067                    is_modified = True
[b787e68c]1068           
[51a71a3]1069                if is_2Ddata:
1070                    # set mask   
1071                    is_modified = self._validate_Npts()
[247cb58]1072                   
[51a71a3]1073            else:
1074                self.fitrange = False   
1075
[c77d859]1076            ## if any value is modify draw model with new value
[51a71a3]1077            if not self.fitrange:
[247cb58]1078                #self.btFit.Disable()
[51a71a3]1079                if is_2Ddata: self.btEditMask.Disable()
1080            else:
[247cb58]1081                #self.btFit.Enable(True)
[51a71a3]1082                if is_2Ddata: self.btEditMask.Enable(True)
1083
1084            if is_modified and self.fitrange:
[240b9966]1085                self.state_change= True
[c77d859]1086                self._draw_model() 
[7975f2b]1087                self.Refresh()
1088        return is_modified
1089   
[35c9d31]1090    def _update_paramv_on_fit(self):
1091        """
[5062bbf]1092        make sure that update param values just before the fitting
[35c9d31]1093        """
1094        #flag for qmin qmax check values
[7609f1a]1095        flag = True
[51a71a3]1096        self.fitrange = True
[35c9d31]1097        is_modified = False
[51a71a3]1098
[4fbc93e]1099        wx.PostEvent(self.manager.parent, StatusEvent(status=" \
1100        updating ... ",type="update"))
1101
[35c9d31]1102        ##So make sure that update param values on_Fit.
1103        #self._undo.Enable(True)
1104        if self.model !=None:           
1105            ##Check the values
1106            self._check_value_enter( self.fittable_param ,is_modified)
1107            self._check_value_enter( self.fixed_param ,is_modified)
[edd166b]1108            self._check_value_enter( self.parameters ,is_modified)
[35c9d31]1109
1110            # If qmin and qmax have been modified, update qmin and qmax and
[7975f2b]1111             # Here we should check whether the boundaries have been modified.
1112            # If qmin and qmax have been modified, update qmin and qmax and
1113            # set the is_modified flag to True
[51a71a3]1114            self.fitrange = self._validate_qrange(self.qmin, self.qmax)
1115            if self.fitrange:
[7975f2b]1116                tempmin = float(self.qmin.GetValue())
1117                if tempmin != self.qmin_x:
1118                    self.qmin_x = tempmin
1119                tempmax = float(self.qmax.GetValue())
1120                if tempmax != self.qmax_x:
1121                    self.qmax_x = tempmax
[7609f1a]1122                if tempmax == tempmin:
1123                    flag = False   
1124                temp_smearer = None
1125                if not self.disable_smearer.GetValue():
1126                    temp_smearer= self.current_smearer
1127                    if self.slit_smearer.GetValue():
1128                        flag = self.update_slit_smear()
1129                    elif self.pinhole_smearer.GetValue():
1130                        flag = self.update_pinhole_smear()
1131                    else:
[f72333f]1132                        self.manager.set_smearer_nodraw(smearer=temp_smearer, qmin= float(self.qmin_x),
[7609f1a]1133                                                 qmax= float(self.qmax_x))
[4fbc93e]1134                elif not self._is_2D():
[7609f1a]1135                    self.manager.set_smearer(smearer=temp_smearer, qmin= float(self.qmin_x),
1136                                                 qmax= float(self.qmax_x))
[51a71a3]1137                    index_data = ((self.qmin_x <= self.data.x)&(self.data.x <= self.qmax_x))
1138                    self.Npts_fit.SetValue(str(len(self.data.x[index_data==True])))
1139                    flag = True
[4fbc93e]1140                if self._is_2D():
[51a71a3]1141                    # only 2D case set mask   
1142                    flag = self._validate_Npts()
1143                    if not flag:
1144                        return flag
[7609f1a]1145            else: flag = False
1146        else: 
[7975f2b]1147            flag = False
[51a71a3]1148
1149        #For invalid q range, disable the mask editor and fit button, vs.   
1150        if not self.fitrange:
[247cb58]1151            #self.btFit.Disable()
[4fbc93e]1152            if self._is_2D():self.btEditMask.Disable()
[51a71a3]1153        else:
[247cb58]1154            #self.btFit.Enable(True)
[4fbc93e]1155            if self._is_2D():self.btEditMask.Enable(True)
[51a71a3]1156
[7609f1a]1157        if not flag:
[51a71a3]1158            msg= "Cannot Plot or Fit :Must select a model or Fitting range is not valid!!!  "
[7609f1a]1159            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
[51a71a3]1160       
[7609f1a]1161        self.save_current_state()
[4470b10]1162   
[35c9d31]1163        return flag                           
[acd0bda3]1164               
[c99a6c5]1165    def _is_modified(self, is_modified):
[acd0bda3]1166        """
[5062bbf]1167        return to self._is_modified
[acd0bda3]1168        """
[c99a6c5]1169        return is_modified
[acd0bda3]1170                       
[cfc0913]1171    def _reset_parameters_state(self, listtorestore,statelist):
1172        """
[5062bbf]1173        Reset the parameters at the given state
[cfc0913]1174        """
[6999659]1175        if len(statelist)==0 or  len(listtorestore)==0 :
1176            return
1177        if len(statelist)!=  len(listtorestore) :
[cfc0913]1178            return
[c99a6c5]1179
[cfc0913]1180        for j in range(len(listtorestore)):
1181            item_page = listtorestore[j]
1182            item_page_info = statelist[j]
1183            ##change the state of the check box for simple parameters
[b421b1a]1184            if item_page[0]!=None:               
[cfc0913]1185                item_page[0].SetValue(item_page_info[0])
[b421b1a]1186               
[cfc0913]1187            if item_page[2]!=None:
1188                item_page[2].SetValue(item_page_info[2])
1189               
1190            if item_page[3]!=None:
1191                ## show or hide text +/-
1192                if item_page_info[2]:
1193                    item_page[3].Show(True)
1194                else:
1195                    item_page[3].Hide()
1196            if item_page[4]!=None:
1197                ## show of hide the text crtl for fitting error
1198                if item_page_info[4][0]:
1199                    item_page[4].Show(True)
1200                    item_page[4].SetValue(item_page_info[4][1])
1201                else:
1202                    item_page[3].Hide()
1203            if item_page[5]!=None:
1204                ## show of hide the text crtl for fitting error
1205                if item_page_info[5][0]:
1206                    item_page[5].Show(True)
[b421b1a]1207                    item_page[5].SetValue(item_page_info[5][1])
[cfc0913]1208                else:
1209                    item_page[5].Hide()
1210                   
1211            if item_page[6]!=None:
1212                ## show of hide the text crtl for fitting error
1213                if item_page_info[6][0]:
1214                    item_page[6].Show(True)
1215                    item_page[6].SetValue(item_page_info[6][1])
1216                else:
1217                    item_page[6].Hide()
[5062bbf]1218                                     
[cfc0913]1219    def _copy_parameters_state(self, listtocopy, statelist):
1220        """
[5062bbf]1221        copy the state of button
1222       
1223        :param listtocopy: the list of check button to copy
1224        :param statelist: list of state object to store the current state
1225       
[cfc0913]1226        """
1227        if len(listtocopy)==0:
1228            return
[1c1436d]1229       
[cfc0913]1230        for item in listtocopy:
[f20767b]1231 
[cfc0913]1232            checkbox_state = None
1233            if item[0]!= None:
1234                checkbox_state= item[0].GetValue()
1235            parameter_name = item[1]
1236            parameter_value = None
1237            if item[2]!=None:
1238                parameter_value = item[2].GetValue()
1239            static_text = None
1240            if item[3]!=None:
1241                static_text = item[3].IsShown()
1242            error_value = None
1243            error_state = None
1244            if item[4]!= None:
1245                error_value = item[4].GetValue()
1246                error_state = item[4].IsShown()
1247               
1248            min_value = None
1249            min_state = None
1250            if item[5]!= None:
1251                min_value = item[5].GetValue()
1252                min_state = item[5].IsShown()
1253               
1254            max_value = None
1255            max_state = None
1256            if item[6]!= None:
1257                max_value = item[6].GetValue()
1258                max_state = item[6].IsShown()
[240b9966]1259            unit=None
1260            if item[7]!=None:
1261                unit = item[7].GetLabel()
[cfc0913]1262               
1263            statelist.append([checkbox_state, parameter_name, parameter_value,
1264                              static_text ,[error_state,error_value],
[240b9966]1265                                [min_state,min_value],[max_state , max_value],unit])
[cfc0913]1266           
[c77d859]1267    def _set_model_sizer_selection(self, model):
1268        """
[5062bbf]1269        Display the sizer according to the type of the current model
[c77d859]1270        """
[5062bbf]1271        if model == None:
[70c57ebf]1272            return
[72f719b]1273        if hasattr(model ,"s_model"):
[c77d859]1274           
[72f719b]1275            class_name= model.s_model.__class__
1276            name= model.s_model.name
[c77d859]1277            flag= name != "NoStructure"
1278            if flag and (class_name in self.model_list_box["Structure Factors"]):
[6dc9ad8]1279                self.structurebox.Show()
1280                self.text2.Show()               
[3b605bb]1281                self.structurebox.Enable()
[c097f02]1282                self.text2.Enable()
[c77d859]1283                items = self.structurebox.GetItems()
1284                self.sizer1.Layout()
[08ba57d]1285                self.SetScrollbars(20,20,25,65)
[c77d859]1286                for i in range(len(items)):
1287                    if items[i]== str(name):
1288                        self.structurebox.SetSelection(i)
1289                        break
1290                   
[72f719b]1291        if hasattr(model ,"p_model"):
1292            class_name = model.p_model.__class__
1293            name = model.p_model.name
[c77d859]1294            self.formfactorbox.Clear()
1295           
1296            for k, list in self.model_list_box.iteritems():
[376916c]1297                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
[c77d859]1298                    self.shape_rbutton.SetValue(True)
[376916c]1299                    ## fill the form factor list with new model
1300                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
1301                    items = self.formfactorbox.GetItems()
1302                    ## set comboxbox to the selected item
1303                    for i in range(len(items)):
1304                        if items[i]== str(name):
1305                            self.formfactorbox.SetSelection(i)
1306                            break
1307                    return
1308                elif k == "Shape-Independent":
[c77d859]1309                    self.shape_indep_rbutton.SetValue(True)
1310                elif k == "Structure Factors":
1311                     self.struct_rbutton.SetValue(True)
1312                else:
1313                    self.plugin_rbutton.SetValue(True)
[376916c]1314               
[c77d859]1315                if class_name in list:
1316                    ## fill the form factor list with new model
1317                    self._populate_box(self.formfactorbox, list)
1318                    items = self.formfactorbox.GetItems()
1319                    ## set comboxbox to the selected item
1320                    for i in range(len(items)):
1321                        if items[i]== str(name):
1322                            self.formfactorbox.SetSelection(i)
1323                            break
1324                    break
1325        else:
[cdbe88e]1326
1327            ## Select the model from the menu
[c77d859]1328            class_name = model.__class__
1329            name = model.name
1330            self.formfactorbox.Clear()
1331            items = self.formfactorbox.GetItems()
[376916c]1332   
[cdbe88e]1333            for k, list in self.model_list_box.iteritems():         
[376916c]1334                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
[3b605bb]1335                    if class_name in self.model_list_box["P(Q)*S(Q)"]:
[6dc9ad8]1336                        self.structurebox.Show()
1337                        self.text2.Show()
[3b605bb]1338                        self.structurebox.Enable()
[cdbe88e]1339                        self.structurebox.SetSelection(0)
[c097f02]1340                        self.text2.Enable()
[3b605bb]1341                    else:
[6dc9ad8]1342                        self.structurebox.Hide()
1343                        self.text2.Hide()
[3b605bb]1344                        self.structurebox.Disable()
1345                        self.structurebox.SetSelection(0)
[c097f02]1346                        self.text2.Disable()
[3b605bb]1347                       
[c77d859]1348                    self.shape_rbutton.SetValue(True)
[376916c]1349                    ## fill the form factor list with new model
1350                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
1351                    items = self.formfactorbox.GetItems()
1352                    ## set comboxbox to the selected item
1353                    for i in range(len(items)):
1354                        if items[i]== str(name):
1355                            self.formfactorbox.SetSelection(i)
1356                            break
1357                    return
1358                elif k == "Shape-Independent":
[c77d859]1359                    self.shape_indep_rbutton.SetValue(True)
1360                elif k == "Structure Factors":
[cdbe88e]1361                    self.struct_rbutton.SetValue(True)
[c77d859]1362                else:
1363                    self.plugin_rbutton.SetValue(True)
1364                if class_name in list:
[3b605bb]1365                    self.structurebox.SetSelection(0)
1366                    self.structurebox.Disable()
[c097f02]1367                    self.text2.Disable()                   
[376916c]1368                    ## fill the form factor list with new model
[c77d859]1369                    self._populate_box(self.formfactorbox, list)
1370                    items = self.formfactorbox.GetItems()
1371                    ## set comboxbox to the selected item
1372                    for i in range(len(items)):
1373                        if items[i]== str(name):
1374                            self.formfactorbox.SetSelection(i)
1375                            break
1376                    break
[1467e1a6]1377   
[c77d859]1378    def _draw_model(self):
1379        """
[5062bbf]1380        Method to draw or refresh a plotted model.
1381        The method will use the data member from the model page
1382        to build a call to the fitting perspective manager.
[c77d859]1383        """
[ffa69b6]1384        if self.check_invalid_panel():
1385            return
[c77d859]1386        if self.model !=None:
[fca9cbd9]1387            temp_smear=None
1388            if hasattr(self, "enable_smearer"):
[7609f1a]1389                if not self.disable_smearer.GetValue():
1390                    temp_smear= self.current_smearer
[484faf7]1391           
[f72333f]1392            self.manager.draw_model(self.model, 
1393                                    data=self.data,
[c16557c]1394                                    smearer= temp_smear,
[484faf7]1395                                    qmin=float(self.qmin_x), 
1396                                    qmax=float(self.qmax_x),
[4e6b5939]1397                                    qstep= float(self.num_points),
[f72333f]1398                                    enable2D=self.enable2D)
[71f0373]1399       
[ff8f99b]1400    def _set_model_sizer(self,sizer, box_sizer, title="", object=None):
[c77d859]1401        """
[5062bbf]1402        Use lists to fill a sizer for model info
[c77d859]1403        """
1404       
1405        sizer.Clear(True)
[ff8f99b]1406        ##For MAC, this should defined here.
1407        if box_sizer == None:
[acd0bda3]1408            box_description= wx.StaticBox(self, -1,str(title))
1409            boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
[ff8f99b]1410        else:
1411            boxsizer1 = box_sizer
1412           
[c77d859]1413        #--------------------------------------------------------
[376916c]1414        self.shape_rbutton = wx.RadioButton(self, -1, 'Shapes', style=wx.RB_GROUP)
1415        self.shape_indep_rbutton = wx.RadioButton(self, -1, "Shape-Independent")
1416        self.struct_rbutton = wx.RadioButton(self, -1, "Structure Factor ")
1417        self.plugin_rbutton = wx.RadioButton(self, -1, "Customized Models")
[7ad6ff5]1418               
[c77d859]1419        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
1420                            id= self.shape_rbutton.GetId() ) 
1421        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
1422                            id= self.shape_indep_rbutton.GetId() ) 
1423        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
1424                            id= self.struct_rbutton.GetId() ) 
1425        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
1426                            id= self.plugin_rbutton.GetId() ) 
[c99a6c5]1427        #MAC needs SetValue
[ff8f99b]1428        self.shape_rbutton.SetValue(True)
[cfc0913]1429     
[3b605bb]1430        sizer_radiobutton = wx.GridSizer(2, 2,5, 5)
[c77d859]1431        sizer_radiobutton.Add(self.shape_rbutton)
1432        sizer_radiobutton.Add(self.shape_indep_rbutton)
1433        sizer_radiobutton.Add(self.plugin_rbutton)
1434        sizer_radiobutton.Add(self.struct_rbutton)
1435       
1436        sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
1437       
[fa58441]1438        self.text1 = wx.StaticText( self,-1,"" )
1439        self.text2 = wx.StaticText( self,-1,"P(Q)*S(Q)" )
[c77d859]1440       
1441       
[8bd4dc0]1442        self.formfactorbox = wx.ComboBox(self, -1,style=wx.CB_READONLY)
[ffa69b6]1443        if self.model!= None:
[c77d859]1444            self.formfactorbox.SetValue(self.model.name)
[ffa69b6]1445           
[8bd4dc0]1446        self.structurebox = wx.ComboBox(self, -1,style=wx.CB_READONLY)
[fcd8887d]1447       
1448        self.initialize_combox()
1449             
[c77d859]1450        wx.EVT_COMBOBOX(self.formfactorbox,-1, self._on_select_model)
1451        wx.EVT_COMBOBOX(self.structurebox,-1, self._on_select_model)
[3b605bb]1452       
[c77d859]1453       
[59a7f2d]1454        ## check model type to show sizer
[c77d859]1455        if self.model !=None:
1456            self._set_model_sizer_selection( self.model )
1457       
1458        sizer_selection.Add(self.text1)
1459        sizer_selection.Add((5,5))
1460        sizer_selection.Add(self.formfactorbox)
1461        sizer_selection.Add((5,5))
1462        sizer_selection.Add(self.text2)
1463        sizer_selection.Add((5,5))
1464        sizer_selection.Add(self.structurebox)
1465        sizer_selection.Add((5,5))
1466       
1467        boxsizer1.Add( sizer_radiobutton )
1468        boxsizer1.Add( (20,20))
1469        boxsizer1.Add( sizer_selection )
1470        if object !=None:
[f6b65b8]1471            boxsizer1.Add( (-72,-72))
[e3a76c8]1472            boxsizer1.Add( object,  0, wx.ALIGN_RIGHT| wx.RIGHT, 35)
[f6b65b8]1473            boxsizer1.Add( (60,60))
[c77d859]1474        #--------------------------------------------------------
1475        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1476        sizer.Layout()
[08ba57d]1477        self.SetScrollbars(20,20,25,65)
[c77d859]1478       
1479    def _show_combox(self, event):
1480        """
[5062bbf]1481        Show combox box associate with type of model selected
[c77d859]1482        """
[ffa69b6]1483        if self.check_invalid_panel():
[4470b10]1484            self.shape_rbutton.SetValue(True)
[ffa69b6]1485            return
1486
[376916c]1487        ## Don't want to populate combo box again if the event comes from check box
1488        if self.shape_rbutton.GetValue()and\
1489             event.GetEventObject()==self.shape_rbutton:
1490            ##fill the combobox with form factor list
[3b605bb]1491            self.structurebox.SetSelection(0)
1492            self.structurebox.Disable()
[c77d859]1493            self.formfactorbox.Clear()
[376916c]1494            self._populate_box( self.formfactorbox,self.model_list_box["Shapes"])
[c77d859]1495           
[376916c]1496        if self.shape_indep_rbutton.GetValue()and\
1497             event.GetEventObject()==self.shape_indep_rbutton:
1498            ##fill the combobox with shape independent  factor list
[3b605bb]1499            self.structurebox.SetSelection(0)
1500            self.structurebox.Disable()
[c77d859]1501            self.formfactorbox.Clear()
1502            self._populate_box( self.formfactorbox,
[376916c]1503                                self.model_list_box["Shape-Independent"])
[c77d859]1504           
[376916c]1505        if self.struct_rbutton.GetValue() and\
1506             event.GetEventObject()==self.struct_rbutton:
1507            ##fill the combobox with structure factor list
[3b605bb]1508            self.structurebox.SetSelection(0)
1509            self.structurebox.Disable()
[c77d859]1510            self.formfactorbox.Clear()
1511            self._populate_box( self.formfactorbox,
1512                                self.model_list_box["Structure Factors"])
1513           
[376916c]1514        if self.plugin_rbutton.GetValue()and\
1515             event.GetEventObject()==self.plugin_rbutton:
1516           
1517            ##fill the combobox with form factor list
[3b605bb]1518            self.structurebox.Disable()
[c77d859]1519            self.formfactorbox.Clear()
1520            self._populate_box( self.formfactorbox,
[376916c]1521                                self.model_list_box["Customized Models"])
[3595309d]1522       
[77e23a2]1523        self._on_select_model(event=None)
[3595309d]1524        self._save_typeOfmodel()
[3b605bb]1525        self.sizer4_4.Layout()
[9853ad0]1526        self.sizer4.Layout()
[3b605bb]1527        self.Layout()
1528        self.Refresh()
[08ba57d]1529        self.SetScrollbars(20,20,25,65)
[c77d859]1530           
1531    def _populate_box(self, combobox, list):
1532        """
[5062bbf]1533        fill combox box with dict item
1534       
1535        :param list: contains item to fill the combox
[c77d859]1536            item must model class
1537        """
[f72333f]1538        st = time.time()
[c77d859]1539        for models in list:
1540            model= models()
1541            name = model.__class__.__name__
[0a518e4c]1542            if models.__name__!="NoStructure":
1543                if hasattr(model, "name"):
1544                    name = model.name
1545                combobox.Append(name,models)
[c77d859]1546        return 0
[7609f1a]1547
[6e9976b]1548    def _onQrangeEnter(self, event):
1549        """
[5062bbf]1550        Check validity of value enter in the Q range field
[6e9976b]1551        """
1552       
1553        tcrtl= event.GetEventObject()
1554        #Clear msg if previously shown.
1555        msg= ""
1556        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1557        # Flag to register when a parameter has changed.
1558        is_modified = False
1559        if tcrtl.GetValue().lstrip().rstrip()!="":
1560            try:
1561                value = float(tcrtl.GetValue())
1562                tcrtl.SetBackgroundColour(wx.WHITE)
1563
1564                # If qmin and qmax have been modified, update qmin and qmax
[484faf7]1565                if self._validate_qrange( self.qmin, self.qmax):
[6e9976b]1566                    tempmin = float(self.qmin.GetValue())
1567                    if tempmin != self.qmin_x:
1568                        self.qmin_x = tempmin
1569                    tempmax = float(self.qmax.GetValue())
1570                    if tempmax != self.qmax_x:
1571                        self.qmax_x = tempmax
1572                else:
1573                    tcrtl.SetBackgroundColour("pink")
1574                    msg= "Model Error:wrong value entered : %s"% sys.exc_value
1575                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1576                    return 
1577               
1578            except:
1579                tcrtl.SetBackgroundColour("pink")
1580                msg= "Model Error:wrong value entered : %s"% sys.exc_value
1581                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1582                return 
1583            #Check if # of points for theory model are valid(>0).
1584            if self.npts != None:
1585                if check_float(self.npts):
1586                    temp_npts = float(self.npts.GetValue())
1587                    if temp_npts !=  self.num_points:
1588                        self.num_points = temp_npts
1589                        is_modified = True
1590                else:
1591                    msg= "Cannot Plot :No npts in that Qrange!!!  "
1592                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1593           
1594        else:
1595           tcrtl.SetBackgroundColour("pink")
1596           msg= "Model Error:wrong value entered!!!"
1597           wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1598           
1599        #self._undo.Enable(True)
1600        self.save_current_state()
1601        event = PageInfoEvent(page = self)
1602        wx.PostEvent(self.parent, event)
1603        self.state_change= False
[484faf7]1604        #Draw the model for a different range
1605        self._draw_model()
[6e9976b]1606                   
[59a7f2d]1607    def _on_select_model_helper(self): 
[c77d859]1608        """
[5062bbf]1609        call back for model selection
[c77d859]1610        """
[376916c]1611        ## reset dictionary containing reference to dispersion
1612        self._disp_obj_dict = {}
1613        self.disp_cb_dict ={}
[b421b1a]1614       
[c77d859]1615        f_id = self.formfactorbox.GetCurrentSelection()
[ff8f99b]1616        #For MAC
1617        form_factor = None
1618        if f_id >= 0:
1619            form_factor = self.formfactorbox.GetClientData( f_id )
[9170547]1620
[376916c]1621        if not form_factor in  self.model_list_box["multiplication"]:
[6dc9ad8]1622            self.structurebox.Hide()
1623            self.text2.Hide()           
[3b605bb]1624            self.structurebox.Disable()
1625            self.structurebox.SetSelection(0)
[c097f02]1626            self.text2.Disable()
[87fbc60]1627        else:
[6dc9ad8]1628            self.structurebox.Show()
1629            self.text2.Show()
[87fbc60]1630            self.structurebox.Enable()
[c097f02]1631            self.text2.Enable()
[f72333f]1632        #if self.data.__class__.__name__ =="Data2D":
1633            #self.smear_description_2d.Show(True)
[9bd6c13c]1634           
[3b605bb]1635        s_id = self.structurebox.GetCurrentSelection()
1636        struct_factor = self.structurebox.GetClientData( s_id )
[a074145]1637       
[3b605bb]1638        if  struct_factor !=None:
[9853ad0]1639            from sans.models.MultiplicationModel import MultiplicationModel
1640            self.model= MultiplicationModel(form_factor(),struct_factor())
[0aeabc6]1641           
[c77d859]1642        else:
[fbf4bf8]1643            if form_factor != None:
1644                self.model= form_factor()
1645            else:
1646                self.model = None
1647                return self.model
[a074145]1648       
[cfc0913]1649        ## post state to fit panel
[f20767b]1650        self.state.parameters =[]
[fc6ea43]1651        self.state.model =self.model
[71f0373]1652        self.disp_list =self.model.getDispParamList()
[f20767b]1653        self.state.disp_list = self.disp_list
[7975f2b]1654        self.Layout()     
[c99a6c5]1655       
[85b3971]1656    def _validate_qrange(self, qmin_ctrl, qmax_ctrl):
1657        """
[5062bbf]1658        Verify that the Q range controls have valid values
1659        and that Qmin < Qmax.
1660       
1661        :param qmin_ctrl: text control for Qmin
1662        :param qmax_ctrl: text control for Qmax
1663       
1664        :return: True is the Q range is value, False otherwise
1665       
[85b3971]1666        """
1667        qmin_validity = check_float(qmin_ctrl)
1668        qmax_validity = check_float(qmax_ctrl)
1669        if not (qmin_validity and qmax_validity):
1670            return False
1671        else:
1672            qmin = float(qmin_ctrl.GetValue())
1673            qmax = float(qmax_ctrl.GetValue())
[7609f1a]1674            if qmin <= qmax:
[85b3971]1675                #Make sure to set both colours white. 
1676                qmin_ctrl.SetBackgroundColour(wx.WHITE)
1677                qmin_ctrl.Refresh()
1678                qmax_ctrl.SetBackgroundColour(wx.WHITE)
1679                qmax_ctrl.Refresh()
1680            else:
1681                qmin_ctrl.SetBackgroundColour("pink")
1682                qmin_ctrl.Refresh()
1683                qmax_ctrl.SetBackgroundColour("pink")
1684                qmax_ctrl.Refresh()
1685                msg= "Invalid Q range: Q min must be smaller than Q max"
1686                wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
1687                return False
1688        return True
[51a71a3]1689   
1690    def _validate_Npts(self): 
1691        """
[5062bbf]1692        Validate the number of points for fitting is more than 10 points.
1693        If valid, setvalues Npts_fit otherwise post msg.
[51a71a3]1694        """
1695        #default flag
1696        flag = True
[7609f1a]1697
[51a71a3]1698        # q value from qx and qy
1699        radius= numpy.sqrt( self.data.qx_data*self.data.qx_data + self.data.qy_data*self.data.qy_data )
1700        #get unmasked index
1701        index_data = (float(self.qmin.GetValue()) <= radius)&(radius<= float(self.qmax.GetValue()))
1702        index_data = (index_data)&(self.data.mask) 
1703        index_data = (index_data)&(numpy.isfinite(self.data.data))
1704
1705        if len(index_data[index_data]) < 10:
1706            # change the color pink.
1707            self.qmin.SetBackgroundColour("pink")
1708            self.qmin.Refresh()
1709            self.qmax.SetBackgroundColour("pink")
1710            self.qmax.Refresh()
1711            msg= "Cannot Plot :No or too little npts in that data range!!!  "
1712            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1713            self.fitrange = False
1714            flag = False
1715        else:
1716            self.Npts_fit.SetValue(str(len(self.data.mask[index_data==True])))
1717            self.fitrange = True
1718           
1719        return flag
1720   
[c77d859]1721    def _check_value_enter(self, list, modified):
1722        """
[5062bbf]1723        :param list: model parameter and panel info
1724        :Note: each item of the list should be as follow:
1725            item=[check button state, parameter's name,
1726                paramater's value, string="+/-",
1727                parameter's error of fit,
1728                parameter's minimum value,
1729                parrameter's maximum value ,
1730                parameter's units]
[c77d859]1731        """ 
[c99a6c5]1732        is_modified =  modified
[c77d859]1733        if len(list)==0:
[c99a6c5]1734            return is_modified
[c77d859]1735        for item in list:
[edd166b]1736            #skip angle parameters for 1D
[6318298]1737            if self.data.__class__.__name__ !="Data2D":
[edd166b]1738                if item in self.orientation_params:
1739                    continue
1740            #try:
1741            name = str(item[1])
1742           
1743            if string.find(name,".npts") ==-1 and string.find(name,".nsigmas")==-1:     
[c985bef]1744                ## check model parameters range             
[77e23a2]1745                param_min= None
1746                param_max= None
[7975f2b]1747               
[c985bef]1748                ## check minimun value
[edd166b]1749                if item[5]!= None and item[5]!= "":
[298b762]1750                    if item[5].GetValue().lstrip().rstrip()!="":
[edd166b]1751                        try:
[7975f2b]1752                           
[edd166b]1753                            param_min = float(item[5].GetValue())
[918fcb1]1754                            if not self._validate_qrange(item[5],item[2]):
[7975f2b]1755                                if numpy.isfinite(param_min):
1756                                    item[2].SetValue(format_number(param_min))
[6e9976b]1757                           
1758                            item[5].SetBackgroundColour(wx.WHITE)
1759                            item[2].SetBackgroundColour(wx.WHITE)
1760                                           
[edd166b]1761                        except:
1762                            msg = "Wrong Fit parameter range entered "
1763                            wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
1764                            raise ValueError, msg
[c985bef]1765                        is_modified = True
[77e23a2]1766                ## check maximum value
[7975f2b]1767                if item[6]!= None and item[6]!= "":
[298b762]1768                    if item[6].GetValue().lstrip().rstrip()!="":
[7975f2b]1769                        try:                         
[edd166b]1770                            param_max = float(item[6].GetValue())
[918fcb1]1771                            if not self._validate_qrange(item[2],item[6]):
[7975f2b]1772                                if numpy.isfinite(param_max):
1773                                    item[2].SetValue(format_number(param_max)) 
[6e9976b]1774                           
1775                            item[6].SetBackgroundColour(wx.WHITE)
1776                            item[2].SetBackgroundColour(wx.WHITE)
[edd166b]1777                        except:
1778                            msg = "Wrong Fit parameter range entered "
1779                            wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
1780                            raise ValueError, msg
[c985bef]1781                        is_modified = True
[7975f2b]1782               
[edd166b]1783
[77e23a2]1784                if param_min != None and param_max !=None:
[85b3971]1785                    if not self._validate_qrange(item[5], item[6]):
[77e23a2]1786                        msg= "Wrong Fit range entered for parameter "
1787                        msg+= "name %s of model %s "%(name, self.model.name)
[edd166b]1788                        wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
[7975f2b]1789               
[cfc0913]1790                if name in self.model.details.keys():   
[edd166b]1791                        self.model.details[name][1:3]= param_min,param_max
1792                        is_modified = True
[7975f2b]1793             
[edd166b]1794                else:
[7975f2b]1795                        self.model.details [name] = ["",param_min,param_max] 
1796                        is_modified = True
[6e9976b]1797            try:     
1798                value= float(item[2].GetValue())
1799     
1800                # If the value of the parameter has changed,
1801                # +update the model and set the is_modified flag
1802                if value != self.model.getParam(name) and numpy.isfinite(value):
1803                    self.model.setParam(name,value)
1804                    is_modified = True   
1805            except:
1806                msg = "Wrong Fit parameter value entered "
1807                wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
[7975f2b]1808               
[c99a6c5]1809        return is_modified
[c77d859]1810       
1811 
1812    def _set_dipers_Param(self, event):
1813        """
[5062bbf]1814        respond to self.enable_disp and self.disable_disp radio box.
1815        The dispersity object is reset inside the model into Gaussian.
1816        When the user select yes , this method display a combo box for more selection
1817        when the user selects No,the combo box disappears.
1818        Redraw the model with the default dispersity (Gaussian)
[c77d859]1819        """
[ffa69b6]1820        if self.check_invalid_panel():
1821            return 
[4470b10]1822        ## On selction if no model exists.
1823        if self.model ==None:
1824            self.disable_disp.SetValue(True)
1825            msg="Please select a Model first..."
1826            wx.MessageBox(msg, 'Info')
1827            wx.PostEvent(self.manager.parent, StatusEvent(status=\
1828                            "Polydispersion: %s"%msg))
1829            return
1830
[1c1436d]1831        self._reset_dispersity()
[1467e1a6]1832   
[70c57ebf]1833        if self.model ==None:
1834            self.model_disp.Hide()
1835            self.disp_box.Hide()
1836            self.sizer4_4.Clear(True)
1837            return
[b421b1a]1838
[1c1436d]1839        if self.enable_disp.GetValue():
1840            self.model_disp.Show(True)
1841            self.disp_box.Show(True)
1842            ## layout for model containing no dispersity parameters
[f20767b]1843           
[71f0373]1844            self.disp_list= self.model.getDispParamList()
[f20767b]1845             
1846            if len(self.disp_list)==0 and len(self.disp_cb_dict)==0:
[1c1436d]1847                self._layout_sizer_noDipers() 
[c77d859]1848            else:
[1c1436d]1849                ## set gaussian sizer
1850                self._on_select_Disp(event=None)
1851        else:
1852            self.model_disp.Hide()
1853            self.disp_box.Hide()
[71f0373]1854            self.disp_box.SetSelection(0) 
[1c1436d]1855            self.sizer4_4.Clear(True)
[f20767b]1856           
[240b9966]1857        ## post state to fit panel
[1c1436d]1858        self.save_current_state()
[240b9966]1859        if event !=None:
[3a37fe0]1860            #self._undo.Enable(True)
[240b9966]1861            event = PageInfoEvent(page = self)
1862            wx.PostEvent(self.parent, event)
[1467e1a6]1863        #draw the model with the current dispersity
[f20767b]1864        self._draw_model()
[f1aa385]1865        self.sizer4_4.Layout()
1866        self.sizer5.Layout()
[71f0373]1867        self.Layout()
[edd166b]1868        self.Refresh()     
[3b605bb]1869         
[c77d859]1870       
1871    def _layout_sizer_noDipers(self):
1872        """
[5062bbf]1873        Draw a sizer with no dispersity info
[c77d859]1874        """
1875        ix=0
1876        iy=1
1877        self.fittable_param=[]
1878        self.fixed_param=[]
[1c1436d]1879        self.orientation_params_disp=[]
1880       
[c77d859]1881        self.model_disp.Hide()
1882        self.disp_box.Hide()
1883        self.sizer4_4.Clear(True)
1884        model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
1885        self.sizer4_4.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[dcf29d7]1886        self.sizer4_4.Layout()
[c77d859]1887        self.sizer4.Layout()
[08ba57d]1888        self.SetScrollbars(20,20,25,65)
[3b605bb]1889     
[c77d859]1890           
1891    def _reset_dispersity(self):
1892        """
[5062bbf]1893        put gaussian dispersity into current model
[c77d859]1894        """
[1c1436d]1895        if len(self.param_toFit)>0:
1896            for item in self.fittable_param:
[513115c]1897                if item in self.param_toFit:
[1c1436d]1898                    self.param_toFit.remove(item)
[edd166b]1899
[1c1436d]1900            for item in self.orientation_params_disp:
[513115c]1901                if item in self.param_toFit:
[1c1436d]1902                    self.param_toFit.remove(item)
[513115c]1903         
[c77d859]1904        self.fittable_param=[]
1905        self.fixed_param=[]
[5812a55]1906        self.orientation_params_disp=[]
[71f0373]1907        self.values=[]
1908        self.weights=[]
[f20767b]1909     
1910        from sans.models.dispersion_models import GaussianDispersion, ArrayDispersion
[c77d859]1911        if len(self.disp_cb_dict)==0:
[e2f7b92]1912            self.save_current_state()
[3b605bb]1913            self.sizer4_4.Clear(True)
1914            self.Layout()
[7975f2b]1915 
[c77d859]1916            return 
[f20767b]1917        if (len(self.disp_cb_dict)>0) :
1918            for p in self.disp_cb_dict:
1919                # The parameter was un-selected. Go back to Gaussian model (with 0 pts)                   
1920                disp_model = GaussianDispersion()
1921               
[ff8f99b]1922                self._disp_obj_dict[p] = disp_model
1923                # Set the new model as the dispersion object for the selected parameter
[f20767b]1924                try:
[ff8f99b]1925                   self.model.set_dispersion(p, disp_model)
[f20767b]1926                except:
[c985bef]1927
[f20767b]1928                    pass
[7975f2b]1929
[240b9966]1930        ## save state into
1931        self.save_current_state()
[7975f2b]1932        self.Layout() 
[c985bef]1933        self.Refresh()
[7975f2b]1934                 
[c77d859]1935    def _on_select_Disp(self,event):
1936        """
[5062bbf]1937        allow selecting different dispersion
1938        self.disp_list should change type later .now only gaussian
[c77d859]1939        """
[b787e68c]1940        n = self.disp_box.GetCurrentSelection()
[30d103a]1941        name = self.disp_box.GetValue()
[b787e68c]1942        dispersity= self.disp_box.GetClientData(n)
[f20767b]1943        self.disp_name = name
[30d103a]1944       
1945        if name.lower() == "array":
[c77d859]1946            self._set_sizer_arraydispersion()
[30d103a]1947        else:
1948            self._set_sizer_dispersion(dispersity= dispersity)
[3b605bb]1949           
[b787e68c]1950        self.state.disp_box= n
[6e9150d]1951        ## Redraw the model
1952        self._draw_model() 
[3a37fe0]1953        #self._undo.Enable(True)
[3b9e023]1954        event = PageInfoEvent(page = self)
1955        wx.PostEvent(self.parent, event)
1956       
[7975f2b]1957        self.sizer4_4.Layout()
1958        self.sizer4.Layout()
[08ba57d]1959        self.SetScrollbars(20,20,25,65)
[3b605bb]1960       
[c77d859]1961    def _set_sizer_arraydispersion(self):
1962        """
[5062bbf]1963        draw sizer with array dispersity  parameters
[c77d859]1964        """
[f20767b]1965       
[513115c]1966        if len(self.param_toFit)>0:
1967            for item in self.fittable_param:
1968                if item in self.param_toFit:
1969                    self.param_toFit.remove(item)
1970            for item in self.orientation_params_disp:
1971                if item in self.param_toFit:
1972                    self.param_toFit.remove(item)
[920a6e5]1973        for item in self.model.details.keys():
1974            if item in self.model.fixed:
1975                del self.model.details [item]                           
[f20767b]1976
[1c1436d]1977        self.fittable_param=[]
1978        self.fixed_param=[]
[60132ef]1979        self.orientation_params_disp=[]
[c77d859]1980        self.sizer4_4.Clear(True) 
[f20767b]1981        self._reset_dispersity()
[c77d859]1982        ix=0
1983        iy=1     
1984        disp1 = wx.StaticText(self, -1, 'Array Dispersion')
1985        self.sizer4_4.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1986       
1987        # Look for model parameters to which we can apply an ArrayDispersion model
1988        # Add a check box for each parameter.
1989        self.disp_cb_dict = {}
[6e9150d]1990        ix+=1 
1991        self.noDisper_rbox = wx.RadioButton(self, -1,"None", (10, 10),style= wx.RB_GROUP)
1992        self.Bind(wx.EVT_RADIOBUTTON,self.select_disp_angle , id=self.noDisper_rbox.GetId())
[ff8f99b]1993        #MAC needs SetValue
1994        self.noDisper_rbox.SetValue(True)
[6e9150d]1995        self.sizer4_4.Add(self.noDisper_rbox, (iy, ix),
1996                           (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[c77d859]1997       
[f20767b]1998        for p in self.model.dispersion.keys():
1999            if not p in self.model.orientation_params:
2000                ix+=1 
[ad8f0d0]2001                self.disp_cb_dict[p] = wx.RadioButton(self, -1, p, (10, 10))
[f20767b]2002                self.state.disp_cb_dict[p]=  self.disp_cb_dict[p].GetValue()
[f5dadd5]2003                self.Bind(wx.EVT_RADIOBUTTON, self.select_disp_angle, id=self.disp_cb_dict[p].GetId())
[f20767b]2004                self.sizer4_4.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[6e9150d]2005       
[f20767b]2006        for p in self.model.dispersion.keys():
2007            if p in self.model.orientation_params:
2008                ix+=1 
[f5dadd5]2009                self.disp_cb_dict[p] = wx.RadioButton(self, -1, p, (10, 10))
[f20767b]2010                self.state.disp_cb_dict[p]=  self.disp_cb_dict[p].GetValue()
[6318298]2011                if not (self.enable2D or self.data.__class__.__name__ =="Data2D"):
[6dc9ad8]2012                    self.disp_cb_dict[p].Hide()
[f20767b]2013                else:
[6dc9ad8]2014                    self.disp_cb_dict[p].Show(True)
[f5dadd5]2015                self.Bind(wx.EVT_RADIOBUTTON, self.select_disp_angle, id=self.disp_cb_dict[p].GetId())
[f20767b]2016                self.sizer4_4.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
2017
2018
[c77d859]2019        ix =0
2020        iy +=1 
2021        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
[e2f7b92]2022        self.Layout()
[f20767b]2023
2024        self.state.orientation_params =[]
2025        self.state.orientation_params_disp =[]
2026        self.state.parameters =[]
2027        self.state.fittable_param =[]
2028        self.state.fixed_param =[]
2029       
2030        ## save checkbutton state and txtcrtl values
2031       
2032        self._copy_parameters_state(self.orientation_params,
2033                                     self.state.orientation_params)
2034
[240b9966]2035        self._copy_parameters_state(self.orientation_params_disp,
2036                                     self.state.orientation_params_disp)
[f20767b]2037       
2038        self._copy_parameters_state(self.parameters, self.state.parameters)
[240b9966]2039        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
2040        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
[3b9e023]2041       
[f20767b]2042       
[3b9e023]2043        ## post state to fit panel
2044        event = PageInfoEvent(page = self)
2045        wx.PostEvent(self.parent, event)
2046       
[ff8f99b]2047    def _set_range_sizer(self, title, box_sizer=None, object1=None,object=None):
[c77d859]2048        """
[5062bbf]2049        Fill the Q range sizer
[c77d859]2050        """
[51a71a3]2051        #2D data? default
2052        is_2Ddata = False
2053       
2054        #check if it is 2D data
[6318298]2055        if self.data.__class__.__name__ == 'Data2D':
[51a71a3]2056            is_2Ddata = True
2057           
[c77d859]2058        self.sizer5.Clear(True)
2059        #--------------------------------------------------------------
[ff8f99b]2060        if box_sizer == None:
[acd0bda3]2061            box_description= wx.StaticBox(self, -1,str(title))
2062            boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
[ff8f99b]2063        else:
2064            #for MAC
2065            boxsizer1 = box_sizer
2066
[6e9976b]2067        self.qmin    = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH,20),style=wx.TE_PROCESS_ENTER,
[7609f1a]2068                                            text_enter_callback = self._onparamEnter)
[b5e98540]2069        self.qmin.SetValue(str(self.qmin_x))
[c77d859]2070        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
2071     
[6e9976b]2072        self.qmax    = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH,20),style=wx.TE_PROCESS_ENTER,
[7609f1a]2073                                            text_enter_callback = self._onparamEnter)
[b5e98540]2074        self.qmax.SetValue(str(self.qmax_x))
[c77d859]2075        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
[904168e1]2076       
2077        id = wx.NewId()
[51a71a3]2078        self.reset_qrange =wx.Button(self,id,'Reset',size=(77,20))
[7975f2b]2079     
[904168e1]2080        self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked,id=id)
2081        self.reset_qrange.SetToolTipString("Reset Q range to the default values")
[c77d859]2082     
2083        sizer_horizontal=wx.BoxSizer(wx.HORIZONTAL)
[51a71a3]2084        sizer= wx.GridSizer(2, 4,2, 6)
2085
2086        self.btEditMask = wx.Button(self,wx.NewId(),'Editor', size=(88,23))
2087        self.btEditMask.Bind(wx.EVT_BUTTON, self._onMask,id= self.btEditMask.GetId())
2088        self.btEditMask.SetToolTipString("Edit Mask.")
2089        self.EditMask_title = wx.StaticText(self, -1, ' Masking(2D)')
2090
[904168e1]2091        sizer.Add(wx.StaticText(self, -1, '    Q range'))     
[51a71a3]2092        sizer.Add(wx.StaticText(self, -1, ' Min[1/A]'))
2093        sizer.Add(wx.StaticText(self, -1, ' Max[1/A]'))
2094        sizer.Add(self.EditMask_title)
[904168e1]2095        sizer.Add(self.reset_qrange)   
[51a71a3]2096       
[c77d859]2097        sizer.Add(self.qmin)
2098        sizer.Add(self.qmax)
[51a71a3]2099        sizer.Add(self.btEditMask)
2100       
[c77d859]2101        if object1!=None:
[51a71a3]2102           
2103            boxsizer1.Add(object1) 
2104            boxsizer1.Add((10,10))
2105        boxsizer1.Add(sizer)
2106        if object!=None:
2107            boxsizer1.Add((10,15))
2108            boxsizer1.Add(object)
[19403da]2109        if is_2Ddata:
2110            self.btEditMask.Enable() 
2111            self.EditMask_title.Enable() 
2112        else:
[51a71a3]2113            self.btEditMask.Disable() 
[19403da]2114            self.EditMask_title.Disable()
[cfc0913]2115        ## save state
2116        self.save_current_state()
[c77d859]2117        #----------------------------------------------------------------
2118        self.sizer5.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
2119        self.sizer5.Layout()
[7975f2b]2120
[cfc0913]2121   
[00c3aac]2122    def _fill_save_sizer(self):
2123        """
[5062bbf]2124        Draw the layout for saving option
[00c3aac]2125        """
[1b43306]2126        return
[00c3aac]2127        self.sizer6.Clear(True)
[295cd7e]2128        box_description= wx.StaticBox(self, -1,"Save Model")
[00c3aac]2129        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
2130        sizer_save = wx.BoxSizer(wx.HORIZONTAL)
2131       
[9dd261e]2132        self.btSave_title = wx.StaticText(self, -1, 'Save the current Model')
[00c3aac]2133        self.btSave = wx.Button(self,wx.NewId(),'Save')
[9bc499b6]2134        self.btSave.Bind(wx.EVT_BUTTON, self.on_save_state,id= self.btSave.GetId())
[295cd7e]2135        self.btSave.SetToolTipString("Save the current Model")
[45ed4dad]2136       
2137        sizer_save.Add(self.btSave_title) 
[9c38ed4]2138        sizer_save.Add((20,20),0, wx.LEFT|wx.RIGHT|wx.EXPAND,80) 
[00c3aac]2139        sizer_save.Add(self.btSave)     
2140        boxsizer1.Add(sizer_save)
2141        self.sizer6.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
2142        self.sizer6.Layout()
[08ba57d]2143        self.SetScrollbars(20,20,25,65)
[7975f2b]2144       
2145    def _lay_out(self):
2146        """
[5062bbf]2147        returns self.Layout
2148       
2149        :Note: Mac seems to like this better when self.
2150            Layout is called after fitting.
[7975f2b]2151        """
2152        self._sleep4sec()
2153        self.Layout()
2154        return 
2155   
2156    def _sleep4sec(self):
2157        """
[12eac73]2158            sleep for 1 sec only applied on Mac
2159            Note: This 1sec helps for Mac not to crash on self.:ayout after self._draw_model
[7975f2b]2160        """
2161        if ON_MAC == True:
[12eac73]2162            time.sleep(1)
[f72333f]2163           
[904168e1]2164    def on_reset_clicked(self,event):
2165        """
[5062bbf]2166        On 'Reset' button  for Q range clicked
[904168e1]2167        """
[7609f1a]2168        flag = True
[ffa69b6]2169        if self.check_invalid_panel():
2170            return
[904168e1]2171        ##For 3 different cases: Data2D, Data1D, and theory
[6318298]2172        if self.data.__class__.__name__ == "Data2D":
[904168e1]2173            data_min= 0
2174            x= max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
2175            y= max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
2176            self.qmin_x = data_min
2177            self.qmax_x = math.sqrt(x*x + y*y)
[f72333f]2178            # check smearing
2179            if not self.disable_smearer.GetValue():
2180                temp_smearer= self.current_smearer
2181                ## set smearing value whether or not the data contain the smearing info
2182                if self.pinhole_smearer.GetValue():
2183                    flag = self.update_pinhole_smear()
2184                else:
2185                    flag = True
[6318298]2186        elif self.data.__class__.__name__ != "Data2D":
[904168e1]2187            self.qmin_x = min(self.data.x)
2188            self.qmax_x = max(self.data.x)
[7609f1a]2189            # check smearing
2190            if not self.disable_smearer.GetValue():
2191                temp_smearer= self.current_smearer
2192                ## set smearing value whether or not the data contain the smearing info
2193                if self.slit_smearer.GetValue():
2194                    flag = self.update_slit_smear()
2195                elif self.pinhole_smearer.GetValue():
2196                    flag = self.update_pinhole_smear()
2197                else:
2198                    flag = True
[904168e1]2199        else:
[d4bb639]2200            self.qmin_x = _QMIN_DEFAULT
2201            self.qmax_x = _QMAX_DEFAULT
2202            self.num_points = _NPTS_DEFAULT           
[904168e1]2203            self.state.npts = self.num_points
[7975f2b]2204           
[7609f1a]2205        if flag == False:
2206            msg= "Cannot Plot :Must enter a number!!!  "
2207            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
[51a71a3]2208        else:
2209            # set relative text ctrs.
2210            self.qmin.SetValue(str(self.qmin_x))
2211            self.qmax.SetValue(str(self.qmax_x))
2212            self.set_npts2fit()
2213            # At this point, some button and variables satatus (disabled?) should be checked
2214            # such as color that should be reset to white in case that it was pink.
2215            self._onparamEnter_helper()
2216
[7609f1a]2217        self.save_current_state()
[904168e1]2218        self.state.qmin = self.qmin_x
2219        self.state.qmax = self.qmax_x
[00c3aac]2220       
[904168e1]2221        #reset the q range values
2222        self._reset_plotting_range(self.state)
[f72333f]2223        #self.compute_chisqr(smearer=self.current_smearer)
[904168e1]2224        #Re draw plot
2225        self._draw_model()
2226
[7ad6ff5]2227    def on_model_help_clicked(self,event):
2228        """
[5062bbf]2229        on 'More details' button
[7ad6ff5]2230        """
[484faf7]2231        from help_panel import  HelpWindow
[c77d859]2232       
[7ad6ff5]2233        if self.model == None:
2234            name = 'FuncHelp'
2235        else:
2236            name = self.model.origin_name
2237
[da3f24c]2238        frame = HelpWindow(None, -1,  pageToOpen="media/model_functions.html")   
[7ad6ff5]2239        frame.Show(True)
2240        if frame.rhelp.HasAnchor(name):
2241            frame.rhelp.ScrollToAnchor(name)
2242        else:
2243           msg= "Model does not contains an available description "
2244           msg +="Please try searching in the Help window"
2245           wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))                   
[c77d859]2246               
Note: See TracBrowser for help on using the repository browser.