source: sasview/sansview/perspectives/fitting/basepage.py @ 60132ef

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 60132ef was 60132ef, checked in by Gervaise Alina <gervyh@…>, 15 years ago

working on dispersity

  • Property mode set to 100644
File size: 49.8 KB
Line 
1
2import sys, os
3import wx
4import numpy
5import time
6
7from sans.guiframe.utils import format_number,check_float
8from sans.guicomm.events import StatusEvent   
9import pagestate
10from pagestate import PageState
11(PageInfoEvent, EVT_PAGE_INFO)   = wx.lib.newevent.NewEvent()
12_BOX_WIDTH = 80
13
14class BasicPage(wx.ScrolledWindow):
15    """
16        This class provide general structure of  fitpanel page
17    """
18     ## Internal name for the AUI manager
19    window_name = "Basic Page"
20    ## Title to appear on top of the window
21    window_caption = "Basic page "
22   
23    def __init__(self,parent, page_info):
24        wx.ScrolledWindow.__init__(self, parent)
25        ##window_name
26        self.window_name = page_info.window_name
27        ##window_caption
28        self.window_caption = page_info.window_caption
29        ## parent of the page
30        self.parent = parent
31        ## manager is the fitting plugin
32        self.manager= page_info.manager
33        ## owner of the page (fitting plugin)
34        self.event_owner= page_info.event_owner
35         ## current model
36        self.model = page_info.model
37        ## data
38        self.data = page_info.data
39        ## dictionary containing list of models
40        self.model_list_box = page_info.model_list_box
41        ## Data member to store the dispersion object created
42        self._disp_obj_dict = {}
43        ## selected parameters to apply dispersion
44        self.disp_cb_dict ={}
45        ##list of model parameters. each item must have same length
46        ## each item related to a given parameters
47        ##[cb state, name, value, "+/-", error of fit, min, max , units]
48        self.parameters=[]
49        ## list of parameters to fit , must be like self.parameters
50        self.param_toFit=[]
51        ## list of looking like parameters but with non fittable parameters info
52        self.fixed_param=[]
53        ## list of looking like parameters but with  fittable parameters info
54        self.fittable_param=[]
55        ##list of dispersion parameters
56        self.disp_list=[]
57        ## list of orientation parameters
58        self.orientation_params=[]
59        self.orientation_params_disp=[]
60        if self.model !=None:
61            self.disp_list= self.model.getDispParamList()
62        ##enable model 2D draw
63        self.enable2D= False
64        ## check that the fit range is correct to plot the model again
65        self.fitrange= True
66        ## Q range
67        self.qmin_x= 0.001
68        self.qmax_x= 0.13
69        self.num_points= 100
70        ## Create memento to save the current state
71       
72        self.state= PageState(parent= self.parent,model=self.model, data=self.data)
73       
74        ## retrieve saved state
75        self.number_saved_state= 0
76        ## dictionary of saved state
77        self.saved_states={}
78        self.slicerpop = wx.Menu()
79        ## Default locations
80        self._default_save_location = os.getcwd()     
81        ## save initial state on context menu
82        self.onSave(event=None)
83        self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu)
84       
85        ## create the basic structure of the panel with empty sizer
86        self.define_page_structure()
87        ## drawing Initial dispersion parameters sizer
88        self.set_dispers_sizer()
89        self._fill_save_sizer()
90        ## layout
91        self.set_layout()
92       
93       
94    def onContextMenu(self, event): 
95        """
96            Retrieve the state selected state
97        """
98        pos = event.GetPosition()
99        pos = self.ScreenToClient(pos)
100        self.PopupMenu(self.slicerpop, pos) 
101       
102       
103       
104    def define_page_structure(self):
105        """
106            Create empty sizer for a panel
107        """
108        self.vbox  = wx.BoxSizer(wx.VERTICAL)
109        self.sizer0 = wx.BoxSizer(wx.VERTICAL)
110        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
111        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
112        self.sizer3 = wx.BoxSizer(wx.VERTICAL)
113        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
114        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
115        self.sizer6 = wx.BoxSizer(wx.VERTICAL)
116       
117        self.sizer0.SetMinSize((375,-1))
118        self.sizer1.SetMinSize((375,-1))
119        self.sizer2.SetMinSize((375,-1))
120        self.sizer3.SetMinSize((375,-1))
121        self.sizer4.SetMinSize((375,-1))
122        self.sizer5.SetMinSize((375,-1))
123        self.sizer6.SetMinSize((375,-1))
124       
125        self.vbox.Add(self.sizer0)
126        self.vbox.Add(self.sizer1)
127        self.vbox.Add(self.sizer2)
128        self.vbox.Add(self.sizer3)
129        self.vbox.Add(self.sizer4)
130        self.vbox.Add(self.sizer5)
131        self.vbox.Add(self.sizer6)
132       
133       
134    def set_layout(self):
135        """
136             layout
137        """
138        self.vbox.Layout()
139        self.vbox.Fit(self) 
140        self.SetSizer(self.vbox)
141       
142        self.set_scroll()
143        self.Centre()
144       
145       
146    def set_scroll(self):
147        self.SetScrollbars(20,20,200,100)
148        self.Layout()   
149        self.SetAutoLayout(True)
150         
151         
152    def set_owner(self,owner):
153        """
154            set owner of fitpage
155            @param owner: the class responsible of plotting
156        """
157        self.event_owner = owner   
158        self.state.event_owner = owner
159 
160    def set_manager(self, manager):
161        """
162             set panel manager
163             @param manager: instance of plugin fitting
164        """
165        self.manager = manager 
166        self.state.manager = manager
167       
168    def populate_box(self, dict):
169        """
170             Store list of model
171             @param dict: dictionary containing list of models
172        """
173        self.model_list_box = dict
174        self.state.model_list_box = self.model_list_box
175           
176   
177       
178    def set_dispers_sizer(self):
179        """
180            fill sizer containing dispersity info
181        """
182        self.sizer4.Clear(True)
183        name="Polydispersity and Orientational Distribution"
184        box_description= wx.StaticBox(self, -1,name)
185        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
186        #----------------------------------------------------
187        self.disable_disp = wx.RadioButton(self, -1, 'Off', (10, 10), style=wx.RB_GROUP)
188        self.enable_disp = wx.RadioButton(self, -1, 'On', (10, 30))
189        ## saving the state of enable dispersity button
190        self.state.enable_disp= self.enable_disp.GetValue()
191       
192        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.disable_disp.GetId())
193        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.enable_disp.GetId())
194       
195        sizer_dispersion = wx.BoxSizer(wx.HORIZONTAL)
196        sizer_dispersion.Add((20,20))
197        name=""#Polydispersity and \nOrientational Distribution "
198        sizer_dispersion.Add(wx.StaticText(self,-1,name))
199        sizer_dispersion.Add(self.enable_disp )
200        sizer_dispersion.Add((20,20))
201        sizer_dispersion.Add(self.disable_disp )
202        sizer_dispersion.Add((10,10))
203       
204        ## fill a sizer with the combobox to select dispersion type
205        sizer_select_dispers = wx.BoxSizer(wx.HORIZONTAL) 
206        self.model_disp = wx.StaticText(self, -1, 'Distribution Function ')
207           
208        import sans.models.dispersion_models 
209        self.polydisp= sans.models.dispersion_models.models
210        self.disp_box = wx.ComboBox(self, -1)
211       
212        for key in self.polydisp.iterkeys():
213            name = str(key.__name__)
214            if name=="ArrayDispersion":
215                # Remove the option until the rest of the code is ready for it
216                self.disp_box.Append("Select customized Model",key)
217               
218            else:
219                self.disp_box.Append(name,key)
220        self.disp_box.SetSelection(0) 
221       
222        wx.EVT_COMBOBOX(self.disp_box,-1, self._on_select_Disp) 
223             
224        sizer_select_dispers.Add((10,10)) 
225        sizer_select_dispers.Add(self.model_disp) 
226        sizer_select_dispers.Add(self.disp_box) 
227        sizer_select_dispers.Add((10,10)) 
228        self.model_disp.Hide()
229        self.disp_box.Hide()
230       
231        boxsizer1.Add( sizer_dispersion )
232        boxsizer1.Add( (10,10) )
233        boxsizer1.Add( sizer_select_dispers )
234        self.sizer4_4 = wx.GridBagSizer(5,5)
235        boxsizer1.Add( self.sizer4_4  )
236        #-----------------------------------------------------
237        self.sizer4.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
238        self.sizer4_4.Layout()
239        self.sizer4.Layout()
240        self.Layout()
241        self.SetScrollbars(20,20,200,100)
242        self.Refresh()
243       
244   
245    def select_disp_angle(self, event): 
246        """
247            Event for when a user select a parameter to average over.
248            @param event: check box event
249        """
250       
251       
252        # Go through the list of dispersion check boxes to identify which one has changed
253        for p in self.disp_cb_dict:
254            # Catch which one of the box was just checked or unchecked.
255            if event.GetEventObject() == self.disp_cb_dict[p]:             
256
257               
258                if self.disp_cb_dict[p].GetValue() == True:
259                    # The user wants this parameter to be averaged.
260                    # Pop up the file selection dialog.
261                    path = self._selectDlg()
262                   
263                    # If nothing was selected, just return
264                    if path is None:
265                        self.disp_cb_dict[p].SetValue(False)
266                        return
267                    try:
268                        self._default_save_location = os.path.dirname(path)
269                    except:
270                        pass 
271                    try:
272                        values,weights = self.read_file(path)
273                    except:
274                        msg="Could not read input file"
275                        wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
276                        return
277                   
278                    # If any of the two arrays is empty, notify the user that we won't
279                    # proceed
280                    if values is None or weights is None:
281                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
282                            "The loaded %s distrubtion is corrupted or empty" % p))
283                        return
284                       
285                    # Tell the user that we are about to apply the distribution
286                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
287                            "Applying loaded %s distribution: %s" % (p, path))) 
288                   
289                    # Create the dispersion objects
290                    from sans.models.dispersion_models import ArrayDispersion
291                    disp_model = ArrayDispersion()
292                    disp_model.set_weights(values, weights)
293                    # Store the object to make it persist outside the scope of this method
294                    #TODO: refactor model to clean this up?
295                    self._disp_obj_dict[p] = disp_model
296                    print "dispersity------>",p
297                    # Set the new model as the dispersion object for the selected parameter
298                    self.model.set_dispersion(p, disp_model)
299                         
300                else:
301                    # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
302                    self._reset_dispersity()
303                   
304                ## Redraw the model
305                self._draw_model()
306        return
307   
308   
309    def onResetModel(self, event):
310        """
311            Reset model state
312        """
313        ## post help message for the selected model
314        msg = self.slicerpop.GetHelpString(event.GetId())
315        msg +=" reloaded"
316        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
317       
318        name= self.slicerpop.GetLabel(event.GetId())
319        if name in self.saved_states.keys():
320            previous_state = self.saved_states[name]
321            self.reset_page(previous_state)
322           
323   
324    def onSave(self, event):
325        """
326            save history of the data and model
327        """
328        if self.model==None:
329            return 
330        if hasattr(self,"enable_disp"):
331            self.state.enable_disp = self.enable_disp.GetValue()
332        if hasattr(self, "disp_box"):
333            self.state.disp_box = self.disp_box.GetSelection()
334       
335        self.state.model = self.model.clone()
336        new_state = self.state.clone()
337       
338        ##Add model state on context menu
339        self.number_saved_state += 1
340        name= self.model.name+"[%g]"%self.number_saved_state
341        self.saved_states[name]= new_state
342       
343        ## Add item in the context menu
344        year, month, day,hour,minute,second,tda,ty,tm_isdst= time.gmtime()
345        my_time= str(hour)+"hrs "+str(minute)+"min "+str(second)+"s"
346        date= str( month)+"|"+str(day)+"|"+str(year)
347        msg=  "Model saved at %s on %s"%(my_time, date)
348         ## post help message for the selected model
349        msg +=" Saved! right click on this page to retrieve this model"
350        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
351       
352        id = wx.NewId()
353        self.slicerpop.Append(id,name,str(msg))
354        wx.EVT_MENU(self, id, self.onResetModel)
355       
356    def onSetFocus(self, evt):
357        """
358            highlight the current textcrtl and hide the error text control shown
359            after fitting
360        """
361       
362        if hasattr(self,"text2_3"):
363            self.text2_3.Hide()
364        if len(self.parameters)>0:
365            for item in self.parameters:
366                ## hide statictext +/-   
367                if item[3]!=None:
368                    item[3].Hide()
369                ## hide textcrtl  for error after fit
370                if item[4]!=None:
371                    item[4].Clear()
372                    item[4].Hide()
373        if len(self.fittable_param)>0:
374            for item in self.fittable_param:
375                ## hide statictext +/-   
376                if item[3]!=None:
377                    item[3].Hide()
378                ## hide textcrtl  for error after fit
379                if item[4]!=None:
380                    item[4].Clear()
381                    item[4].Hide()
382        self.Layout()
383        # Get a handle to the TextCtrl
384        widget = evt.GetEventObject()
385        # Select the whole control, after this event resolves
386        wx.CallAfter(widget.SetSelection, -1,-1)
387        return
388   
389   
390    def read_file(self, path):
391        """
392            Read two columns file
393            @param path: the path to the file to read
394        """
395        try:
396            if path==None:
397                wx.PostEvent(self.parent.parent, StatusEvent(status=\
398                            " Selected Distribution was not loaded: %s"%path))
399                return None, None
400            input_f = open(path, 'r')
401            buff = input_f.read()
402            lines = buff.split('\n')
403           
404            angles = []
405            weights=[]
406            for line in lines:
407                toks = line.split()
408                if len(toks)==2:
409                    try:
410                        angle = float(toks[0])
411                        weight = float(toks[1])
412                    except:
413                        # Skip non-data lines
414                        pass
415                    angles.append(angle)
416                    weights.append(weight)
417            return numpy.array(angles), numpy.array(weights)
418        except:
419            raise 
420   
421   
422    def createMemento(self):
423        """
424            return the current state of the page
425        """
426        return self.state.clone()
427   
428   
429    def save_current_state(self):
430        """
431            Store current state
432        """
433        if self.model!= None:
434            self.state.model = self.model.clone()
435        self.state.save_data(self.data)
436   
437        if hasattr(self,"cb1"):
438            self.state.cb1= self.cb1.GetValue()
439           
440        if hasattr(self,"enable_disp"):
441            self.state.enable_disp= self.enable_disp.GetValue()
442           
443        if hasattr(self,"enable_smearer"):
444            self.state.enable_smearer = self.enable_smearer.GetValue()   
445           
446        if hasattr(self,"disp_box"):
447            self.state.disp_box = self.disp_box.GetCurrentSelection()
448        self._save_plotting_range()
449     
450        ## save checkbutton state and txtcrtl values
451        self.state.parameters=[]
452        self.state.fittable_param=[]
453        self.state.fixed_param=[]
454       
455        self._copy_parameters_state(self.parameters, self.state.parameters)
456        self._copy_parameters_state(self.fittable_param, self.state.fittable_param)
457        self._copy_parameters_state(self.fixed_param, self.state.fixed_param)
458       
459        ## post state to fit panel
460        event = PageInfoEvent(page = self)
461        wx.PostEvent(self.parent, event)
462   
463   
464    def reset_page_helper(self, state):
465        """
466            Use page_state and change the state of existing page
467        """
468        self.state = state.clone()
469        self.model= self.state.model
470        self.data = self.state.data
471       
472        ##model parameter values restore
473        self._set_model_sizer_selection( self.model )
474        self.set_model_param_sizer(self.model)
475        if hasattr(self, "cb1"):   
476            self.cb1.SetValue(self.state.cb1)
477        ## display dispersion info layer
478        self.enable_disp.SetValue(self.state.enable_disp)
479        if hasattr(self, "disp_box"):
480            self.disp_box.SetSelection(self.state.disp_box) 
481        self._set_dipers_Param(event=None)
482       
483        ## smearing info  restore
484        if hasattr(self,"enable_smearer"):
485            self.enable_smearer.SetValue(state.enable_smearer)
486         ## reset state of checkbox,textcrtl  and parameters value
487       
488        ##plotting range restore   
489        self._reset_plotting_range()
490        ## reset context menu items
491        self._reset_context_menu()
492       
493        self._reset_parameters_state(self.parameters,state.parameters)
494        self._reset_parameters_state(self.fittable_param,state.fittable_param)
495        self._reset_parameters_state(self.fixed_param,state.fixed_param)
496       
497        ## draw the model with previous parameters value
498        self._draw_model()
499       
500   
501   
502         
503       
504    def _selectDlg(self):
505        """
506            open a dialog file to selected the customized dispersity
507        """
508        import os
509        dlg = wx.FileDialog(self, "Choose a weight file",
510                                self._default_save_location , "", "*.*", wx.OPEN)
511        path = None
512        if dlg.ShowModal() == wx.ID_OK:
513            path = dlg.GetPath()
514        dlg.Destroy()
515        return path
516   
517   
518    def _reset_context_menu(self):
519        """
520            reset the context menu
521        """
522        for name, state in self.state.saved_states.iteritems():
523            self.number_saved_state += 1
524            ## Add item in the context menu
525            id = wx.NewId()
526            self.slicerpop.Append(id,name, 'Save model and state %g'%self.number_saved_state)
527            wx.EVT_MENU(self, id, self.onResetModel)
528   
529    def _reset_plotting_range(self):
530        """
531            Reset the plotting range to a given state
532        """
533       
534        #self.qmin.SetValue(format_number(self.state.qmin))
535        #self.qmax.SetValue(format_number(self.state.qmax))
536        self.qmin.SetValue(str(self.state.qmin))
537        self.qmax.SetValue(str(self.state.qmax)) 
538        if self.state.npts!=None:
539            self.npts.SetValue(format_number(self.state.npts)) 
540            self.num_points = float(self.state.npts)
541           
542        self.qmin_x = float(self.qmin.GetValue())
543        self.qmax_x = float(self.qmax.GetValue())
544       
545       
546    def _save_plotting_range(self ):
547        """
548            save the state of plotting range
549        """
550        self.state.qmin = self.qmin_x
551        self.state.qmax = self.qmax_x
552        if self.npts!=None:
553            self.state.npts= self.num_points
554           
555           
556    def _onparamEnter_helper(self):
557        """
558             check if values entered by the user are changed and valid to replot
559             model
560             use : _check_value_enter
561        """
562        if self.model !=None:
563            ## save current state
564            self.save_current_state()
565            # Flag to register when a parameter has changed.
566            is_modified = False
567            is_modified =self._check_value_enter( self.fittable_param ,is_modified)
568            is_modified =self._check_value_enter( self.fixed_param ,is_modified)
569            is_modified =self._check_value_enter( self.parameters ,is_modified)       
570           
571           
572            self.Layout()
573            # Here we should check whether the boundaries have been modified.
574            # If qmin and qmax have been modified, update qmin and qmax and
575            # set the is_modified flag to True
576            from sans.guiframe.utils import check_value
577            if check_value( self.qmin, self.qmax):
578                if float(self.qmin.GetValue()) != self.qmin_x:
579                    self.qmin_x = float(self.qmin.GetValue())
580                    is_modified = True
581                if float(self.qmax.GetValue()) != self.qmax_x:
582                    self.qmax_x = float(self.qmax.GetValue())
583                    is_modified = True
584                self.fitrange = True
585            else:
586                self.fitrange = False
587            if self.npts != None:
588                if check_float(self.npts):
589                    if float(self.npts.GetValue()) !=  self.num_points:
590                        self.num_points = float(self.npts.GetValue())
591                        is_modified = True
592                else:
593                    msg= "Cannot Plot :Must enter a number!!!  "
594                    wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
595                   
596           
597            ## if any value is modify draw model with new value
598            if is_modified:
599                self._draw_model() 
600               
601               
602    def _reset_parameters_state(self, listtorestore,statelist):
603        """
604            Reset the parameters at the given state
605        """
606        if len(statelist)==0 or  len(listtorestore)==0 :
607            return
608        if len(statelist)!=  len(listtorestore) :
609            return
610        for j in range(len(listtorestore)):
611            item_page = listtorestore[j]
612            item_page_info = statelist[j]
613            ##change the state of the check box for simple parameters
614            if item_page[0]!=None:
615                item_page[0].SetValue(item_page_info[0])
616   
617            if item_page[2]!=None:
618                item_page[2].SetValue(item_page_info[2])
619               
620            if item_page[3]!=None:
621                ## show or hide text +/-
622                if item_page_info[2]:
623                    item_page[3].Show(True)
624                else:
625                    item_page[3].Hide()
626            if item_page[4]!=None:
627                ## show of hide the text crtl for fitting error
628                if item_page_info[4][0]:
629                    item_page[4].Show(True)
630                    item_page[4].SetValue(item_page_info[4][1])
631                else:
632                    item_page[3].Hide()
633            if item_page[5]!=None:
634                ## show of hide the text crtl for fitting error
635                if item_page_info[5][0]:
636                    item_page[5].Show(True)
637                    item_page[5].SetValue(item_page_info[4][1])
638                else:
639                    item_page[5].Hide()
640                   
641            if item_page[6]!=None:
642                ## show of hide the text crtl for fitting error
643                if item_page_info[6][0]:
644                    item_page[6].Show(True)
645                    item_page[6].SetValue(item_page_info[6][1])
646                else:
647                    item_page[6].Hide()
648                           
649                           
650    def _copy_parameters_state(self, listtocopy, statelist):
651        """
652            copy the state of button
653            @param listtocopy: the list of check button to copy
654            @param statelist: list of state object to store the current state
655        """
656        if len(listtocopy)==0:
657            return
658       
659        for item in listtocopy:
660            checkbox_state = None
661            if item[0]!= None:
662                checkbox_state= item[0].GetValue()
663            parameter_name = item[1]
664            parameter_value = None
665            if item[2]!=None:
666                parameter_value = item[2].GetValue()
667            static_text = None
668            if item[3]!=None:
669                static_text = item[3].IsShown()
670            error_value = None
671            error_state = None
672            if item[4]!= None:
673                error_value = item[4].GetValue()
674                error_state = item[4].IsShown()
675               
676            min_value = None
677            min_state = None
678            if item[5]!= None:
679                min_value = item[5].GetValue()
680                min_state = item[5].IsShown()
681               
682            max_value = None
683            max_state = None
684            if item[6]!= None:
685                max_value = item[6].GetValue()
686                max_state = item[6].IsShown()
687               
688            statelist.append([checkbox_state, parameter_name, parameter_value,
689                              static_text ,[error_state,error_value],
690                                [min_state,min_value],[max_state , max_value],None])
691           
692       
693   
694    def _set_model_sizer_selection(self, model):
695        """
696            Display the sizer according to the type of the current model
697        """
698        if hasattr(model ,"model2"):
699           
700            class_name= model.model2.__class__
701            name= model.model2.name
702            flag= name != "NoStructure"
703            if flag and (class_name in self.model_list_box["Structure Factors"]):
704                self.structurebox.Enable()
705                items = self.structurebox.GetItems()
706                self.sizer1.Layout()
707                self.SetScrollbars(20,20,200,100)
708                for i in range(len(items)):
709                    if items[i]== str(name):
710                        self.structurebox.SetSelection(i)
711                        break
712                   
713        if hasattr(model ,"model1"):
714            class_name = model.model1.__class__
715            name = model.model1.name
716            self.formfactorbox.Clear()
717           
718            for k, list in self.model_list_box.iteritems():
719                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
720                    self.shape_rbutton.SetValue(True)
721                    ## fill the form factor list with new model
722                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
723                    items = self.formfactorbox.GetItems()
724                    ## set comboxbox to the selected item
725                    for i in range(len(items)):
726                        if items[i]== str(name):
727                            self.formfactorbox.SetSelection(i)
728                            break
729                    return
730                elif k == "Shape-Independent":
731                    self.shape_indep_rbutton.SetValue(True)
732                elif k == "Structure Factors":
733                     self.struct_rbutton.SetValue(True)
734                else:
735                    self.plugin_rbutton.SetValue(True)
736               
737                if class_name in list:
738                    ## fill the form factor list with new model
739                    self._populate_box(self.formfactorbox, list)
740                    items = self.formfactorbox.GetItems()
741                    ## set comboxbox to the selected item
742                    for i in range(len(items)):
743                        if items[i]== str(name):
744                            self.formfactorbox.SetSelection(i)
745                            break
746                    break
747        else:
748            ## Select the model from the combobox
749            class_name = model.__class__
750            name = model.name
751            self.formfactorbox.Clear()
752            items = self.formfactorbox.GetItems()
753   
754            for k, list in self.model_list_box.iteritems():
755                if k in["P(Q)*S(Q)","Shapes" ] and class_name in self.model_list_box["Shapes"]:
756                   
757                    if class_name in self.model_list_box["P(Q)*S(Q)"]:
758                        self.structurebox.Enable()
759                    else:
760                        self.structurebox.Disable()
761                        self.structurebox.SetSelection(0)
762                       
763                    self.shape_rbutton.SetValue(True)
764                    ## fill the form factor list with new model
765                    self._populate_box(self.formfactorbox,self.model_list_box["Shapes"])
766                    items = self.formfactorbox.GetItems()
767                    ## set comboxbox to the selected item
768                    for i in range(len(items)):
769                        if items[i]== str(name):
770                            self.formfactorbox.SetSelection(i)
771                            break
772                    return
773                elif k == "Shape-Independent":
774                    self.shape_indep_rbutton.SetValue(True)
775                elif k == "Structure Factors":
776                     self.struct_rbutton.SetValue(True)
777                else:
778                    self.plugin_rbutton.SetValue(True)
779                if class_name in list:
780                    self.structurebox.SetSelection(0)
781                    self.structurebox.Disable()
782                    ## fill the form factor list with new model
783                    self._populate_box(self.formfactorbox, list)
784                    items = self.formfactorbox.GetItems()
785                    ## set comboxbox to the selected item
786                    for i in range(len(items)):
787                        if items[i]== str(name):
788                            self.formfactorbox.SetSelection(i)
789                            break
790                    break
791                   
792       
793    def _draw_model(self):
794        """
795            Method to draw or refresh a plotted model.
796            The method will use the data member from the model page
797            to build a call to the fitting perspective manager.
798           
799            [Note to coder: This way future changes will be done in only one place.]
800        """
801        if self.model !=None:
802            self.manager.draw_model(self.model, data=self.data,
803                                    qmin=float(self.qmin_x), qmax=float(self.qmax_x),
804                                    qstep= float(self.num_points),
805                                    enable2D=self.enable2D) 
806       
807    def _set_model_sizer(self, sizer, title="", object=None):
808        """
809            Use lists to fill a sizer for model info
810        """
811       
812        sizer.Clear(True)
813        box_description= wx.StaticBox(self, -1,str(title))
814        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
815        #--------------------------------------------------------
816        self.shape_rbutton = wx.RadioButton(self, -1, 'Shapes', style=wx.RB_GROUP)
817        self.shape_indep_rbutton = wx.RadioButton(self, -1, "Shape-Independent")
818        self.struct_rbutton = wx.RadioButton(self, -1, "Structure Factor ")
819        self.plugin_rbutton = wx.RadioButton(self, -1, "Customized Models")
820       
821        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
822                            id= self.shape_rbutton.GetId() ) 
823        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
824                            id= self.shape_indep_rbutton.GetId() ) 
825        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
826                            id= self.struct_rbutton.GetId() ) 
827        self.Bind( wx.EVT_RADIOBUTTON, self._show_combox,
828                            id= self.plugin_rbutton.GetId() ) 
829       
830     
831        sizer_radiobutton = wx.GridSizer(2, 2,5, 5)
832        sizer_radiobutton.Add(self.shape_rbutton)
833        sizer_radiobutton.Add(self.shape_indep_rbutton)
834        sizer_radiobutton.Add(self.plugin_rbutton)
835        sizer_radiobutton.Add(self.struct_rbutton)
836       
837        sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
838       
839        self.text1 = wx.StaticText( self,-1,"" )
840        self.text2 = wx.StaticText( self,-1,"P(Q)*S(Q)" )
841       
842       
843        self.formfactorbox = wx.ComboBox(self, -1,style=wx.CB_READONLY)
844        if self.model!=None:
845            self.formfactorbox.SetValue(self.model.name)
846           
847           
848        self.structurebox = wx.ComboBox(self, -1,style=wx.CB_READONLY)
849        wx.EVT_COMBOBOX(self.formfactorbox,-1, self._on_select_model)
850        wx.EVT_COMBOBOX(self.structurebox,-1, self._on_select_model)
851       
852       
853       
854        ## fill combox box
855        if len(self.model_list_box)>0:
856            self._populate_box( self.formfactorbox,self.model_list_box["Shapes"])
857       
858        if len(self.model_list_box)>0:
859            self._populate_box( self.structurebox,
860                                self.model_list_box["Structure Factors"])
861            self.structurebox.Insert("None", 0,None)
862            self.structurebox.SetSelection(0)
863            self.structurebox.Disable()
864 
865            if self.model.__class__ in self.model_list_box["P(Q)*S(Q)"]:
866                self.structurebox.Enable()
867           
868       
869        ## check model type to show sizer
870        if self.model !=None:
871            self._set_model_sizer_selection( self.model )
872       
873        sizer_selection.Add(self.text1)
874        sizer_selection.Add((5,5))
875        sizer_selection.Add(self.formfactorbox)
876        sizer_selection.Add((5,5))
877        sizer_selection.Add(self.text2)
878        sizer_selection.Add((5,5))
879        sizer_selection.Add(self.structurebox)
880        sizer_selection.Add((5,5))
881       
882        boxsizer1.Add( sizer_radiobutton )
883        boxsizer1.Add( (20,20))
884        boxsizer1.Add( sizer_selection )
885        if object !=None:
886            boxsizer1.Add( (-72,-72))
887            boxsizer1.Add( object,  0, wx.ALIGN_RIGHT| wx.RIGHT, 10)
888            boxsizer1.Add( (60,60))
889        #--------------------------------------------------------
890        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
891        sizer.Layout()
892        self.SetScrollbars(20,20,200,100)
893       
894       
895    def _show_combox(self, event):
896        """
897            Show combox box associate with type of model selected
898        """
899        ## Don't want to populate combo box again if the event comes from check box
900        if self.shape_rbutton.GetValue()and\
901             event.GetEventObject()==self.shape_rbutton:
902            ##fill the combobox with form factor list
903            self.structurebox.SetSelection(0)
904            self.structurebox.Disable()
905            self.formfactorbox.Clear()
906            self._populate_box( self.formfactorbox,self.model_list_box["Shapes"])
907           
908        if self.shape_indep_rbutton.GetValue()and\
909             event.GetEventObject()==self.shape_indep_rbutton:
910            ##fill the combobox with shape independent  factor list
911            self.structurebox.SetSelection(0)
912            self.structurebox.Disable()
913            self.formfactorbox.Clear()
914            self._populate_box( self.formfactorbox,
915                                self.model_list_box["Shape-Independent"])
916           
917        if self.struct_rbutton.GetValue() and\
918             event.GetEventObject()==self.struct_rbutton:
919            ##fill the combobox with structure factor list
920            self.structurebox.SetSelection(0)
921            self.structurebox.Disable()
922            self.formfactorbox.Clear()
923            self._populate_box( self.formfactorbox,
924                                self.model_list_box["Structure Factors"])
925           
926        if self.plugin_rbutton.GetValue()and\
927             event.GetEventObject()==self.plugin_rbutton:
928           
929            ##fill the combobox with form factor list
930            self.structurebox.Disable()
931            self.formfactorbox.Clear()
932            self._populate_box( self.formfactorbox,
933                                self.model_list_box["Customized Models"])
934       
935        self._on_select_model(event=None)
936        self.sizer4_4.Layout()
937        self.sizer4.Layout()
938        self.Layout()
939        self.Refresh()
940        self.SetScrollbars(20,20,200,100)
941           
942    def _populate_box(self, combobox, list):
943        """
944            fill combox box with dict item
945            @param list: contains item to fill the combox
946            item must model class
947        """
948        for models in list:
949            model= models()
950            name = model.__class__.__name__
951            if models.__name__!="NoStructure":
952                if hasattr(model, "name"):
953                    name = model.name
954                combobox.Append(name,models)
955        try:
956
957            combobox.SetSelection(0)
958           
959        except:
960            pass
961   
962        return 0
963   
964   
965    def _on_select_model_helper(self): 
966        """
967             call back for model selection
968        """
969        ## reset dictionary containing reference to dispersion
970        self._disp_obj_dict = {}
971        self.disp_cb_dict ={}
972        f_id = self.formfactorbox.GetCurrentSelection()
973        form_factor = self.formfactorbox.GetClientData( f_id )
974        if not form_factor in  self.model_list_box["multiplication"]:
975            self.structurebox.Disable()
976            self.structurebox.SetSelection(0)
977        else:
978            self.structurebox.Enable()
979           
980        s_id = self.structurebox.GetCurrentSelection()
981        struct_factor = self.structurebox.GetClientData( s_id )
982       
983        if  struct_factor !=None:
984            from sans.models.MultiplicationModel import MultiplicationModel
985            self.model= MultiplicationModel(form_factor(),struct_factor())
986        else:
987            self.model= form_factor()
988       
989        ## post state to fit panel
990        self.save_current_state()
991        self.sizer4_4.Layout()
992        self.sizer4.Layout()
993        self.Layout()
994        self.SetScrollbars(20,20,200,100)
995        self.Refresh()
996       
997       
998       
999    def _onparamEnter(self,event):
1000        """
1001            when enter value on panel redraw model according to changed
1002        """
1003        tcrtl= event.GetEventObject()
1004        if check_float(tcrtl):
1005            self._onparamEnter_helper()
1006        else:
1007            msg= "Cannot Plot :Must enter a number!!!  "
1008            wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1009            return 
1010       
1011       
1012    def _check_value_enter(self, list, modified):
1013        """
1014            @param list: model parameter and panel info
1015            each item of the list should be as follow:
1016            item=[cb state, name, value, "+/-", error of fit, min, max , units]
1017        """ 
1018        is_modified =  modified
1019        if len(list)==0:
1020            return is_modified
1021        for item in list:
1022            try:
1023                name = str(item[1])
1024                if hasattr(self,"text2_3"):
1025                    self.text2_3.Hide()
1026                ## check model parameters range
1027                ## check minimun value
1028                param_min= None
1029                param_max= None
1030                if item[5]!= None:
1031                    if format_number(item[5].GetValue())!="NaN":
1032                        param_min = float(item[5].GetValue())
1033                   
1034                ## check maximum value
1035                if item[6]!= None:
1036                    if format_number(item[6].GetValue())!="NaN":
1037                        param_max = float(item[6].GetValue())
1038                       
1039                from sans.guiframe.utils import check_value
1040                if param_min != None and param_max !=None:
1041                    if not check_value(item[5], item[6]):
1042                        msg= "Wrong Fit range entered for parameter "
1043                        msg+= "name %s of model %s "%(name, self.model.name)
1044                        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1045                if name in self.model.details.keys():   
1046                    self.model.details[name][1:]= param_min,param_max
1047               
1048                ## hide statictext +/-   
1049                if item[3]!=None:
1050                    item[3].Hide()
1051                ## hide textcrtl  for error after fit
1052                if item[4]!=None:
1053                    item[4].Clear()
1054                    item[4].Hide()
1055                   
1056           
1057                value= float(item[2].GetValue())
1058               
1059                # If the value of the parameter has changed,
1060                # +update the model and set the is_modified flag
1061                if value != self.model.getParam(name):
1062                    self.model.setParam(name,value)
1063                    is_modified = True   
1064           
1065            except:
1066                msg= "Model Drawing  Error:wrong value entered : %s"% sys.exc_value
1067                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
1068                return 
1069       
1070        return is_modified
1071       
1072 
1073    def _set_dipers_Param(self, event):
1074        """
1075            Add more item to select user dispersity
1076        """
1077        if self.model == None:
1078            msg= " Select non - model value:%s !"%self.model
1079            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
1080            return 
1081        else:
1082           
1083            if self.enable_disp.GetValue():
1084                self.model_disp.Show(True)
1085                self.disp_box.Show(True)
1086                ## layout for model containing no dispersity parameters
1087                if len(self.disp_list)==0:
1088                    self._layout_sizer_noDipers() 
1089                else:
1090                    ## set gaussian sizer
1091                    self._on_select_Disp(event=None)
1092            else:
1093                self.model_disp.Hide()
1094                self.disp_box.Hide()
1095                self.sizer4_4.Clear(True)
1096                self._reset_dispersity()
1097               
1098         
1099            ## post state to fit panel
1100            self.save_current_state()
1101           
1102         
1103           
1104       
1105    def _layout_sizer_noDipers(self):
1106        """
1107            Draw a sizer with no dispersity info
1108        """
1109        ix=0
1110        iy=1
1111        self.fittable_param=[]
1112        self.fixed_param=[]
1113        self.model_disp.Hide()
1114        self.disp_box.Hide()
1115        self.sizer4_4.Clear(True)
1116        model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
1117        self.sizer4_4.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1118        self.sizer4_4.Layout()
1119        self.sizer4.Layout()
1120        self.SetScrollbars(20,20,200,100)
1121     
1122           
1123    def _reset_dispersity(self):
1124        """
1125             put gaussian dispersity into current model
1126        """
1127        self.fittable_param=[]
1128        self.fixed_param=[]
1129       
1130        from sans.models.dispersion_models import GaussianDispersion
1131        if len(self.disp_cb_dict)==0:
1132            self.sizer4_4.Clear(True)
1133            self.sizer4_4.Layout()
1134            self.sizer4.Layout()
1135            self.Layout()
1136            self.Refresh()
1137            self.SetScrollbars(20,20,200,100)   
1138            return 
1139       
1140        for p in self.disp_cb_dict:
1141            # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
1142            disp_model = GaussianDispersion()
1143            # Store the object to make it persist outside the scope of this method
1144            #TODO: refactor model to clean this up?
1145            self._disp_obj_dict[p] = disp_model
1146            # Set the new model as the dispersion object for the selected parameter
1147            self.model.set_dispersion(p, disp_model)
1148            # Redraw the model
1149            self._draw_model()
1150           
1151        self.sizer4_4.Layout()
1152        self.sizer4.Layout()
1153        self.Layout()
1154        self.SetScrollbars(20,20,200,100)   
1155        self.Refresh()
1156       
1157           
1158           
1159    def _on_select_Disp(self,event):
1160        """
1161             allow selecting different dispersion
1162             self.disp_list should change type later .now only gaussian
1163        """
1164       
1165        n = self.disp_box.GetCurrentSelection()
1166        dispersity= self.disp_box.GetClientData(n)
1167        name= dispersity.__name__
1168        if name == "GaussianDispersion":
1169            self._set_sizer_gaussian()
1170           
1171        if  name=="ArrayDispersion":
1172            self._set_sizer_arraydispersion()
1173           
1174        self.state.disp_box= n
1175        ## post state to fit panel
1176        event = PageInfoEvent(page = self)
1177        wx.PostEvent(self.parent, event)
1178       
1179        self.sizer4_4.Layout()
1180        self.sizer4.Layout()
1181        self.Layout()
1182        self.SetScrollbars(20,20,200,100)
1183        self.Refresh()
1184       
1185       
1186       
1187       
1188    def _set_sizer_arraydispersion(self):
1189        """
1190            draw sizer with array dispersity  parameters
1191        """
1192        self.orientation_params_disp=[]
1193        self.sizer4_4.Clear(True) 
1194        ix=0
1195        iy=1     
1196        disp1 = wx.StaticText(self, -1, 'Array Dispersion')
1197        self.sizer4_4.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
1198       
1199        # Look for model parameters to which we can apply an ArrayDispersion model
1200        # Add a check box for each parameter.
1201        self.disp_cb_dict = {}
1202        for p in self.model.dispersion.keys():
1203            ix+=1 
1204            self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
1205           
1206            wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
1207            self.sizer4_4.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
1208       
1209        ix =0
1210        iy +=1 
1211        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
1212        self.sizer4_4.Layout()
1213        self.sizer4.Layout()
1214        self.SetScrollbars(20,20,200,100)
1215       
1216       
1217    def _set_range_sizer(self, title, object1=None,object=None):
1218        """
1219            Fill the
1220        """
1221        self.sizer5.Clear(True)
1222        box_description= wx.StaticBox(self, -1,str(title))
1223        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1224        #--------------------------------------------------------------
1225        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
1226        #For qmin and qmax, do not use format_number.(If do, qmin and max could be different from what is in the data.)
1227        #self.qmin.SetValue(format_number(self.qmin_x))
1228        self.qmin.SetValue(str(self.qmin_x))
1229        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
1230        self.qmin.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1231        self.qmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
1232        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
1233     
1234        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
1235        #For qmin and qmax, do not use format_number.(If do, qmin and max could be different from what is in the data.)
1236        #self.qmax.SetValue(format_number(self.qmax_x))
1237        self.qmax.SetValue(str(self.qmax_x))
1238        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
1239        self.qmax.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1240        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
1241        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
1242     
1243        sizer_horizontal=wx.BoxSizer(wx.HORIZONTAL)
1244        sizer= wx.GridSizer(3, 3,5, 5)
1245       
1246        sizer.Add((5,5))
1247        sizer.Add(wx.StaticText(self, -1, 'Min'))
1248        sizer.Add(wx.StaticText(self, -1, 'Max'))
1249        sizer.Add(wx.StaticText(self, -1, 'Q range'))
1250             
1251        sizer.Add(self.qmin)
1252        sizer.Add(self.qmax)
1253        sizer_horizontal.Add(sizer)
1254        if object!=None:
1255            sizer_horizontal.Add(object)
1256       
1257        if object1!=None:
1258           boxsizer1.Add(object1) 
1259           boxsizer1.Add((10,10))
1260        boxsizer1.Add(sizer_horizontal)
1261        ## save state
1262        self.save_current_state()
1263        #----------------------------------------------------------------
1264        self.sizer5.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1265        self.sizer5.Layout()
1266        self.Layout()
1267        self.SetScrollbars(20,20,200,100)
1268   
1269   
1270    def _fill_save_sizer(self):
1271        """
1272            Draw the layout for saving option
1273        """
1274        self.sizer6.Clear(True)
1275        box_description= wx.StaticBox(self, -1,"Save Status")
1276        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1277        sizer_save = wx.BoxSizer(wx.HORIZONTAL)
1278       
1279        self.btSave_title = wx.StaticText(self, -1, 'Save the current panel status')
1280        self.btSave = wx.Button(self,wx.NewId(),'Save')
1281        self.btSave.Bind(wx.EVT_BUTTON, self.onSave,id= self.btSave.GetId())
1282        self.btSave.SetToolTipString("Save current panel status")
1283       
1284        sizer_save.Add(self.btSave_title) 
1285        sizer_save.Add((20,20),0, wx.LEFT|wx.RIGHT|wx.EXPAND,45) 
1286             
1287        sizer_save.Add(self.btSave)     
1288       
1289        boxsizer1.Add(sizer_save)
1290        self.sizer6.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1291        self.sizer6.Layout()
1292        self.SetScrollbars(20,20,200,100)
1293       
1294       
1295               
Note: See TracBrowser for help on using the repository browser.