source: sasview/sansview/perspectives/fitting/basepage.py @ 70468a5

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

faster gui-updating on selecting a model

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