source: sasview/theoryview/perspectives/theory/basepage.py @ f9a1279

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 f9a1279 was 0277d084, checked in by Gervaise Alina <gervyh@…>, 15 years ago

add theory view

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