source: sasview/sansview/perspectives/fitting/basepage.py @ 944b1a6

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 944b1a6 was 6694604, checked in by Jae Cho <jhjcho@…>, 13 years ago

minor fixes including paste info

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