source: sasview/fittingview/src/sans/perspectives/fitting/basepage.py @ 8e165f9

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 8e165f9 was 49c69de, checked in by Gervaise Alina <gervyh@…>, 13 years ago

move perspective from sansview to fittingview

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