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

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

small fix for the key copy to clipboard

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