source: sasview/sansview/perspectives/fitting/basepage.py @ 232c3db

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 232c3db was f83b94a, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on save state

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