source: sasview/sansview/perspectives/fitting/basepage.py @ 2c6b224

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 2c6b224 was 07c8630, checked in by Jae Cho <jhjcho@…>, 13 years ago

added copy and paste menu in the menubar and toolbar

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