source: sasview/sansview/perspectives/fitting/basepage.py @ b787e68c

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

working on saving page state

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