source: sasview/sansview/perspectives/fitting/basepage.py @ 77e23a2

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

add fit with parameter range when selecting park only

  • Property mode set to 100644
File size: 42.0 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       
814       
815    def _onparamEnter(self,event):
816        """
817            when enter value on panel redraw model according to changed
818        """
819        self._onparamEnter_helper()
820       
821       
822    def _check_value_enter(self, list, modified):
823        """
824            @param list: model parameter and panel info
825            each item of the list should be as follow:
826            item=[cb state, name, value, "+/-", error of fit, min, max , units]
827        """ 
828        is_modified =  modified
829        if len(list)==0:
830            return is_modified
831        for item in list:
832            try:
833                name = str(item[1])
834                if hasattr(self,"text2_3"):
835                    self.text2_3.Hide()
836                ## check model parameters range
837                ## check minimun value
838                param_min= None
839                param_max= None
840                if item[5]!= None:
841                    if format_number(item[5].GetValue())!="NaN":
842                        param_min = float(item[5].GetValue())
843                    self.model.details[name][1]=param_min
844                ## check maximum value
845                if item[6]!= None:
846                    if format_number(item[6].GetValue())!="NaN":
847                        param_max = float(item[6].GetValue())
848                       
849                from sans.guiframe.utils import check_value
850                if param_min != None and param_max !=None:
851                    if check_value(item[5], item[6]):
852                        self.model.details[name][1:]=param_min,param_max
853                    else:
854                        msg= "Wrong Fit range entered for parameter "
855                        msg+= "name %s of model %s "%(name, self.model.name)
856                        wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
857                        self.model.details[name][1:]=param_min,param_max
858                ## hide statictext +/-   
859                if item[3]!=None:
860                    item[3].Hide()
861                ## hide textcrtl  for error after fit
862                if item[4]!=None:
863                    item[4].Clear()
864                    item[4].Hide()
865               
866                value= float(item[2].GetValue())
867                # If the value of the parameter has changed,
868                # +update the model and set the is_modified flag
869                if value != self.model.getParam(name):
870                    self.model.setParam(name,value)
871                    is_modified = True   
872            except:
873                msg= "Model Drawing  Error:wrong value entered : %s"% sys.exc_value
874                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
875                return 
876       
877        return is_modified
878       
879       
880 
881    def _set_dipers_Param(self, event):
882        """
883            Add more item to select user dispersity
884        """
885        if self.model == None:
886            msg= " Select non - model value:%s !"%self.model
887            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
888            return 
889        else:
890            if self.enable_disp.GetValue():
891                self.model_disp.Show(True)
892                self.disp_box.Show(True)
893                ## layout for model containing no dispersity parameters
894                if len(self.disp_list)==0:
895                    self._layout_sizer_noDipers() 
896                else:
897                    ## set gaussian sizer
898                    self._set_sizer_gaussian() 
899            else:
900                self.model_disp.Hide()
901                self.disp_box.Hide()
902                self.sizer4_4.Clear(True)
903                self._reset_dispersity()
904           
905            self.sizer4.Layout()
906            self.Layout()
907            self.SetScrollbars(20,20,200,100)
908           
909   
910       
911    def _layout_sizer_noDipers(self):
912        """
913            Draw a sizer with no dispersity info
914        """
915        ix=0
916        iy=1
917        self.fittable_param=[]
918        self.fixed_param=[]
919        self.model_disp.Hide()
920        self.disp_box.Hide()
921        self.sizer4_4.Clear(True)
922        model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
923        self.sizer4_4.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
924        self.sizer4.Layout()
925        self.SetScrollbars(20,20,200,100)
926        return 
927   
928 
929           
930    def _reset_dispersity(self):
931        """
932             put gaussian dispersity into current model
933        """
934        self.fittable_param=[]
935        self.fixed_param=[]
936       
937        from sans.models.dispersion_models import GaussianDispersion
938        if len(self.disp_cb_dict)==0:
939            return 
940       
941        for p in self.disp_cb_dict:
942            # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
943            disp_model = GaussianDispersion()
944            # Store the object to make it persist outside the scope of this method
945            #TODO: refactor model to clean this up?
946            self._disp_obj_dict[p] = disp_model
947            # Set the new model as the dispersion object for the selected parameter
948            self.model.set_dispersion(p, disp_model)
949            # Redraw the model
950            self._draw_model()
951           
952           
953    def _on_select_Disp(self,event):
954        """
955             allow selecting different dispersion
956             self.disp_list should change type later .now only gaussian
957        """
958        dispersity  =event.GetClientData()
959        name= dispersity.__name__
960        if name == "GaussianDispersion":
961            self._set_sizer_gaussian()
962           
963        if  name=="ArrayDispersion":
964            self._set_sizer_arraydispersion()
965           
966           
967           
968   
969    def _set_sizer_arraydispersion(self):
970        """
971            draw sizer with array dispersity  parameters
972        """
973        self.sizer4_4.Clear(True) 
974        ix=0
975        iy=1     
976        disp1 = wx.StaticText(self, -1, 'Array Dispersion')
977        self.sizer4_4.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
978       
979        # Look for model parameters to which we can apply an ArrayDispersion model
980        # Add a check box for each parameter.
981        self.disp_cb_dict = {}
982        for p in self.model.dispersion.keys():
983            ix+=1 
984            self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
985           
986            wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
987            self.sizer4_4.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
988       
989        ix =0
990        iy +=1 
991        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
992        self.sizer4_4.Layout()
993        self.sizer4.Layout()
994        self.SetScrollbars(20,20,200,100)
995       
996       
997    def _set_range_sizer(self, title, object1=None,object=None):
998        """
999            Fill the
1000        """
1001        self.sizer5.Clear(True)
1002        box_description= wx.StaticBox(self, -1,str(title))
1003        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1004        #--------------------------------------------------------------
1005        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
1006        self.qmin.SetValue(format_number(self.qmin_x))
1007        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
1008        self.qmin.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1009        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
1010     
1011        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
1012        self.qmax.SetValue(format_number(self.qmax_x))
1013        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
1014        self.qmax.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
1015        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
1016     
1017        sizer_horizontal=wx.BoxSizer(wx.HORIZONTAL)
1018        sizer= wx.GridSizer(3, 3,5, 5)
1019       
1020        sizer.Add((5,5))
1021        sizer.Add(wx.StaticText(self, -1, 'Min'))
1022        sizer.Add(wx.StaticText(self, -1, 'Max'))
1023        sizer.Add(wx.StaticText(self, -1, 'Q range'))
1024             
1025        sizer.Add(self.qmin)
1026        sizer.Add(self.qmax)
1027        sizer_horizontal.Add(sizer)
1028        if object!=None:
1029            sizer_horizontal.Add(object)
1030       
1031        if object1!=None:
1032           boxsizer1.Add(object1) 
1033           boxsizer1.Add((10,10))
1034        boxsizer1.Add(sizer_horizontal)
1035       
1036        #----------------------------------------------------------------
1037        self.sizer5.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1038        self.sizer5.Layout()
1039        self.SetScrollbars(20,20,200,100)
1040   
1041    def _fill_save_sizer(self):
1042        """
1043            Draw the layout for saving option
1044        """
1045        self.sizer6.Clear(True)
1046        box_description= wx.StaticBox(self, -1,"Save Options")
1047        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
1048        sizer_save = wx.BoxSizer(wx.HORIZONTAL)
1049       
1050        self.btSave = wx.Button(self,wx.NewId(),'Save')
1051        self.btSave.Bind(wx.EVT_BUTTON, self.onSave,id= self.btSave.GetId())
1052        self.btSave.SetToolTipString("Save current state")
1053         
1054        sizer_save.Add((20,20),0, wx.LEFT|wx.RIGHT|wx.EXPAND,120)       
1055        sizer_save.Add(self.btSave)     
1056       
1057        boxsizer1.Add(sizer_save)
1058        self.sizer6.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
1059        self.sizer6.Layout()
1060        self.SetScrollbars(20,20,200,100)
1061       
1062       
1063               
Note: See TracBrowser for help on using the repository browser.