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

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

create a virtual data for empty fitpage

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