source: sasview/sansview/perspectives/fitting/basepage.py @ 4225aed

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 4225aed was 4225aed, checked in by Gervaise Alina <gervyh@…>, 13 years ago

working on batch

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