source: sasview/sansview/perspectives/fitting/basepage.py @ 23ccf07

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 23ccf07 was 2657df9, checked in by Jae Cho <jhjcho@…>, 14 years ago

disabled right-click book mark when no data was set yet

  • Property mode set to 100644
File size: 108.1 KB
Line 
1
2import sys
3import os
4import wx
5import numpy
6import time
7import copy 
8import math
9import string
10from sans.guiframe.panel_base import PanelBase
11from wx.lib.scrolledpanel import ScrolledPanel
12from sans.guiframe.utils import format_number,check_float
13from sans.guiframe.events import PanelOnFocusEvent
14from sans.guiframe.events import StatusEvent
15from sans.guiframe.events import AppendBookmarkEvent
16import pagestate
17from pagestate import PageState
18(PageInfoEvent, EVT_PAGE_INFO)   = wx.lib.newevent.NewEvent()
19(PreviousStateEvent, EVT_PREVIOUS_STATE)   = wx.lib.newevent.NewEvent()
20(NextStateEvent, EVT_NEXT_STATE)   = wx.lib.newevent.NewEvent()
21
22_BOX_WIDTH = 76
23_QMIN_DEFAULT = 0.0005
24_QMAX_DEFAULT = 0.5
25_NPTS_DEFAULT = 200
26#Control panel width
27if sys.platform.count("darwin")==0:
28    PANEL_WIDTH = 450
29    FONT_VARIANT = 0
30    ON_MAC = False
31else:
32    PANEL_WIDTH = 500
33    FONT_VARIANT = 1
34    ON_MAC = True
35
36
37
38class BasicPage(ScrolledPanel, PanelBase):
39    """
40    This class provide general structure of  fitpanel page
41    """
42     ## Internal name for the AUI manager
43    window_name = "Fit Page"
44    ## Title to appear on top of the window
45    window_caption = "Fit Page "
46   
47    def __init__(self, parent,color='blue', **kwargs):
48        """
49        """
50        ScrolledPanel.__init__(self, parent, **kwargs)
51        PanelBase.__init__(self, parent)
52        self.SetupScrolling()
53        #Set window's font size
54        self.SetWindowVariant(variant=FONT_VARIANT)
55     
56        self.SetBackgroundColour(color)
57        ## parent of the page
58        self.parent = parent
59        ## manager is the fitting plugin
60        ## owner of the page (fitting plugin)
61        self.event_owner = None
62         ## current model
63        self.model = None
64        ## data
65        self.data = None
66        self.mask = None
67        self.uid = None
68        ## Q range
69        self.qmin = None
70        self.qmax = None
71        self.qmax_x = _QMAX_DEFAULT
72        self.qmin_x = _QMIN_DEFAULT
73        self.npts_x = _NPTS_DEFAULT
74        ## total number of point: float
75        self.npts = None
76        ## default fitengine type
77        self.engine_type = 'scipy'
78        ## smear default
79        self.smearer = None
80        self.current_smearer = None
81        ## 2D smear accuracy default
82        self.smear2d_accuracy = 'Low'
83        ## slit smear:
84        self.dxl = None
85        self.dxw = None
86        ## pinhole smear
87        self.dx_min = None
88        self.dx_max = None
89       
90        self.disp_cb_dict = {}
91   
92        self.state = PageState(parent=parent)
93        ## dictionary containing list of models
94        self.model_list_box = {}
95       
96        ## Data member to store the dispersion object created
97        self._disp_obj_dict = {}
98        ## selected parameters to apply dispersion
99        self.disp_cb_dict ={}
100
101        ## smearer object
102        self.smearer = None
103        self.enable2D = False
104       
105        ##list of model parameters. each item must have same length
106        ## each item related to a given parameters
107        ##[cb state, name, value, "+/-", error of fit, min, max , units]
108        self.parameters = []
109        # non-fittable parameter whose value is astring
110        self.str_parameters = []
111        ## list of parameters to fit , must be like self.parameters
112        self.param_toFit = []
113        ## list of looking like parameters but with non fittable parameters info
114        self.fixed_param = []
115        ## list of looking like parameters but with  fittable parameters info
116        self.fittable_param = []
117        ##list of dispersion parameters
118        self.disp_list = []
119        self.disp_name = ""
120       
121        ## list of orientation parameters
122        self.orientation_params = []
123        self.orientation_params_disp = []
124        if self.model != None:
125            self.disp_list = self.model.getDispParamList()
126       
127        ##enable model 2D draw
128        self.enable2D = False
129        ## check that the fit range is correct to plot the model again
130        self.fitrange = True
131        ## Create memento to save the current state
132        self.state = PageState(parent=self.parent,
133                               model=self.model, data=self.data)
134        ## flag to determine if state has change
135        self.state_change = False
136        ## save customized array
137        self.values = []
138        self.weights = []
139        ## retrieve saved state
140        self.number_saved_state = 0
141        ## dictionary of saved state
142        self.saved_states = {} 
143        ## Create context menu for page
144        self.popUpMenu = wx.Menu()
145   
146        id = wx.NewId()
147        self._keep = wx.MenuItem(self.popUpMenu,id,"BookMark",
148                                 " Keep the panel status to recall it later")
149        self.popUpMenu.AppendItem(self._keep)
150        self._keep.Enable(False)
151        self._set_bookmark_flag(False)
152        self._set_save_flag(False)
153        wx.EVT_MENU(self, id, self.on_bookmark)
154        self.popUpMenu.AppendSeparator()
155   
156        ## Default locations
157        self._default_save_location = os.getcwd()     
158        ## save initial state on context menu
159        #self.onSave(event=None)
160        self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
161       
162        # bind key event
163        self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
164
165        ## create the basic structure of the panel with empty sizer
166        self.define_page_structure()
167        ## drawing Initial dispersion parameters sizer
168        self.set_dispers_sizer()
169       
170        ## layout
171        self.set_layout()
172       
173   
174       
175    def on_set_focus(self, event):
176        """
177        """
178        if self._manager is not None:
179            wx.PostEvent(self._manager.parent, PanelOnFocusEvent(panel=self))
180       
181    class ModelTextCtrl(wx.TextCtrl):
182        """
183        Text control for model and fit parameters.
184        Binds the appropriate events for user interactions.
185        Default callback methods can be overwritten on initialization
186       
187        :param kill_focus_callback: callback method for EVT_KILL_FOCUS event
188        :param set_focus_callback:  callback method for EVT_SET_FOCUS event
189        :param mouse_up_callback:   callback method for EVT_LEFT_UP event
190        :param text_enter_callback: callback method for EVT_TEXT_ENTER event
191       
192        """
193        ## Set to True when the mouse is clicked while the whole string is selected
194        full_selection = False
195        ## Call back for EVT_SET_FOCUS events
196        _on_set_focus_callback = None
197       
198        def __init__(self, parent, id=-1, 
199                     value=wx.EmptyString, 
200                     pos=wx.DefaultPosition, 
201                     size=wx.DefaultSize,
202                     style=0, 
203                     validator=wx.DefaultValidator,
204                     name=wx.TextCtrlNameStr,
205                     kill_focus_callback=None,
206                     set_focus_callback=None,
207                     mouse_up_callback=None,
208                     text_enter_callback = None):
209             
210            wx.TextCtrl.__init__(self, parent, id, value, pos,
211                                  size, style, validator, name)
212           
213            # Bind appropriate events
214            self._on_set_focus_callback = parent.onSetFocus \
215                      if set_focus_callback is None else set_focus_callback
216            self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus)
217            self.Bind(wx.EVT_KILL_FOCUS, self._silent_kill_focus \
218                      if kill_focus_callback is None else kill_focus_callback)               
219            self.Bind(wx.EVT_TEXT_ENTER, parent._onparamEnter \
220                      if text_enter_callback is None else text_enter_callback)
221            if not ON_MAC :
222                self.Bind(wx.EVT_LEFT_UP,    self._highlight_text \
223                          if mouse_up_callback is None else mouse_up_callback)
224           
225        def _on_set_focus(self, event):
226            """
227            Catch when the text control is set in focus to highlight the whole
228            text if necessary
229           
230            :param event: mouse event
231           
232            """
233            event.Skip()
234            self.full_selection = True
235            return self._on_set_focus_callback(event)
236       
237 
238           
239        def _highlight_text(self, event):
240            """
241            Highlight text of a TextCtrl only of no text has be selected
242           
243            :param event: mouse event
244           
245            """
246            # Make sure the mouse event is available to other listeners
247            event.Skip()
248            control  = event.GetEventObject()
249            if self.full_selection:
250                self.full_selection = False
251                # Check that we have a TextCtrl
252                if issubclass(control.__class__, wx.TextCtrl):
253                    # Check whether text has been selected,
254                    # if not, select the whole string
255                    (start, end) = control.GetSelection()
256                    if start==end:
257                        control.SetSelection(-1,-1)
258                       
259        def _silent_kill_focus(self,event):
260            """
261            Save the state of the page
262            """
263           
264            event.Skip()
265            pass
266   
267    def set_page_info(self, page_info):
268        """
269        set some page important information at once
270        """
271       ##window_name
272        self.window_name = page_info.window_name
273        ##window_caption
274        self.window_caption = page_info.window_caption
275        ## manager is the fitting plugin
276        self._manager= page_info.manager
277        ## owner of the page (fitting plugin)
278        self.event_owner= page_info.event_owner
279         ## current model
280        self.model = page_info.model
281        ## data
282        self.data = page_info.data
283        ## dictionary containing list of models
284        self.model_list_box = page_info.model_list_box
285        ## Data member to store the dispersion object created
286        self.populate_box(dict=self.model_list_box)
287       
288    def onContextMenu(self, event): 
289        """
290        Retrieve the state selected state
291        """
292        # Skipping the save state functionality for release 0.9.0
293        #return
294   
295        pos = event.GetPosition()
296        pos = self.ScreenToClient(pos)
297       
298        self.PopupMenu(self.popUpMenu, pos) 
299     
300       
301    def onUndo(self, event):
302        """
303        Cancel the previous action
304        """
305        event = PreviousStateEvent(page = self)
306        wx.PostEvent(self.parent, event)
307       
308    def onRedo(self, event):
309        """
310        Restore the previous action cancelled
311        """
312        event = NextStateEvent(page= self)
313        wx.PostEvent(self.parent, event)
314   
315    def define_page_structure(self):
316        """
317        Create empty sizer for a panel
318        """
319        self.vbox  = wx.BoxSizer(wx.VERTICAL)
320        self.sizer0 = wx.BoxSizer(wx.VERTICAL)
321        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
322        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
323        self.sizer3 = wx.BoxSizer(wx.VERTICAL)
324        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
325        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
326        self.sizer6 = wx.BoxSizer(wx.VERTICAL)
327       
328        self.sizer0.SetMinSize((PANEL_WIDTH,-1))
329        self.sizer1.SetMinSize((PANEL_WIDTH,-1))
330        self.sizer2.SetMinSize((PANEL_WIDTH,-1))
331        self.sizer3.SetMinSize((PANEL_WIDTH,-1))
332        self.sizer4.SetMinSize((PANEL_WIDTH,-1))
333        self.sizer5.SetMinSize((PANEL_WIDTH,-1))
334        self.sizer6.SetMinSize((PANEL_WIDTH,-1))
335       
336        self.vbox.Add(self.sizer0)
337        self.vbox.Add(self.sizer1)
338        self.vbox.Add(self.sizer2)
339        self.vbox.Add(self.sizer3)
340        self.vbox.Add(self.sizer4)
341        self.vbox.Add(self.sizer5)
342        self.vbox.Add(self.sizer6)
343       
344    def set_layout(self):
345        """
346        layout
347        """
348        self.vbox.Layout()
349        self.vbox.Fit(self) 
350        self.SetSizer(self.vbox)
351        self.Centre()
352 
353    def set_owner(self,owner):
354        """
355        set owner of fitpage
356       
357        :param owner: the class responsible of plotting
358       
359        """
360        self.event_owner = owner   
361        self.state.event_owner = owner
362       
363    def get_state(self):
364        """
365        """
366        return self.state
367    def get_data(self):
368        """
369        return the current data
370        """
371        return self.data 
372   
373    def set_manager(self, manager):
374        """
375        set panel manager
376       
377        :param manager: instance of plugin fitting
378       
379        """
380        self._manager = manager 
381        self.state.manager = manager
382       
383    def populate_box(self, dict):
384        """
385        Store list of model
386       
387        :param dict: dictionary containing list of models
388       
389        """
390        self.model_list_box = dict
391        self.state.model_list_box = self.model_list_box
392        self.initialize_combox()
393       
394    def initialize_combox(self): 
395        """
396        put default value in the combobox
397        """ 
398        ## fill combox box
399        if self.model_list_box is None:
400            return
401        if len(self.model_list_box) > 0:
402            self._populate_box(self.formfactorbox,
403                               self.model_list_box["Shapes"])
404       
405        if len(self.model_list_box) > 0:
406            self._populate_box(self.structurebox,
407                                self.model_list_box["Structure Factors"])
408            self.structurebox.Insert("None", 0, None)
409            self.structurebox.SetSelection(0)
410            self.structurebox.Hide()
411            self.text2.Hide()
412            self.structurebox.Disable()
413            self.text2.Disable()
414             
415            if self.model.__class__ in self.model_list_box["P(Q)*S(Q)"]:
416                self.structurebox.Show()
417                self.text2.Show()
418                self.structurebox.Enable()
419                self.text2.Enable()           
420               
421    def set_dispers_sizer(self):
422        """
423        fill sizer containing dispersity info
424        """
425        self.sizer4.Clear(True)
426        name="Polydispersity and Orientational Distribution"
427        box_description= wx.StaticBox(self, -1,name)
428        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
429        #----------------------------------------------------
430        self.disable_disp = wx.RadioButton(self, -1, 'Off', (10, 10),
431                                            style=wx.RB_GROUP)
432        self.enable_disp = wx.RadioButton(self, -1, 'On', (10, 30))
433
434        self.disp_help_bt = wx.Button(self,wx.NewId(),'?', size=(20,15))
435        self.disp_help_bt.Bind(wx.EVT_BUTTON, 
436                        self.on_pd_help_clicked,id= self.disp_help_bt.GetId())
437        self.disp_help_bt.SetToolTipString("Helps for Polydispersion.")       
438       
439        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param,
440                     id=self.disable_disp.GetId())
441        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param,
442                   id=self.enable_disp.GetId())
443        #MAC needs SetValue
444        self.disable_disp.SetValue(True)
445        sizer_dispersion = wx.BoxSizer(wx.HORIZONTAL)
446        sizer_dispersion.Add((20,20))
447        name=""#Polydispersity and \nOrientational Distribution "
448        sizer_dispersion.Add(wx.StaticText(self,-1,name))
449        sizer_dispersion.Add(self.enable_disp )
450        sizer_dispersion.Add((20,20))
451        sizer_dispersion.Add(self.disable_disp )
452        sizer_dispersion.Add((25,20))
453        sizer_dispersion.Add(self.disp_help_bt)
454       
455        ## fill a sizer for dispersion         
456        boxsizer1.Add( sizer_dispersion,0,
457                wx.TOP|wx.BOTTOM|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE,border=5)
458        #boxsizer1.Add( (10,10) )
459        #boxsizer1.Add( sizer_select_dispers )
460        self.sizer4_4 = wx.GridBagSizer(6,5)
461
462        boxsizer1.Add( self.sizer4_4  )
463        #-----------------------------------------------------
464        self.sizer4.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
465        self.sizer4_4.Layout()
466        self.sizer4.Layout()
467        self.Layout()
468     
469        self.Refresh()
470        ## saving the state of enable dispersity button
471        self.state.enable_disp= self.enable_disp.GetValue()
472        self.state.disable_disp= self.disable_disp.GetValue()
473        self.SetupScrolling()
474
475   
476    def onResetModel(self, event):
477        """
478        Reset model state
479        """
480        menu = event.GetEventObject()
481        ## post help message for the selected model
482        msg = menu.GetHelpString(event.GetId())
483        msg +=" reloaded"
484        wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
485       
486        name = menu.GetLabel(event.GetId())
487        self._on_select_model_helper()
488       
489        if name in self.saved_states.keys():
490            previous_state = self.saved_states[name]
491            ## reset state of checkbox,textcrtl  and  regular parameters value
492            self.reset_page(previous_state)   
493               
494    def on_preview(self, event):
495        """
496        Report the current fit results
497        """   
498        # Get plot image from plotpanel
499        images, canvases = self.get_images()
500        # get the report dialog
501        self.state.report(images, canvases)
502       
503         
504    def on_save(self, event):   
505        """
506        Save the current state into file
507        """ 
508        self.save_current_state()
509        new_state = self.state.clone()
510        # Ask the user the location of the file to write to.
511        path = None
512        dlg = wx.FileDialog(self, "Choose a file", self._default_save_location,
513                                                 "", "*.fitv", wx.SAVE)
514        if dlg.ShowModal() == wx.ID_OK:
515            path = dlg.GetPath()
516            self._default_save_location = os.path.dirname(path)
517        else:
518            return None
519        #the manager write the state into file
520        self._manager.save_fit_state(filepath=path, fitstate=new_state)
521        return new_state 
522   
523    def _get_time_stamp(self):
524        """
525        return time and date stings
526        """
527        # date and time
528        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
529        current_time= str(hour)+":"+str(minute)+":"+str(second)
530        current_date= str( month)+"/"+str(day)+"/"+str(year)
531        return current_time, current_date
532     
533    def on_bookmark(self, event):
534        """
535        save history of the data and model
536        """
537        if self.model==None:
538            msg="Can not bookmark; Please select Data and Model first..."
539            wx.MessageBox(msg, 'Info')
540            return 
541        self.save_current_state()
542        new_state = self.state.clone()
543        ##Add model state on context menu
544        self.number_saved_state += 1
545        current_time, current_date = self._get_time_stamp()
546        #name= self.model.name+"[%g]"%self.number_saved_state
547        name = "Fitting: %g]" % self.number_saved_state
548        name += self.model.__class__.__name__
549        name += "bookmarked at %s on %s" % (current_time, current_date)
550        self.saved_states[name]= new_state
551       
552        ## Add item in the context menu
553        msg =  "Model saved at %s on %s"%(current_time, current_date)
554         ## post help message for the selected model
555        msg +=" Saved! right click on this page to retrieve this model"
556        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
557       
558        id = wx.NewId()
559        self.popUpMenu.Append(id,name,str(msg))
560        wx.EVT_MENU(self, id, self.onResetModel)
561        wx.PostEvent(self.parent.parent, 
562                     AppendBookmarkEvent(title=name, 
563                                         hint=str(msg), handler=self.onResetModel))
564       
565    def old_on_bookmark(self, event):
566        """
567        save history of the data and model
568        """
569        if self.model==None:
570            msg="Can not bookmark; Please select Data and Model first..."
571            wx.MessageBox(msg, 'Info')
572            return 
573        if hasattr(self,"enable_disp"):
574            self.state.enable_disp = copy.deepcopy(self.enable_disp.GetValue())
575        if hasattr(self, "disp_box"):
576            self.state.disp_box = copy.deepcopy(self.disp_box.GetSelection())
577
578        self.state.model.name= self.model.name
579       
580        #Remember fit engine_type for fit panel
581        if self.engine_type == None: 
582            self.engine_type = "scipy"
583        if self._manager !=None:
584            self._manager._on_change_engine(engine=self.engine_type)
585       
586            self.state.engine_type = self.engine_type
587
588        new_state = self.state.clone()
589        new_state.model.name = self.state.model.name
590       
591        new_state.enable2D = copy.deepcopy(self.enable2D)
592        ##Add model state on context menu
593        self.number_saved_state += 1
594        #name= self.model.name+"[%g]"%self.number_saved_state
595        name= self.model.__class__.__name__+"[%g]"%self.number_saved_state
596        self.saved_states[name]= new_state
597       
598        ## Add item in the context menu
599       
600        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.localtime()
601        my_time= str(hour)+" : "+str(minute)+" : "+str(second)+" "
602        date= str( month)+"|"+str(day)+"|"+str(year)
603        msg=  "Model saved at %s on %s"%(my_time, date)
604         ## post help message for the selected model
605        msg +=" Saved! right click on this page to retrieve this model"
606        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
607       
608        id = wx.NewId()
609        self.popUpMenu.Append(id,name,str(msg))
610        wx.EVT_MENU(self, id, self.onResetModel)
611       
612    def onSetFocus(self, evt):
613        """
614        highlight the current textcrtl and hide the error text control shown
615        after fitting
616        """
617        return
618   
619    def read_file(self, path):
620        """
621        Read two columns file
622       
623        :param path: the path to the file to read
624       
625        """
626        try:
627            if path==None:
628                wx.PostEvent(self.parent.parent, StatusEvent(status=\
629                            " Selected Distribution was not loaded: %s"%path))
630                return None, None
631            input_f = open(path, 'r')
632            buff = input_f.read()
633            lines = buff.split('\n')
634           
635            angles = []
636            weights=[]
637            for line in lines:
638                toks = line.split()
639                try:
640                    angle = float(toks[0])
641                    weight = float(toks[1])
642                except:
643                    # Skip non-data lines
644                    pass
645                angles.append(angle)
646                weights.append(weight)
647            return numpy.array(angles), numpy.array(weights)
648        except:
649            raise 
650
651    def createMemento(self):
652        """
653        return the current state of the page
654        """
655        return self.state.clone()
656   
657   
658    def save_current_state(self):
659        """
660        Store current state
661        """
662        self.state.engine_type = copy.deepcopy(self.engine_type)
663        ## save model option
664        if self.model!= None:
665            self.disp_list= self.model.getDispParamList()
666            self.state.disp_list= copy.deepcopy(self.disp_list)
667            self.state.model = self.model.clone()
668        #save radiobutton state for model selection
669        self.state.shape_rbutton = self.shape_rbutton.GetValue()
670        self.state.shape_indep_rbutton = self.shape_indep_rbutton.GetValue()
671        self.state.struct_rbutton = self.struct_rbutton.GetValue()
672        self.state.plugin_rbutton = self.plugin_rbutton.GetValue()
673        #model combobox
674        self.state.structurebox = self.structurebox.GetSelection()
675        self.state.formfactorbox = self.formfactorbox.GetSelection()
676       
677        self.state.enable2D = copy.deepcopy(self.enable2D)
678        self.state.values= copy.deepcopy(self.values)
679        self.state.weights = copy.deepcopy( self.weights)
680        ## save data   
681        self.state.data= copy.deepcopy(self.data)
682        self.state.qmax_x = self.qmax_x
683        self.state.qmin_x = self.qmin_x
684     
685        if hasattr(self,"enable_disp"):
686            self.state.enable_disp= self.enable_disp.GetValue()
687            self.state.disable_disp = self.disable_disp.GetValue()
688           
689        self.state.smearer = copy.deepcopy(self.smearer)
690        if hasattr(self,"enable_smearer"):
691            self.state.enable_smearer = \
692                                copy.deepcopy(self.enable_smearer.GetValue())
693            self.state.disable_smearer = \
694                                copy.deepcopy(self.disable_smearer.GetValue())
695
696        self.state.pinhole_smearer = \
697                                copy.deepcopy(self.pinhole_smearer.GetValue())
698        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 
699                 
700        if len(self._disp_obj_dict)>0:
701            for k , v in self._disp_obj_dict.iteritems():
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        self.state.str_parameters = []
716
717       
718        ## save checkbutton state and txtcrtl values
719        self._copy_parameters_state(self.str_parameters, 
720                                    self.state.str_parameters)
721        self._copy_parameters_state(self.orientation_params,
722                                     self.state.orientation_params)
723        self._copy_parameters_state(self.orientation_params_disp,
724                                     self.state.orientation_params_disp)
725       
726        self._copy_parameters_state(self.parameters, self.state.parameters)
727        self._copy_parameters_state(self.fittable_param,
728                                     self.state.fittable_param)
729        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
730        #save chisqr
731        self.state.tcChi = self.tcChi.GetValue()
732       
733    def save_current_state_fit(self):
734        """
735        Store current state for fit_page
736        """
737        ## save model option
738        if self.model!= None:
739            self.disp_list= self.model.getDispParamList()
740            self.state.disp_list= copy.deepcopy(self.disp_list)
741            self.state.model = self.model.clone()
742        if hasattr(self, "engine_type"):
743            self.state.engine_type = copy.deepcopy(self.engine_type)
744           
745        self.state.enable2D = copy.deepcopy(self.enable2D)
746        self.state.values= copy.deepcopy(self.values)
747        self.state.weights = copy.deepcopy( self.weights)
748        ## save data   
749        self.state.data= copy.deepcopy(self.data)
750       
751        if hasattr(self,"enable_disp"):
752            self.state.enable_disp= self.enable_disp.GetValue()
753            self.state.disable_disp = self.disable_disp.GetValue()
754           
755        self.state.smearer = copy.deepcopy(self.smearer)
756        if hasattr(self,"enable_smearer"):
757            self.state.enable_smearer = \
758                                copy.deepcopy(self.enable_smearer.GetValue())
759            self.state.disable_smearer = \
760                                copy.deepcopy(self.disable_smearer.GetValue())
761           
762        self.state.pinhole_smearer = \
763                                copy.deepcopy(self.pinhole_smearer.GetValue())
764        self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 
765           
766        if hasattr(self,"disp_box"):
767            self.state.disp_box = self.disp_box.GetCurrentSelection()
768
769            if len(self.disp_cb_dict) > 0:
770                for k, v in self.disp_cb_dict.iteritems():
771         
772                    if v == None :
773                        self.state.disp_cb_dict[k] = v
774                    else:
775                        try:
776                            self.state.disp_cb_dict[k] = v.GetValue()
777                        except:
778                            self.state.disp_cb_dict[k] = None
779           
780            if len(self._disp_obj_dict) > 0:
781                for k , v in self._disp_obj_dict.iteritems():
782     
783                    self.state._disp_obj_dict[k] = v
784                       
785           
786            self.state.values = copy.deepcopy(self.values)
787            self.state.weights = copy.deepcopy(self.weights)
788           
789        ## save plotting range
790        self._save_plotting_range()
791       
792        ## save checkbutton state and txtcrtl values
793        self._copy_parameters_state(self.orientation_params,
794                                     self.state.orientation_params)
795        self._copy_parameters_state(self.orientation_params_disp,
796                                     self.state.orientation_params_disp)
797        self._copy_parameters_state(self.parameters, self.state.parameters)
798        self._copy_parameters_state(self.fittable_param,
799                                             self.state.fittable_param)
800        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
801   
802         
803    def check_invalid_panel(self): 
804        """
805        check if the user can already perform some action with this panel
806        """ 
807        flag = False
808        if self.data is None:
809            self.disable_smearer.SetValue(True)
810            self.disable_disp.SetValue(True)
811            msg = "Please load Data and select Model to start..."
812            wx.MessageBox(msg, 'Info')
813            return  True
814       
815    def set_model_state(self, state):
816        """
817        reset page given a model state
818        """
819        self.disp_cb_dict = state.disp_cb_dict
820        self.disp_list = state.disp_list
821     
822        ## set the state of the radio box
823        self.shape_rbutton.SetValue(state.shape_rbutton )
824        self.shape_indep_rbutton.SetValue(state.shape_indep_rbutton)
825        self.struct_rbutton.SetValue(state.struct_rbutton)
826        self.plugin_rbutton.SetValue(state.plugin_rbutton)
827       
828        ## fill model combobox
829        self._show_combox_helper()
830        #select the current model
831        self.formfactorbox.Select(int(state.formfactorcombobox))
832        self.structurebox.SetSelection(state.structurecombobox )
833        if state.multi_factor != None:
834            self.multifactorbox.SetSelection(state.multi_factor)
835           
836         ## reset state of checkbox,textcrtl  and  regular parameters value
837        self._reset_parameters_state(self.orientation_params_disp,
838                                     state.orientation_params_disp)
839        self._reset_parameters_state(self.orientation_params,
840                                     state.orientation_params)
841        self._reset_parameters_state(self.str_parameters,
842                                     state.str_parameters)
843        self._reset_parameters_state(self.parameters,state.parameters)
844         ## display dispersion info layer       
845        self.enable_disp.SetValue(state.enable_disp)
846        self.disable_disp.SetValue(state.disable_disp)
847       
848        if hasattr(self, "disp_box"):
849           
850            self.disp_box.SetSelection(state.disp_box) 
851            n= self.disp_box.GetCurrentSelection()
852            dispersity= self.disp_box.GetClientData(n)
853            name = dispersity.__name__     
854
855            self._set_dipers_Param(event=None)
856       
857            if name == "ArrayDispersion":
858               
859                for item in self.disp_cb_dict.keys():
860                   
861                    if hasattr(self.disp_cb_dict[item], "SetValue") :
862                        self.disp_cb_dict[item].SetValue(\
863                                                    state.disp_cb_dict[item])
864                        # Create the dispersion objects
865                        from sans.models.dispersion_models import ArrayDispersion
866                        disp_model = ArrayDispersion()
867                        if hasattr(state,"values")and\
868                                 self.disp_cb_dict[item].GetValue() == True:
869                            if len(state.values)>0:
870                                self.values=state.values
871                                self.weights=state.weights
872                                disp_model.set_weights(self.values,
873                                                        state.weights)
874                            else:
875                                self._reset_dispersity()
876                       
877                        self._disp_obj_dict[item] = disp_model
878                        # Set the new model as the dispersion object
879                        #for the selected parameter
880                        self.model.set_dispersion(item, disp_model)
881                   
882                        self.model._persistency_dict[item] = \
883                                                [state.values, state.weights]
884                   
885            else:
886                keys = self.model.getParamList()
887                for item in keys:
888                    if item in self.disp_list and \
889                        not self.model.details.has_key(item):
890                        self.model.details[item] = ["", None, None]
891                for k,v in self.state.disp_cb_dict.iteritems():
892                    self.disp_cb_dict = copy.deepcopy(state.disp_cb_dict) 
893                    self.state.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
894         ## smearing info  restore
895        if hasattr(self, "enable_smearer"):
896            ## set smearing value whether or not the data
897            #contain the smearing info
898            self.enable_smearer.SetValue(state.enable_smearer)
899            self.disable_smearer.SetValue(state.disable_smearer)
900            self.onSmear(event=None)           
901        self.pinhole_smearer.SetValue(state.pinhole_smearer)
902        self.slit_smearer.SetValue(state.slit_smearer)
903        ## we have two more options for smearing
904        if self.pinhole_smearer.GetValue(): self.onPinholeSmear(event=None)
905        elif self.slit_smearer.GetValue(): self.onSlitSmear(event=None)
906       
907        ## reset state of checkbox,textcrtl  and dispersity parameters value
908        self._reset_parameters_state(self.fittable_param,state.fittable_param)
909        self._reset_parameters_state(self.fixed_param,state.fixed_param)
910       
911        ## draw the model with previous parameters value
912        self._onparamEnter_helper()
913        self.select_param(event=None) 
914        #Save state_fit
915        self.save_current_state_fit()
916        self._lay_out()
917        self.Refresh()
918       
919    def reset_page_helper(self, state):
920        """
921        Use page_state and change the state of existing page
922       
923        :precondition: the page is already drawn or created
924       
925        :postcondition: the state of the underlying data change as well as the
926            state of the graphic interface
927        """
928        if state == None:
929            #self._undo.Enable(False)
930            return 
931        # set data, etc. from the state
932        # reset page between theory and fitting from bookmarking
933        #if state.data == None:
934        #    data = None
935        #else:
936        data = state.data
937
938        #if data != None:
939       
940        if data == None:
941            data_min = state.qmin
942            data_max = state.qmax
943            self.qmin_x = data_min
944            self.qmax_x = data_max
945            self.minimum_q.SetValue(str(data_min))
946            self.maximum_q.SetValue(str(data_max))
947            self.qmin.SetValue(str(data_min))
948            self.qmax.SetValue(str(data_max))
949
950            self.state.data = data
951            self.state.qmin = self.qmin_x
952            self.state.qmax = self.qmax_x
953        else:
954            self.set_data(data)
955           
956        self.enable2D= state.enable2D
957        self.engine_type = state.engine_type
958
959        self.disp_cb_dict = state.disp_cb_dict
960        self.disp_list = state.disp_list
961     
962        ## set the state of the radio box
963        self.shape_rbutton.SetValue(state.shape_rbutton )
964        self.shape_indep_rbutton.SetValue(state.shape_indep_rbutton)
965        self.struct_rbutton.SetValue(state.struct_rbutton)
966        self.plugin_rbutton.SetValue(state.plugin_rbutton)
967       
968        ## fill model combobox
969        self._show_combox_helper()
970        #select the current model
971        self.formfactorbox.Select(int(state.formfactorcombobox))
972        self.structurebox.SetSelection(state.structurecombobox )
973        if state.multi_factor != None:
974            self.multifactorbox.SetSelection(state.multi_factor)
975
976        #reset the fitting engine type
977        self.engine_type = state.engine_type
978        #draw the pnael according to the new model parameter
979        self._on_select_model(event=None)
980        # take care of 2D button
981        if data == None and self.model_view.IsEnabled():
982            if self.enable2D:
983                self.model_view.SetLabel("Switch to 1D")
984            else:
985                self.model_view.SetLabel("Switch to 2D")
986        # else:
987               
988        if self._manager !=None:
989            self._manager._on_change_engine(engine=self.engine_type)
990        ## set the select all check box to the a given state
991        self.cb1.SetValue(state.cb1)
992     
993        ## reset state of checkbox,textcrtl  and  regular parameters value
994        self._reset_parameters_state(self.orientation_params_disp,
995                                     state.orientation_params_disp)
996        self._reset_parameters_state(self.orientation_params,
997                                     state.orientation_params)
998        self._reset_parameters_state(self.str_parameters,
999                                     state.str_parameters)
1000        self._reset_parameters_state(self.parameters,state.parameters)   
1001         ## display dispersion info layer       
1002        self.enable_disp.SetValue(state.enable_disp)
1003        self.disable_disp.SetValue(state.disable_disp)
1004        # If the polydispersion is ON
1005        if state.enable_disp:
1006            # reset dispersion according the state
1007            self._set_dipers_Param(event=None)
1008            self._reset_page_disp_helper(state)
1009        ##plotting range restore   
1010        self._reset_plotting_range(state)
1011        ## smearing info  restore
1012        if hasattr(self, "enable_smearer"):
1013            ## set smearing value whether or not the data
1014            #contain the smearing info
1015            self.enable_smearer.SetValue(state.enable_smearer)
1016            self.disable_smearer.SetValue(state.disable_smearer)
1017            self.onSmear(event=None)           
1018        self.pinhole_smearer.SetValue(state.pinhole_smearer)
1019        self.slit_smearer.SetValue(state.slit_smearer)
1020        ## we have two more options for smearing
1021        if self.pinhole_smearer.GetValue(): self.onPinholeSmear(event=None)
1022        elif self.slit_smearer.GetValue(): self.onSlitSmear(event=None)
1023       
1024        ## reset state of checkbox,textcrtl  and dispersity parameters value
1025        self._reset_parameters_state(self.fittable_param,state.fittable_param)
1026        self._reset_parameters_state(self.fixed_param,state.fixed_param)
1027       
1028        ## draw the model with previous parameters value
1029        self._onparamEnter_helper()
1030        #reset the value of chisqr when not consistent with the value computed
1031        self.tcChi.SetValue(str(self.state.tcChi))
1032        ## reset context menu items
1033        self._reset_context_menu()
1034       
1035        ## set the value of the current state to the state given as parameter
1036        self.state = state.clone() 
1037   
1038    def _reset_page_disp_helper(self, state):
1039        """
1040        Help to rest page for dispersions
1041        """
1042        keys = self.model.getParamList()
1043        for item in keys:
1044            if item in self.disp_list and \
1045                not self.model.details.has_key(item):
1046                self.model.details[item] = ["", None, None]
1047        #for k,v in self.state.disp_cb_dict.iteritems():
1048        self.disp_cb_dict = copy.deepcopy(state.disp_cb_dict) 
1049        self.state.disp_cb_dict = copy.deepcopy(state.disp_cb_dict)
1050        self.values = copy.deepcopy(state.values)
1051        self.weights = copy.deepcopy(state.weights)
1052       
1053        for key, disp in state._disp_obj_dict.iteritems():
1054            # From saved file, disp_model can not be sent in model obj.
1055            # it will be sent as a string here, then converted to model object.
1056            if disp.__class__.__name__ == 'str':
1057                com_str  = "from sans.models.dispersion_models "
1058                com_str += "import %s as disp_func"
1059                exec com_str % disp
1060                disp_model = disp_func()
1061            else:
1062                disp_model = disp
1063
1064            self._disp_obj_dict[key] = disp_model
1065            param_name = key.split('.')[0]
1066            # Try to set dispersion only when available
1067            # for eg., pass the orient. angles for 1D Cal
1068            try:
1069                self.model.set_dispersion(param_name, disp_model)
1070                self.model._persistency_dict[key] = \
1071                                 [state.values, state.weights]
1072            except:
1073                pass
1074            selection = self._find_polyfunc_selection(disp_model)
1075            for list in self.fittable_param:
1076                if list[1] == key and list[7] != None:
1077                    list[7].SetSelection(selection)
1078                    # For the array disp_model, set the values and weights
1079                    if selection == 1:
1080                        disp_model.set_weights(self.values[key], 
1081                                              self.weights[key])
1082                        try:
1083                            # Diables all fittable params for array
1084                            list[0].SetValue(False)
1085                            list[0].Disable()
1086                            list[2].Disable()
1087                            list[5].Disable()
1088                            list[6].Disable()
1089                        except:
1090                            pass
1091            # For array, disable all fixed params
1092            if selection == 1:
1093                for item in self.fixed_param:
1094                    if item[1].split(".")[0] == key.split(".")[0]:
1095                        # try it and pass it for the orientation for 1D
1096                        try:
1097                            item[2].Disable()
1098                        except:
1099                            pass
1100   
1101        # Make sure the check box updated when all checked
1102        if self.cb1.GetValue():
1103            self.select_all_param(None)       
1104     
1105    def _selectDlg(self):
1106        """
1107        open a dialog file to selected the customized dispersity
1108        """
1109        import os
1110        dlg = wx.FileDialog(self, "Choose a weight file",
1111                                self._default_save_location , "", 
1112                                "*.*", wx.OPEN)
1113        path = None
1114        if dlg.ShowModal() == wx.ID_OK:
1115            path = dlg.GetPath()
1116        dlg.Destroy()
1117        return path
1118
1119    def _reset_context_menu(self):
1120        """
1121        reset the context menu
1122        """
1123        for name, state in self.state.saved_states.iteritems():
1124            self.number_saved_state += 1
1125            ## Add item in the context menu
1126            id = wx.NewId()
1127            msg = 'Save model and state %g' % self.number_saved_state
1128            self.popUpMenu.Append(id, name, msg)
1129            wx.EVT_MENU(self, id, self.onResetModel)
1130   
1131    def _reset_plotting_range(self, state):
1132        """
1133        Reset the plotting range to a given state
1134        """
1135        # if self.check_invalid_panel():
1136        #    return
1137        self.qmin.SetValue(str(state.qmin))
1138        self.qmax.SetValue(str(state.qmax)) 
1139
1140    def _save_typeOfmodel(self):
1141        """
1142        save radiobutton containing the type model that can be selected
1143        """
1144        self.state.shape_rbutton = self.shape_rbutton.GetValue()
1145        self.state.shape_indep_rbutton = self.shape_indep_rbutton.GetValue()
1146        self.state.struct_rbutton = self.struct_rbutton.GetValue()
1147        self.state.plugin_rbutton = self.plugin_rbutton.GetValue()
1148        self.state.structurebox= self.structurebox.GetCurrentSelection()
1149        self.state.formfactorbox = self.formfactorbox.GetCurrentSelection()
1150       
1151        #self._undo.Enable(True)
1152        ## post state to fit panel
1153        event = PageInfoEvent(page = self)
1154        wx.PostEvent(self.parent, event)
1155       
1156    def _save_plotting_range(self ):
1157        """
1158        save the state of plotting range
1159        """
1160        self.state.qmin = self.qmin_x
1161        self.state.qmax = self.qmax_x
1162        self.state.npts = self.npts_x
1163           
1164    def _onparamEnter_helper(self):
1165        """
1166        check if values entered by the user are changed and valid to replot
1167        model
1168        """
1169        # Flag to register when a parameter has changed.   
1170        is_modified = False
1171        self.fitrange = True
1172        is_2Ddata = False
1173        #self._undo.Enable(True)
1174        # check if 2d data
1175        if self.data.__class__.__name__ == "Data2D":
1176            is_2Ddata = True
1177        if self.model !=None:
1178            try:
1179                is_modified = self._check_value_enter(self.fittable_param,
1180                                                     is_modified)
1181                is_modified = self._check_value_enter(self.fixed_param,
1182                                                      is_modified)
1183                is_modified = self._check_value_enter(self.parameters,
1184                                                      is_modified) 
1185            except:
1186                pass
1187            #if is_modified:
1188
1189            # Here we should check whether the boundaries have been modified.
1190            # If qmin and qmax have been modified, update qmin and qmax and
1191            # set the is_modified flag to True
1192            if self._validate_qrange(self.qmin, self.qmax):
1193                tempmin = float(self.qmin.GetValue())
1194                if tempmin != self.qmin_x:
1195                    self.qmin_x = tempmin
1196                    is_modified = True
1197                tempmax = float(self.qmax.GetValue())
1198                if tempmax != self.qmax_x:
1199                    self.qmax_x = tempmax
1200                    is_modified = True
1201           
1202                if is_2Ddata:
1203                    # set mask   
1204                    is_modified = self._validate_Npts()
1205                   
1206            else:
1207                self.fitrange = False   
1208           
1209            ## if any value is modify draw model with new value
1210            if not self.fitrange:
1211                #self.btFit.Disable()
1212                if is_2Ddata: self.btEditMask.Disable()
1213            else:
1214                #self.btFit.Enable(True)
1215                if is_2Ddata: self.btEditMask.Enable(True)
1216            if is_modified and self.fitrange:
1217                if self.data == None:
1218                    # Theory case: need to get npts value to draw
1219                    self.npts_x = float(self.Npts_total.GetValue())
1220                self.state_change= True
1221                self._draw_model() 
1222                self.Refresh()
1223        return is_modified
1224   
1225    def _update_paramv_on_fit(self):
1226        """
1227        make sure that update param values just before the fitting
1228        """
1229        #flag for qmin qmax check values
1230        flag = True
1231        self.fitrange = True
1232        is_modified = False
1233
1234        #wx.PostEvent(self._manager.parent, StatusEvent(status=" \
1235        #updating ... ",type="update"))
1236
1237        ##So make sure that update param values on_Fit.
1238        #self._undo.Enable(True)
1239        if self.model !=None:           
1240            ##Check the values
1241            self._check_value_enter( self.fittable_param ,is_modified)
1242            self._check_value_enter( self.fixed_param ,is_modified)
1243            self._check_value_enter( self.parameters ,is_modified)
1244
1245            # If qmin and qmax have been modified, update qmin and qmax and
1246             # Here we should check whether the boundaries have been modified.
1247            # If qmin and qmax have been modified, update qmin and qmax and
1248            # set the is_modified flag to True
1249            self.fitrange = self._validate_qrange(self.qmin, self.qmax)
1250            if self.fitrange:
1251                tempmin = float(self.qmin.GetValue())
1252                if tempmin != self.qmin_x:
1253                    self.qmin_x = tempmin
1254                tempmax = float(self.qmax.GetValue())
1255                if tempmax != self.qmax_x:
1256                    self.qmax_x = tempmax
1257                if tempmax == tempmin:
1258                    flag = False   
1259                temp_smearer = None
1260                if not self.disable_smearer.GetValue():
1261                    temp_smearer= self.current_smearer
1262                    if self.slit_smearer.GetValue():
1263                        flag = self.update_slit_smear()
1264                    elif self.pinhole_smearer.GetValue():
1265                        flag = self.update_pinhole_smear()
1266                    else:
1267                        self._manager.set_smearer(smearer=temp_smearer,
1268                                                  uid=self.uid,
1269                                                     qmin=float(self.qmin_x),
1270                                                      qmax=float(self.qmax_x),
1271                                                      draw=False)
1272                elif not self._is_2D():
1273                    self._manager.set_smearer(smearer=temp_smearer,
1274                                              qmin=float(self.qmin_x),
1275                                              uid=self.uid, 
1276                                                 qmax= float(self.qmax_x))
1277                    if self.data != None:
1278                        index_data = ((self.qmin_x <= self.data.x)&\
1279                                      (self.data.x <= self.qmax_x))
1280                        val = str(len(self.data.x[index_data==True]))
1281                        self.Npts_fit.SetValue(val)
1282                    else:
1283                        # No data in the panel
1284                        try:
1285                            self.npts_x = float(self.Npts_total.GetValue())
1286                        except:
1287                            flag = False
1288                            return flag
1289                    flag = True
1290                if self._is_2D():
1291                    # only 2D case set mask 
1292                    flag = self._validate_Npts()
1293                    if not flag:
1294                        return flag
1295            else: flag = False
1296        else: 
1297            flag = False
1298
1299        #For invalid q range, disable the mask editor and fit button, vs.   
1300        if not self.fitrange:
1301            #self.btFit.Disable()
1302            if self._is_2D():self.btEditMask.Disable()
1303        else:
1304            #self.btFit.Enable(True)
1305            if self._is_2D():self.btEditMask.Enable(True)
1306
1307        if not flag:
1308            msg = "Cannot Plot or Fit :Must select a "
1309            msg += " model or Fitting range is not valid!!!  "
1310            wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1311       
1312        self.save_current_state()
1313   
1314        return flag                           
1315               
1316    def _is_modified(self, is_modified):
1317        """
1318        return to self._is_modified
1319        """
1320        return is_modified
1321                       
1322    def _reset_parameters_state(self, listtorestore, statelist):
1323        """
1324        Reset the parameters at the given state
1325        """
1326        if len(statelist) == 0 or len(listtorestore) == 0:
1327            return
1328        if len(statelist) !=  len(listtorestore):
1329            return
1330
1331        for j in range(len(listtorestore)):
1332            item_page = listtorestore[j]
1333            item_page_info = statelist[j]
1334            ##change the state of the check box for simple parameters
1335            if item_page[0]!=None:   
1336                item_page[0].SetValue(item_page_info[0])
1337            if item_page[2]!=None:
1338                item_page[2].SetValue(item_page_info[2])
1339                if item_page[2].__class__.__name__ == "ComboBox":
1340                   if self.model.fun_list.has_key(item_page_info[2]):
1341                       fun_val = self.model.fun_list[item_page_info[2]]
1342                       self.model.setParam(item_page_info[1],fun_val)
1343            if item_page[3]!=None:
1344                ## show or hide text +/-
1345                if item_page_info[2]:
1346                    item_page[3].Show(True)
1347                else:
1348                    item_page[3].Hide()
1349            if item_page[4]!=None:
1350                ## show of hide the text crtl for fitting error
1351                if item_page_info[4][0]:
1352                    item_page[4].Show(True)
1353                    item_page[4].SetValue(item_page_info[4][1])
1354                else:
1355                    item_page[3].Hide()
1356            if item_page[5]!=None:
1357                ## show of hide the text crtl for fitting error
1358                item_page[5].Show(item_page_info[5][0])
1359                item_page[5].SetValue(item_page_info[5][1])
1360               
1361            if item_page[6]!=None:
1362                ## show of hide the text crtl for fitting error
1363                item_page[6].Show(item_page_info[6][0])
1364                item_page[6].SetValue(item_page_info[6][1])
1365
1366                   
1367    def _reset_strparam_state(self, listtorestore, statelist):
1368        """
1369        Reset the string parameters at the given state
1370        """
1371        if len(statelist) == 0:
1372            return
1373
1374        listtorestore = copy.deepcopy(statelist)
1375       
1376        for j in range(len(listtorestore)):
1377            item_page = listtorestore[j]
1378            item_page_info = statelist[j]
1379            ##change the state of the check box for simple parameters
1380           
1381            if item_page[0] != None:   
1382                item_page[0].SetValue(format_number(item_page_info[0], True))
1383
1384            if item_page[2] != None:
1385                param_name = item_page_info[1]
1386                value = item_page_info[2]
1387                selection = value
1388                if self.model.fun_list.has_key(value):
1389                    selection = self.model.fun_list[value]
1390                item_page[2].SetValue(selection)
1391                self.model.setParam(param_name, selection)
1392                                     
1393    def _copy_parameters_state(self, listtocopy, statelist):
1394        """
1395        copy the state of button
1396       
1397        :param listtocopy: the list of check button to copy
1398        :param statelist: list of state object to store the current state
1399       
1400        """
1401        if len(listtocopy)==0:
1402            return
1403       
1404        for item in listtocopy:
1405 
1406            checkbox_state = None
1407            if item[0]!= None:
1408                checkbox_state= item[0].GetValue()
1409            parameter_name = item[1]
1410            parameter_value = None
1411            if item[2]!=None:
1412                parameter_value = item[2].GetValue()
1413            static_text = None
1414            if item[3]!=None:
1415                static_text = item[3].IsShown()
1416            error_value = None
1417            error_state = None
1418            if item[4]!= None:
1419                error_value = item[4].GetValue()
1420                error_state = item[4].IsShown()
1421               
1422            min_value = None
1423            min_state = None
1424            if item[5]!= None:
1425                min_value = item[5].GetValue()
1426                min_state = item[5].IsShown()
1427               
1428            max_value = None
1429            max_state = None
1430            if item[6]!= None:
1431                max_value = item[6].GetValue()
1432                max_state = item[6].IsShown()
1433            unit=None
1434            if item[7]!=None:
1435                unit = item[7].GetLabel()
1436               
1437            statelist.append([checkbox_state, parameter_name, parameter_value,
1438                              static_text ,[error_state, error_value],
1439                                [min_state, min_value],
1440                                [max_state, max_value], unit])
1441           
1442    def _set_model_sizer_selection(self, model):
1443        """
1444        Display the sizer according to the type of the current model
1445        """
1446        if model == None:
1447            return
1448        if hasattr(model ,"s_model"):
1449           
1450            class_name = model.s_model.__class__
1451            name = model.s_model.name
1452            flag = (name != "NoStructure")
1453            if flag and \
1454                (class_name in self.model_list_box["Structure Factors"]):
1455                self.structurebox.Show()
1456                self.text2.Show()               
1457                self.structurebox.Enable()
1458                self.text2.Enable()
1459                items = self.structurebox.GetItems()
1460                self.sizer1.Layout()
1461               
1462                for i in range(len(items)):
1463                    if items[i]== str(name):
1464                        self.structurebox.SetSelection(i)
1465                        break
1466                   
1467        if hasattr(model ,"p_model"):
1468            class_name = model.p_model.__class__
1469            name = model.p_model.name
1470            self.formfactorbox.Clear()
1471           
1472            for k, list in self.model_list_box.iteritems():
1473                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
1474                    self.shape_rbutton.SetValue(True)
1475                    ## fill the form factor list with new model
1476                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
1477                    items = self.formfactorbox.GetItems()
1478                    ## set comboxbox to the selected item
1479                    for i in range(len(items)):
1480                        if items[i]== str(name):
1481                            self.formfactorbox.SetSelection(i)
1482                            break
1483                    return
1484                elif k == "Shape-Independent":
1485                    self.shape_indep_rbutton.SetValue(True)
1486                elif k == "Structure Factors":
1487                     self.struct_rbutton.SetValue(True)
1488                elif  k == "Multi-Functions":
1489                    continue
1490                else:
1491                    self.plugin_rbutton.SetValue(True)
1492               
1493                if class_name in list:
1494                    ## fill the form factor list with new model
1495                    self._populate_box(self.formfactorbox, list)
1496                    items = self.formfactorbox.GetItems()
1497                    ## set comboxbox to the selected item
1498                    for i in range(len(items)):
1499                        if items[i]== str(name):
1500                            self.formfactorbox.SetSelection(i)
1501                            break
1502                    break
1503        else:
1504
1505            ## Select the model from the menu
1506            class_name = model.__class__
1507            name = model.name
1508            self.formfactorbox.Clear()
1509            items = self.formfactorbox.GetItems()
1510   
1511            for k, list in self.model_list_box.iteritems():         
1512                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
1513                    if class_name in self.model_list_box["P(Q)*S(Q)"]:
1514                        self.structurebox.Show()
1515                        self.text2.Show()
1516                        self.structurebox.Enable()
1517                        self.structurebox.SetSelection(0)
1518                        self.text2.Enable()
1519                    else:
1520                        self.structurebox.Hide()
1521                        self.text2.Hide()
1522                        self.structurebox.Disable()
1523                        self.structurebox.SetSelection(0)
1524                        self.text2.Disable()
1525                       
1526                    self.shape_rbutton.SetValue(True)
1527                    ## fill the form factor list with new model
1528                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
1529                    items = self.formfactorbox.GetItems()
1530                    ## set comboxbox to the selected item
1531                    for i in range(len(items)):
1532                        if items[i]== str(name):
1533                            self.formfactorbox.SetSelection(i)
1534                            break
1535                    return
1536                elif k == "Shape-Independent":
1537                    self.shape_indep_rbutton.SetValue(True)
1538                elif k == "Structure Factors":
1539                    self.struct_rbutton.SetValue(True)
1540                elif  k == "Multi-Functions":
1541                    continue
1542                else:
1543                    self.plugin_rbutton.SetValue(True)
1544                if class_name in list:
1545                    self.structurebox.SetSelection(0)
1546                    self.structurebox.Disable()
1547                    self.text2.Disable()                   
1548                    ## fill the form factor list with new model
1549                    self._populate_box(self.formfactorbox, list)
1550                    items = self.formfactorbox.GetItems()
1551                    ## set comboxbox to the selected item
1552                    for i in range(len(items)):
1553                        if items[i]== str(name):
1554                            self.formfactorbox.SetSelection(i)
1555                            break
1556                    break
1557   
1558    def _draw_model(self, update_chisqr=True):
1559        """
1560        Method to draw or refresh a plotted model.
1561        The method will use the data member from the model page
1562        to build a call to the fitting perspective manager.
1563       
1564        :param chisqr: update chisqr value [bool]
1565        """
1566        #if self.check_invalid_panel():
1567        #    return
1568        if self.model !=None:
1569            temp_smear=None
1570            if hasattr(self, "enable_smearer"):
1571                if not self.disable_smearer.GetValue():
1572                    temp_smear= self.current_smearer
1573            toggle_mode_on = self.model_view.IsEnabled()
1574            self._manager.draw_model(self.model, 
1575                                    data=self.data,
1576                                    smearer= temp_smear,
1577                                    qmin=float(self.qmin_x), 
1578                                    qmax=float(self.qmax_x),
1579                                    qstep= float(self.npts_x),
1580                                    page_id=self.uid,
1581                                    toggle_mode_on=toggle_mode_on, 
1582                                    state = self.state,
1583                                    enable2D=self.enable2D,
1584                                    update_chisqr=update_chisqr)
1585       
1586       
1587    def _on_show_sld(self, event=None):
1588        """
1589        Plot SLD profile
1590        """
1591        # get profile data
1592        x,y=self.model.getProfile()
1593
1594        from danse.common.plottools import Data1D
1595        #from sans.perspectives.theory.profile_dialog import SLDPanel
1596        from sans.guiframe.local_perspectives.plotting.profile_dialog \
1597        import SLDPanel
1598        sld_data = Data1D(x,y)
1599        sld_data.name = 'SLD'
1600        sld_data.axes = self.sld_axes
1601        self.panel = SLDPanel(self, data=sld_data,axes =self.sld_axes,id =-1 )
1602        self.panel.ShowModal()   
1603       
1604    def _set_multfactor_combobox(self, multiplicity=10):   
1605        """
1606        Set comboBox for muitfactor of CoreMultiShellModel
1607        :param multiplicit: no. of multi-functionality
1608        """
1609        # build content of the combobox
1610        for idx in range(0,multiplicity):
1611            self.multifactorbox.Append(str(idx),int(idx))
1612            #self.multifactorbox.SetSelection(1)
1613        self._hide_multfactor_combobox()
1614       
1615    def _show_multfactor_combobox(self):   
1616        """
1617        Show the comboBox of muitfactor of CoreMultiShellModel
1618        """ 
1619        if not self.mutifactor_text.IsShown():
1620            self.mutifactor_text.Show(True)
1621            self.mutifactor_text1.Show(True)
1622        if not self.multifactorbox.IsShown():
1623            self.multifactorbox.Show(True) 
1624             
1625    def _hide_multfactor_combobox(self):   
1626        """
1627        Hide the comboBox of muitfactor of CoreMultiShellModel
1628        """ 
1629        if self.mutifactor_text.IsShown():
1630            self.mutifactor_text.Hide()
1631            self.mutifactor_text1.Hide()
1632        if self.multifactorbox.IsShown():
1633            self.multifactorbox.Hide()   
1634
1635       
1636    def _show_combox_helper(self):
1637        """
1638        Fill panel's combo box according to the type of model selected
1639        """
1640        if self.shape_rbutton.GetValue():
1641            ##fill the combobox with form factor list
1642            self.structurebox.SetSelection(0)
1643            self.structurebox.Disable()
1644            self.formfactorbox.Clear()
1645            self._populate_box( self.formfactorbox,self.model_list_box["Shapes"])
1646        if self.shape_indep_rbutton.GetValue():
1647            ##fill the combobox with shape independent  factor list
1648            self.structurebox.SetSelection(0)
1649            self.structurebox.Disable()
1650            self.formfactorbox.Clear()
1651            self._populate_box( self.formfactorbox,
1652                                self.model_list_box["Shape-Independent"])
1653        if self.struct_rbutton.GetValue():
1654            ##fill the combobox with structure factor list
1655            self.structurebox.SetSelection(0)
1656            self.structurebox.Disable()
1657            self.formfactorbox.Clear()
1658            self._populate_box( self.formfactorbox,
1659                                self.model_list_box["Structure Factors"])
1660        if self.plugin_rbutton.GetValue():
1661            ##fill the combobox with form factor list
1662            self.structurebox.Disable()
1663            self.formfactorbox.Clear()
1664            self._populate_box( self.formfactorbox,
1665                                self.model_list_box["Customized Models"])
1666       
1667    def _show_combox(self, event=None):
1668        """
1669        Show combox box associate with type of model selected
1670        """
1671        #if self.check_invalid_panel():
1672        #    self.shape_rbutton.SetValue(True)
1673        #    return
1674
1675        self._show_combox_helper()
1676        self._on_select_model(event=None)
1677        self._save_typeOfmodel()
1678        self.sizer4_4.Layout()
1679        self.sizer4.Layout()
1680        self.Layout()
1681        self.Refresh()
1682 
1683    def _populate_box(self, combobox, list):
1684        """
1685        fill combox box with dict item
1686       
1687        :param list: contains item to fill the combox
1688            item must model class
1689        """
1690        for models in list:
1691            model= models()
1692            name = model.__class__.__name__
1693            if models.__name__!="NoStructure":
1694                if hasattr(model, "name"):
1695                    name = model.name
1696                combobox.Append(name,models)
1697        return 0
1698   
1699    def _onQrangeEnter(self, event):
1700        """
1701        Check validity of value enter in the Q range field
1702       
1703        """
1704        tcrtl = event.GetEventObject()
1705        #Clear msg if previously shown.
1706        msg = ""
1707        wx.PostEvent(self.parent, StatusEvent(status=msg))
1708        # Flag to register when a parameter has changed.
1709        is_modified = False
1710        if tcrtl.GetValue().lstrip().rstrip() != "":
1711            try:
1712                value = float(tcrtl.GetValue())
1713                tcrtl.SetBackgroundColour(wx.WHITE)
1714                # If qmin and qmax have been modified, update qmin and qmax
1715                if self._validate_qrange(self.qmin, self.qmax):
1716                    tempmin = float(self.qmin.GetValue())
1717                    if tempmin != self.qmin_x:
1718                        self.qmin_x = tempmin
1719                    tempmax = float(self.qmax.GetValue())
1720                    if tempmax != self.qmax_x:
1721                        self.qmax_x = tempmax
1722                else:
1723                    tcrtl.SetBackgroundColour("pink")
1724                    msg = "Model Error:wrong value entered : %s" % sys.exc_value
1725                    wx.PostEvent(self.parent, StatusEvent(status=msg))
1726                    return 
1727            except:
1728                tcrtl.SetBackgroundColour("pink")
1729                msg = "Model Error:wrong value entered : %s" % sys.exc_value
1730                wx.PostEvent(self.parent, StatusEvent(status=msg))
1731                return 
1732            #Check if # of points for theory model are valid(>0).
1733            if self.npts != None:
1734                if check_float(self.npts):
1735                    temp_npts = float(self.npts.GetValue())
1736                    if temp_npts !=  self.num_points:
1737                        self.num_points = temp_npts
1738                        is_modified = True
1739                else:
1740                    msg = "Cannot Plot :No npts in that Qrange!!!  "
1741                    wx.PostEvent(self.parent, StatusEvent(status=msg))
1742        else:
1743           tcrtl.SetBackgroundColour("pink")
1744           msg = "Model Error:wrong value entered!!!"
1745           wx.PostEvent(self.parent, StatusEvent(status=msg))
1746        #self._undo.Enable(True)
1747        self.save_current_state()
1748        event = PageInfoEvent(page=self)
1749        wx.PostEvent(self.parent, event)
1750        self.state_change = False
1751        #Draw the model for a different range
1752        self._draw_model()
1753                   
1754    def _theory_qrange_enter(self, event):
1755        """
1756        Check validity of value enter in the Q range field
1757        """
1758       
1759        tcrtl= event.GetEventObject()
1760        #Clear msg if previously shown.
1761        msg= ""
1762        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1763        # Flag to register when a parameter has changed.
1764        is_modified = False
1765        if tcrtl.GetValue().lstrip().rstrip()!="":
1766            try:
1767                value = float(tcrtl.GetValue())
1768                tcrtl.SetBackgroundColour(wx.WHITE)
1769
1770                # If qmin and qmax have been modified, update qmin and qmax
1771                if self._validate_qrange(self.theory_qmin, self.theory_qmax):
1772                    tempmin = float(self.theory_qmin.GetValue())
1773                    if tempmin != self.theory_qmin_x:
1774                        self.theory_qmin_x = tempmin
1775                    tempmax = float(self.theory_qmax.GetValue())
1776                    if tempmax != self.qmax_x:
1777                        self.theory_qmax_x = tempmax
1778                else:
1779                    tcrtl.SetBackgroundColour("pink")
1780                    msg= "Model Error:wrong value entered : %s"% sys.exc_value
1781                    wx.PostEvent(self._manager.parent, StatusEvent(status = msg ))
1782                    return 
1783            except:
1784                tcrtl.SetBackgroundColour("pink")
1785                msg= "Model Error:wrong value entered : %s"% sys.exc_value
1786                wx.PostEvent(self._manager.parent, StatusEvent(status = msg ))
1787                return 
1788            #Check if # of points for theory model are valid(>0).
1789            if self.Npts_total.IsEditable() :
1790                if check_float(self.Npts_total):
1791                    temp_npts = float(self.Npts_total.GetValue())
1792                    if temp_npts !=  self.num_points:
1793                        self.num_points = temp_npts
1794                        is_modified = True
1795                else:
1796                    msg= "Cannot Plot :No npts in that Qrange!!!  "
1797                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1798        else:
1799           tcrtl.SetBackgroundColour("pink")
1800           msg = "Model Error:wrong value entered!!!"
1801           wx.PostEvent(self.parent.parent, StatusEvent(status=msg))
1802        #self._undo.Enable(True)
1803        self.save_current_state()
1804        event = PageInfoEvent(page = self)
1805        wx.PostEvent(self.parent, event)
1806        self.state_change= False
1807        #Draw the model for a different range
1808        self._draw_model()
1809                   
1810    def _on_select_model_helper(self): 
1811        """
1812        call back for model selection
1813        """
1814        ## reset dictionary containing reference to dispersion
1815        self._disp_obj_dict = {}
1816        self.disp_cb_dict ={}
1817       
1818        f_id = self.formfactorbox.GetCurrentSelection()
1819        #For MAC
1820        form_factor = None
1821        if f_id >= 0:
1822            form_factor = self.formfactorbox.GetClientData(f_id)
1823
1824        if not form_factor in  self.model_list_box["multiplication"]:
1825            self.structurebox.Hide()
1826            self.text2.Hide()           
1827            self.structurebox.Disable()
1828            self.structurebox.SetSelection(0)
1829            self.text2.Disable()
1830        else:
1831            self.structurebox.Show()
1832            self.text2.Show()
1833            self.structurebox.Enable()
1834            self.text2.Enable()
1835           
1836        if form_factor != None:   
1837            # set multifactor for Mutifunctional models   
1838            if form_factor().__class__ in self.model_list_box["Multi-Functions"]:
1839                m_id = self.multifactorbox.GetCurrentSelection()
1840                multiplicity = form_factor().multiplicity_info[0]
1841                self.multifactorbox.Clear()
1842                #self.mutifactor_text.SetLabel(form_factor().details[])
1843                self._set_multfactor_combobox(multiplicity)
1844                self._show_multfactor_combobox()
1845                #ToDo:  this info should be called directly from the model
1846                text = form_factor().multiplicity_info[1]#'No. of Shells: '
1847
1848                #self.mutifactor_text.Clear()
1849                self.mutifactor_text.SetLabel(text)
1850                if m_id > multiplicity -1:
1851                    # default value
1852                    m_id = 1
1853                   
1854                self.multi_factor = self.multifactorbox.GetClientData(m_id)
1855                if self.multi_factor == None: self.multi_factor =0
1856                form_factor = form_factor(int(self.multi_factor))
1857                self.multifactorbox.SetSelection(m_id)
1858                # Check len of the text1 and max_multiplicity
1859                text = ''
1860                if form_factor.multiplicity_info[0] == len(form_factor.multiplicity_info[2]):
1861                    text = form_factor.multiplicity_info[2][self.multi_factor]
1862                self.mutifactor_text1.SetLabel(text)
1863                # Check if model has  get sld profile.
1864                if len(form_factor.multiplicity_info[3]) > 0:
1865                    self.sld_axes = form_factor.multiplicity_info[3]
1866                    self.show_sld_button.Show(True)
1867                else:
1868                    self.sld_axes = ""
1869
1870            else:
1871                self._hide_multfactor_combobox()
1872                self.show_sld_button.Hide()
1873                form_factor = form_factor()
1874                self.multi_factor = None
1875        else:
1876            self._hide_multfactor_combobox()
1877            self.show_sld_button.Hide()
1878            self.multi_factor = None 
1879             
1880        s_id = self.structurebox.GetCurrentSelection()
1881        struct_factor = self.structurebox.GetClientData( s_id )
1882       
1883        if  struct_factor !=None:
1884            from sans.models.MultiplicationModel import MultiplicationModel
1885            self.model= MultiplicationModel(form_factor,struct_factor())
1886           
1887        else:
1888            if form_factor != None:
1889                self.model= form_factor
1890            else:
1891                self.model = None
1892                return self.model
1893           
1894
1895        ## post state to fit panel
1896        self.state.parameters =[]
1897        self.state.model =self.model
1898        self.state.qmin = self.qmin_x
1899        self.state.multi_factor = self.multi_factor
1900        self.disp_list =self.model.getDispParamList()
1901        self.state.disp_list = self.disp_list
1902        self.Layout()     
1903       
1904    def _validate_qrange(self, qmin_ctrl, qmax_ctrl):
1905        """
1906        Verify that the Q range controls have valid values
1907        and that Qmin < Qmax.
1908       
1909        :param qmin_ctrl: text control for Qmin
1910        :param qmax_ctrl: text control for Qmax
1911       
1912        :return: True is the Q range is value, False otherwise
1913       
1914        """
1915        qmin_validity = check_float(qmin_ctrl)
1916        qmax_validity = check_float(qmax_ctrl)
1917        if not (qmin_validity and qmax_validity):
1918            return False
1919        else:
1920            qmin = float(qmin_ctrl.GetValue())
1921            qmax = float(qmax_ctrl.GetValue())
1922            if qmin <= qmax:
1923                #Make sure to set both colours white. 
1924                qmin_ctrl.SetBackgroundColour(wx.WHITE)
1925                qmin_ctrl.Refresh()
1926                qmax_ctrl.SetBackgroundColour(wx.WHITE)
1927                qmax_ctrl.Refresh()
1928            else:
1929                qmin_ctrl.SetBackgroundColour("pink")
1930                qmin_ctrl.Refresh()
1931                qmax_ctrl.SetBackgroundColour("pink")
1932                qmax_ctrl.Refresh()
1933                msg= "Invalid Q range: Q min must be smaller than Q max"
1934                wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
1935                return False
1936        return True
1937   
1938    def _validate_Npts(self): 
1939        """
1940        Validate the number of points for fitting is more than 10 points.
1941        If valid, setvalues Npts_fit otherwise post msg.
1942        """
1943        #default flag
1944        flag = True
1945        # Theory
1946        if self.data == None and self.enable2D:
1947            return flag
1948
1949        # q value from qx and qy
1950        radius= numpy.sqrt( self.data.qx_data * self.data.qx_data + 
1951                            self.data.qy_data * self.data.qy_data )
1952        #get unmasked index
1953        index_data = (float(self.qmin.GetValue()) <= radius) & \
1954                        (radius <= float(self.qmax.GetValue()))
1955        index_data = (index_data) & (self.data.mask) 
1956        index_data = (index_data) & (numpy.isfinite(self.data.data))
1957
1958        if len(index_data[index_data]) < 10:
1959            # change the color pink.
1960            self.qmin.SetBackgroundColour("pink")
1961            self.qmin.Refresh()
1962            self.qmax.SetBackgroundColour("pink")
1963            self.qmax.Refresh()
1964            msg= "Cannot Plot :No or too little npts in that data range!!!  "
1965            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1966            self.fitrange = False
1967            flag = False
1968        else:
1969            self.Npts_fit.SetValue(str(len(self.data.mask[index_data==True])))
1970            self.fitrange = True
1971           
1972        return flag
1973   
1974    def _check_value_enter(self, list, modified):
1975        """
1976        :param list: model parameter and panel info
1977        :Note: each item of the list should be as follow:
1978            item=[check button state, parameter's name,
1979                paramater's value, string="+/-",
1980                parameter's error of fit,
1981                parameter's minimum value,
1982                parrameter's maximum value ,
1983                parameter's units]
1984        """ 
1985        is_modified =  modified
1986        if len(list)==0:
1987            return is_modified
1988        for item in list:
1989            #skip angle parameters for 1D
1990            if not self.enable2D:#self.data.__class__.__name__ !="Data2D":
1991                if item in self.orientation_params:
1992                    continue
1993            #try:
1994            name = str(item[1])
1995           
1996            if string.find(name,".npts") ==-1 and \
1997                                        string.find(name,".nsigmas")==-1:     
1998                ## check model parameters range             
1999                param_min= None
2000                param_max= None
2001               
2002                ## check minimun value
2003                if item[5]!= None and item[5]!= "":
2004                    if item[5].GetValue().lstrip().rstrip()!="":
2005                        try:
2006                           
2007                            param_min = float(item[5].GetValue())
2008                            if not self._validate_qrange(item[5],item[2]):
2009                                if numpy.isfinite(param_min):
2010                                    item[2].SetValue(format_number(param_min))
2011                           
2012                            item[5].SetBackgroundColour(wx.WHITE)
2013                            item[2].SetBackgroundColour(wx.WHITE)
2014                                           
2015                        except:
2016                            msg = "Wrong Fit parameter range entered "
2017                            wx.PostEvent(self.parent.parent, 
2018                                         StatusEvent(status = msg))
2019                            raise ValueError, msg
2020                        is_modified = True
2021                ## check maximum value
2022                if item[6]!= None and item[6]!= "":
2023                    if item[6].GetValue().lstrip().rstrip()!="":
2024                        try:                         
2025                            param_max = float(item[6].GetValue())
2026                            if not self._validate_qrange(item[2],item[6]):
2027                                if numpy.isfinite(param_max):
2028                                    item[2].SetValue(format_number(param_max)) 
2029                           
2030                            item[6].SetBackgroundColour(wx.WHITE)
2031                            item[2].SetBackgroundColour(wx.WHITE)
2032                        except:
2033                            msg = "Wrong Fit parameter range entered "
2034                            wx.PostEvent(self.parent.parent, 
2035                                         StatusEvent(status = msg))
2036                            raise ValueError, msg
2037                        is_modified = True
2038               
2039
2040                if param_min != None and param_max !=None:
2041                    if not self._validate_qrange(item[5], item[6]):
2042                        msg= "Wrong Fit range entered for parameter "
2043                        msg+= "name %s of model %s "%(name, self.model.name)
2044                        wx.PostEvent(self.parent.parent, 
2045                                     StatusEvent(status = msg))
2046               
2047                if name in self.model.details.keys():   
2048                        self.model.details[name][1:3] = param_min, param_max
2049                        is_modified = True
2050             
2051                else:
2052                        self.model.details [name] = ["", param_min, param_max] 
2053                        is_modified = True
2054            try:   
2055                # Check if the textctr is enabled
2056                if item[2].IsEnabled():
2057                    value= float(item[2].GetValue())
2058                    item[2].SetBackgroundColour("white")
2059                    # If the value of the parameter has changed,
2060                    # +update the model and set the is_modified flag
2061                    if value != self.model.getParam(name) and \
2062                                                numpy.isfinite(value):
2063                        self.model.setParam(name, value)
2064                       
2065            except:
2066                item[2].SetBackgroundColour("pink")
2067                msg = "Wrong Fit parameter value entered "
2068                wx.PostEvent(self.parent.parent, StatusEvent(status = msg))
2069               
2070        return is_modified
2071       
2072 
2073    def _set_dipers_Param(self, event):
2074        """
2075        respond to self.enable_disp and self.disable_disp radio box.
2076        The dispersity object is reset inside the model into Gaussian.
2077        When the user select yes , this method display a combo box for more selection
2078        when the user selects No,the combo box disappears.
2079        Redraw the model with the default dispersity (Gaussian)
2080        """
2081        #if self.check_invalid_panel():
2082        #    return
2083        ## On selction if no model exists.
2084        if self.model ==None:
2085            self.disable_disp.SetValue(True)
2086            msg="Please select a Model first..."
2087            wx.MessageBox(msg, 'Info')
2088            wx.PostEvent(self._manager.parent, StatusEvent(status=\
2089                            "Polydispersion: %s"%msg))
2090            return
2091
2092        self._reset_dispersity()
2093   
2094        if self.model ==None:
2095            self.model_disp.Hide()
2096            self.sizer4_4.Clear(True)
2097            return
2098
2099        if self.enable_disp.GetValue():
2100            ## layout for model containing no dispersity parameters
2101           
2102            self.disp_list= self.model.getDispParamList()
2103             
2104            if len(self.disp_list)==0 and len(self.disp_cb_dict)==0:
2105                self._layout_sizer_noDipers() 
2106            else:
2107                ## set gaussian sizer
2108                self._on_select_Disp(event=None)
2109        else:
2110            self.sizer4_4.Clear(True)
2111           
2112        ## post state to fit panel
2113        self.save_current_state()
2114        if event !=None:
2115            #self._undo.Enable(True)
2116            event = PageInfoEvent(page = self)
2117            wx.PostEvent(self.parent, event)
2118        #draw the model with the current dispersity
2119        self._draw_model()
2120        self.sizer4_4.Layout()
2121        self.sizer5.Layout()
2122        self.Layout()
2123        self.Refresh()     
2124         
2125       
2126    def _layout_sizer_noDipers(self):
2127        """
2128        Draw a sizer with no dispersity info
2129        """
2130        ix=0
2131        iy=1
2132        self.fittable_param=[]
2133        self.fixed_param=[]
2134        self.orientation_params_disp=[]
2135       
2136        self.sizer4_4.Clear(True)
2137        text = "No polydispersity available for this model"
2138        text = "No polydispersity available for this model"
2139        model_disp = wx.StaticText(self, -1, text)
2140        self.sizer4_4.Add(model_disp,( iy, ix),(1,1), 
2141                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10)
2142        self.sizer4_4.Layout()
2143        self.sizer4.Layout()
2144   
2145    def _reset_dispersity(self):
2146        """
2147        put gaussian dispersity into current model
2148        """
2149        if len(self.param_toFit)>0:
2150            for item in self.fittable_param:
2151                if item in self.param_toFit:
2152                    self.param_toFit.remove(item)
2153
2154            for item in self.orientation_params_disp:
2155                if item in self.param_toFit:
2156                    self.param_toFit.remove(item)
2157         
2158        self.fittable_param=[]
2159        self.fixed_param=[]
2160        self.orientation_params_disp=[]
2161        self.values={}
2162        self.weights={}
2163     
2164        from sans.models.dispersion_models import GaussianDispersion, ArrayDispersion
2165        if len(self.disp_cb_dict)==0:
2166            self.save_current_state()
2167            self.sizer4_4.Clear(True)
2168            self.Layout()
2169 
2170            return 
2171        if (len(self.disp_cb_dict)>0) :
2172            for p in self.disp_cb_dict:
2173                # The parameter was un-selected. Go back to Gaussian model (with 0 pts)                   
2174                disp_model = GaussianDispersion()
2175               
2176                self._disp_obj_dict[p] = disp_model
2177                # Set the new model as the dispersion object for the selected parameter
2178                try:
2179                   self.model.set_dispersion(p, disp_model)
2180                except:
2181
2182                    pass
2183
2184        ## save state into
2185        self.save_current_state()
2186        self.Layout() 
2187        self.Refresh()
2188                 
2189    def _on_select_Disp(self,event):
2190        """
2191        allow selecting different dispersion
2192        self.disp_list should change type later .now only gaussian
2193        """
2194        self._set_sizer_dispersion()
2195
2196        ## Redraw the model
2197        self._draw_model() 
2198        #self._undo.Enable(True)
2199        event = PageInfoEvent(page = self)
2200        wx.PostEvent(self.parent, event)
2201       
2202        self.sizer4_4.Layout()
2203        self.sizer4.Layout()
2204        self.SetupScrolling()
2205   
2206    def _on_disp_func(self, event=None): 
2207        """
2208        Select a distribution function for the polydispersion
2209       
2210        :Param event: ComboBox event
2211        """
2212        # get ready for new event
2213        if event != None:
2214            event.Skip()
2215        # Get event object
2216        disp_box =  event.GetEventObject() 
2217
2218        # Try to select a Distr. function
2219        try:   
2220            disp_box.SetBackgroundColour("white")
2221            selection = disp_box.GetCurrentSelection()
2222            param_name = disp_box.Name.split('.')[0]
2223            disp_name = disp_box.GetValue()
2224            dispersity= disp_box.GetClientData(selection)
2225   
2226            #disp_model =  GaussianDispersion()
2227            disp_model = dispersity()
2228            # Get param names to reset the values of the param
2229            name1 = param_name + ".width"
2230            name2 = param_name + ".npts"
2231            name3 = param_name + ".nsigmas"
2232            # Check Disp. function whether or not it is 'array'
2233            if disp_name.lower() == "array":
2234                value2= ""
2235                value3= ""
2236                value1 = self._set_array_disp(name=name1, disp=disp_model)
2237            else:
2238                self._del_array_values(name1)
2239                #self._reset_array_disp(param_name)
2240                self._disp_obj_dict[name1] = disp_model
2241                self.model.set_dispersion(param_name, disp_model)
2242                self.state._disp_obj_dict[name1]= disp_model
2243 
2244                value1= str(format_number(self.model.getParam(name1), True))
2245                value2= str(format_number(self.model.getParam(name2)))
2246                value3= str(format_number(self.model.getParam(name3)))
2247            # Reset fittable polydispersin parameter value
2248            for item in self.fittable_param:
2249                 if item[1] == name1:
2250                    item[2].SetValue(value1) 
2251                    item[5].SetValue("")
2252                    item[6].SetValue("")
2253                    # Disable for array
2254                    if disp_name.lower() == "array":
2255                        item[0].SetValue(False)
2256                        item[0].Disable()
2257                        item[2].Disable()
2258                        item[5].Disable()
2259                        item[6].Disable()
2260                    else:
2261                        item[0].Enable()
2262                        item[2].Enable()
2263                        item[5].Enable()
2264                        item[6].Enable()                       
2265                    break
2266            # Reset fixed polydispersion params
2267            for item in self.fixed_param:
2268                if item[1] == name2:
2269                    item[2].SetValue(value2) 
2270                    # Disable Npts for array
2271                    if disp_name.lower() == "array":
2272                        item[2].Disable()
2273                    else:
2274                        item[2].Enable()
2275                if item[1] == name3:
2276                    item[2].SetValue(value3) 
2277                    # Disable Nsigs for array
2278                    if disp_name.lower() == "array":
2279                        item[2].Disable()
2280                    else:
2281                        item[2].Enable()
2282               
2283            # Make sure the check box updated when all checked
2284            if self.cb1.GetValue():
2285                self.select_all_param(None)
2286
2287            # update params
2288            self._update_paramv_on_fit() 
2289            # draw
2290            self._draw_model()
2291            self.Refresh()
2292        except:
2293            # Error msg
2294            msg = "Error occurred:"
2295            msg += " Could not select the distribution function..."
2296            msg += " Please select another distribution function."
2297            disp_box.SetBackgroundColour("pink")
2298            # Focus on Fit button so that users can see the pinky box
2299            self.btFit.SetFocus()
2300            wx.PostEvent(self.parent.parent, 
2301                         StatusEvent(status=msg, info="error"))
2302       
2303       
2304    def _set_array_disp(self, name=None, disp=None):
2305        """
2306        Set array dispersion
2307       
2308        :param name: name of the parameter for the dispersion to be set
2309        :param disp: the polydisperion object
2310        """
2311        # The user wants this parameter to be averaged.
2312        # Pop up the file selection dialog.
2313        path = self._selectDlg()
2314        # Array data
2315        values = []
2316        weights = []
2317        # If nothing was selected, just return
2318        if path is None:
2319            self.disp_cb_dict[name].SetValue(False)
2320            #self.noDisper_rbox.SetValue(True)
2321            return
2322        self._default_save_location = os.path.dirname(path)
2323
2324        basename  = os.path.basename(path)
2325        values,weights = self.read_file(path)
2326       
2327        # If any of the two arrays is empty, notify the user that we won't
2328        # proceed
2329        if len(self.param_toFit)>0:
2330            if name in self.param_toFit:
2331                self.param_toFit.remove(name)
2332
2333        # Tell the user that we are about to apply the distribution
2334        msg = "Applying loaded %s distribution: %s" % (name, path)
2335        wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
2336
2337        disp.set_weights(values, weights)
2338        self._disp_obj_dict[name] = disp
2339        self.model.set_dispersion(name.split('.')[0], disp)
2340        self.state._disp_obj_dict[name]= disp
2341        self.values[name] = values
2342        self.weights[name] = weights
2343        # Store the object to make it persist outside the
2344        # scope of this method
2345        #TODO: refactor model to clean this up?
2346        self.state.values = {}
2347        self.state.weights = {}
2348        self.state.values = copy.deepcopy(self.values)
2349        self.state.weights = copy.deepcopy(self.weights)
2350
2351        # Set the new model as the dispersion object for the
2352        #selected parameter
2353        #self.model.set_dispersion(p, disp_model)
2354        # Store a reference to the weights in the model object
2355        #so that
2356        # it's not lost when we use the model within another thread.
2357        #TODO: total hack - fix this
2358        self.state.model= self.model.clone()
2359        self.model._persistency_dict[name.split('.')[0]] = \
2360                                        [values, weights]
2361        self.state.model._persistency_dict[name.split('.')[0]] = \
2362                                        [values,weights]
2363        return basename
2364   
2365    def _del_array_values(self, name=None): 
2366        """
2367        Reset array dispersion
2368       
2369        :param name: name of the parameter for the dispersion to be set
2370        """
2371        # Try to delete values and weight of the names array dic if exists
2372        try:
2373            del self.values[name]
2374            del self.weights[name]
2375            # delete all other dic
2376            del self.state.values[name]
2377            del self.state.weights[name]
2378            del self.model._persistency_dict[name.split('.')[0]] 
2379            del self.state.model._persistency_dict[name.split('.')[0]]
2380        except:
2381            pass
2382                                           
2383    def _lay_out(self):
2384        """
2385        returns self.Layout
2386       
2387        :Note: Mac seems to like this better when self.
2388            Layout is called after fitting.
2389        """
2390        self._sleep4sec()
2391        self.Layout()
2392        return 
2393   
2394    def _sleep4sec(self):
2395        """
2396            sleep for 1 sec only applied on Mac
2397            Note: This 1sec helps for Mac not to crash on self.:ayout after self._draw_model
2398        """
2399        if ON_MAC == True:
2400            time.sleep(1)
2401           
2402    def _find_polyfunc_selection(self, disp_func = None):
2403        """
2404        FInd Comboox selection from disp_func
2405       
2406        :param disp_function: dispersion distr. function
2407        """
2408        # List of the poly_model name in the combobox
2409        list = ["RectangleDispersion", "ArrayDispersion", 
2410                    "LogNormalDispersion", "GaussianDispersion", 
2411                    "SchulzDispersion"]
2412
2413        # Find the selection
2414        try:
2415            selection = list.index(disp_func.__class__.__name__)
2416            return selection
2417        except:
2418             return 3
2419                           
2420    def on_reset_clicked(self,event):
2421        """
2422        On 'Reset' button  for Q range clicked
2423        """
2424        flag = True
2425        #if self.check_invalid_panel():
2426        #    return
2427        ##For 3 different cases: Data2D, Data1D, and theory
2428        if self.model == None:
2429            msg="Please select a model first..."
2430            wx.MessageBox(msg, 'Info')
2431            flag = False
2432            return
2433           
2434        elif self.data.__class__.__name__ == "Data2D":
2435            data_min= 0
2436            x= max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
2437            y= max(math.fabs(self.data.ymin), math.fabs(self.data.ymax))
2438            self.qmin_x = data_min
2439            self.qmax_x = math.sqrt(x*x + y*y)
2440            # check smearing
2441            if not self.disable_smearer.GetValue():
2442                temp_smearer= self.current_smearer
2443                ## set smearing value whether or not the data contain the smearing info
2444                if self.pinhole_smearer.GetValue():
2445                    flag = self.update_pinhole_smear()
2446                else:
2447                    flag = True
2448                   
2449        elif self.data == None:
2450            self.qmin_x = _QMIN_DEFAULT
2451            self.qmax_x = _QMAX_DEFAULT
2452            self.num_points = _NPTS_DEFAULT           
2453            self.state.npts = self.num_points
2454           
2455        elif self.data.__class__.__name__ != "Data2D":
2456            self.qmin_x = min(self.data.x)
2457            self.qmax_x = max(self.data.x)
2458            # check smearing
2459            if not self.disable_smearer.GetValue():
2460                temp_smearer= self.current_smearer
2461                ## set smearing value whether or not the data contain the smearing info
2462                if self.slit_smearer.GetValue():
2463                    flag = self.update_slit_smear()
2464                elif self.pinhole_smearer.GetValue():
2465                    flag = self.update_pinhole_smear()
2466                else:
2467                    flag = True
2468        else:
2469            flag = False
2470           
2471        if flag == False:
2472            msg= "Cannot Plot :Must enter a number!!!  "
2473            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
2474        else:
2475            # set relative text ctrs.
2476            self.qmin.SetValue(str(self.qmin_x))
2477            self.qmax.SetValue(str(self.qmax_x))
2478            self.set_npts2fit()
2479            # At this point, some button and variables satatus (disabled?) should be checked
2480            # such as color that should be reset to white in case that it was pink.
2481            self._onparamEnter_helper()
2482
2483        self.save_current_state()
2484        self.state.qmin = self.qmin_x
2485        self.state.qmax = self.qmax_x
2486       
2487        #reset the q range values
2488        self._reset_plotting_range(self.state)
2489        #self.compute_chisqr(smearer=self.current_smearer)
2490        #Re draw plot
2491        self._draw_model()
2492       
2493    def get_images(self):
2494        """
2495        Get the images of the plots corresponding this panel for report
2496       
2497        : return graphs: list of figures
2498        : TODO: Move to guiframe
2499        """
2500        # set list of graphs
2501        graphs = []
2502        canvases = []
2503        # call gui_manager
2504        gui_manager = self.parent.parent
2505        # loops through the panels [dic]
2506        for item1, item2 in gui_manager.panels.iteritems():
2507             data_title = self.data.group_id
2508             data_name = str(self.data.name).split(" [")[0]
2509            # try to get all plots belonging to this control panel
2510             try:
2511                 title = ''
2512                 # check titles (main plot)
2513                 if hasattr(item2,"data2D"):
2514                     title = item2.data2D.title
2515                 # and data_names (model plot[2D], and residuals)
2516                 if item2.group_id == data_title or \
2517                                title.count(data_name) or \
2518                                item2.window_name.count(data_name) or \
2519                                item2.window_caption.count(data_name):
2520                     #panel = gui_manager._mgr.GetPane(item2.window_name)
2521                     # append to the list
2522                     graphs.append(item2.figure) 
2523                     canvases.append(item2.canvas)     
2524             except:
2525                 # Not for control panels
2526                 pass
2527        # return the list of graphs
2528        return graphs, canvases
2529
2530    def on_model_help_clicked(self,event):
2531        """
2532        on 'More details' button
2533        """
2534        from help_panel import  HelpWindow
2535        import sans.models as models 
2536       
2537        # Get models help model_function path
2538        path = models.get_data_path(media='media')
2539        model_path = os.path.join(path,"model_functions.html")
2540        if self.model == None:
2541            name = 'FuncHelp'
2542        else:
2543            name = self.model.__class__.__name__
2544
2545        frame = HelpWindow(None, -1,  pageToOpen=model_path)   
2546        frame.Show(True)
2547        if frame.rhelp.HasAnchor(name):
2548            frame.rhelp.ScrollToAnchor(name)
2549        else:
2550           msg= "Model does not contains an available description "
2551           msg +="Please try searching in the Help window"
2552           wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))     
2553   
2554    def on_pd_help_clicked(self, event):
2555        """
2556        Button event for PD help
2557        """
2558        from help_panel import  HelpWindow
2559        import sans.models as models 
2560       
2561        # Get models help model_function path
2562        path = models.get_data_path(media='media')
2563        pd_path = os.path.join(path,"pd_help.html")
2564
2565        frame = HelpWindow(None, -1,  pageToOpen=pd_path)   
2566        frame.Show(True)
2567       
2568    def on_left_down(self, event):
2569        """
2570        Get key stroke event
2571        """
2572        # Figuring out key combo: Cmd for copy, Alt for paste
2573        if event.CmdDown() and event.ShiftDown():
2574            flag = self.get_paste()
2575        elif event.CmdDown():
2576            flag = self.get_copy()
2577        else:
2578            event.Skip()
2579            return
2580        # make event free
2581        event.Skip()
2582        # messages depending on the flag
2583        if flag == None:
2584            msg = " Parameter values are copied to the clipboard..."
2585            infor = 'warning'
2586        elif flag:
2587            msg = " Parameter values are pasted from the clipboad..."
2588            infor = "warning"
2589        else:
2590            msg = "Error was occured during pasting the parameter values "
2591            msg += "from the clipboard..."
2592            infor = "error"
2593        # inform msg to wx
2594        wx.PostEvent( self.parent.parent, 
2595                      StatusEvent(status= msg, info=infor))
2596       
2597           
2598    def get_copy(self): 
2599        """
2600        Get the string copies of the param names and values in the tap
2601        """ 
2602        content = 'sansview_parameter_values:'
2603        # Do it if params exist       
2604        if  self.parameters !=[]:
2605           
2606            # go through the parameters
2607            string = self._get_copy_helper(self.parameters, 
2608                                           self.orientation_params)
2609            content += string
2610           
2611            # go through the fittables
2612            string = self._get_copy_helper(self.fittable_param, 
2613                                           self.orientation_params_disp)
2614            content += string
2615
2616            # go through the fixed params
2617            string = self._get_copy_helper(self.fixed_param, 
2618                                           self.orientation_params_disp)
2619            content += string
2620               
2621            # go through the str params
2622            string = self._get_copy_helper(self.str_parameters, 
2623                                           self.orientation_params)
2624            content += string
2625
2626        if wx.TheClipboard.Open():
2627            wx.TheClipboard.SetData(wx.TextDataObject(str(content)))
2628            data = wx.TextDataObject()
2629            success = wx.TheClipboard.GetData(data)
2630            text = data.GetText()
2631            wx.TheClipboard.Close()
2632           
2633        return None
2634   
2635    def _get_copy_helper(self, param, orient_param):
2636        """
2637        Helping get value and name of the params
2638       
2639        : param param:  parameters
2640        : param orient_param = oritational params
2641        : return content: strings [list] [name,value:....]
2642        """
2643        content = ''
2644        # go through the str params
2645        for item in param: 
2646            # 2D
2647            if self.data.__class__.__name__== "Data2D":
2648                name = item[1]
2649                value = item[2].GetValue()
2650            # 1D
2651            else:
2652                ## for 1D all parameters except orientation
2653                if not item[1] in orient_param:
2654                    name = item[1]
2655                    value = item[2].GetValue()
2656            # add to the content
2657            content += name + ',' + value + ':'
2658           
2659        return content
2660   
2661    def get_paste(self): 
2662        """
2663        Get the string copies of the param names and values in the tap
2664        """ 
2665        context = {}
2666        text = ""
2667       
2668        # Get text from the clip board       
2669        if wx.TheClipboard.Open():
2670            if wx.TheClipboard.IsSupported(wx.DataFormat(wx.DF_TEXT)):
2671                data = wx.TextDataObject()
2672                # get wx dataobject
2673                success = wx.TheClipboard.GetData(data)
2674                # get text
2675                text = data.GetText()
2676            # close clipboard
2677            wx.TheClipboard.Close()
2678           
2679        # put the text into dictionary   
2680        lines = text.split(':')
2681        if lines[0] != 'sansview_parameter_values':
2682            return False
2683        for line in lines[1:-1]:
2684            if len(line) != 0:
2685                item =line.split(',')
2686                name = item[0]
2687                value = item[1]
2688                # Transfer the text to content[dictionary]
2689                context[name] = value
2690       
2691        # Do it if params exist       
2692        if  self.parameters != []:
2693            # go through the parameters 
2694            self._get_paste_helper(self.parameters, 
2695                                   self.orientation_params, context)
2696
2697            # go through the fittables
2698            self._get_paste_helper(self.fittable_param, 
2699                                   self.orientation_params_disp, context)
2700
2701            # go through the fixed params
2702            self._get_paste_helper(self.fixed_param, 
2703                                   self.orientation_params_disp, context)
2704           
2705            # go through the str params
2706            self._get_paste_helper(self.str_parameters, 
2707                                   self.orientation_params, context)
2708           
2709        return True
2710   
2711    def _get_paste_helper(self, param, orient_param, content):
2712        """
2713        Helping set values of the params
2714       
2715        : param param:  parameters
2716        : param orient_param: oritational params
2717        : param content: dictionary [ name, value: name1.value1,...]
2718        """
2719        # go through the str params
2720        for item in param: 
2721            # 2D
2722            if self.data.__class__.__name__== "Data2D":
2723                name = item[1]
2724                if name in content.keys():
2725                    item[2].SetValue(content[name])
2726            # 1D
2727            else:
2728                ## for 1D all parameters except orientation
2729                if not item[1] in orient_param:
2730                    name = item[1]
2731                    if name in content.keys():
2732                        # Avoid changing combox content which needs special care
2733                        if item[2].__class__.__name__ != "ComboBox":
2734                            item[2].SetValue(content[name])
2735                           
2736               
Note: See TracBrowser for help on using the repository browser.