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

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

fittting range for parameters fixed

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