source: sasview/sansview/perspectives/fitting/modelpage.py @ bdb27e6

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 bdb27e6 was bdb27e6, checked in by Mathieu Doucet <doucetm@…>, 15 years ago

sansview: fixed problem with switching back to a Gaussian dispersity model after have used an ArrayDispersion? model (the dispersion model were not properly set to Gaussian before filling the form, which left the form blank).

  • Property mode set to 100644
File size: 40.2 KB
Line 
1import sys
2import wx
3import wx.lib
4import numpy
5import copy
6import math
7from sans.models.dispersion_models import ArrayDispersion, GaussianDispersion
8
9from sans.guicomm.events import StatusEvent   
10from sans.guiframe.utils import format_number
11(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
12_BOX_WIDTH = 80
13
14
15
16
17class ModelPage(wx.ScrolledWindow):
18    """
19        FitPanel class contains fields allowing to display results when
20        fitting  a model and one data
21        @note: For Fit to be performed the user should check at least one parameter
22        on fit Panel window.
23 
24    """
25    ## Internal name for the AUI manager
26    window_name = "Fit page"
27    ## Title to appear on top of the window
28    window_caption = "Fit Page"
29    name=""
30   
31    def __init__(self, parent,model,name, *args, **kwargs):
32        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
33        """
34            Initialization of the Panel
35        """
36        # model on which the fit would be performed
37        self.model=model
38       
39        ## Data member to store the dispersion object created
40        self._disp_obj_dict = {}
41
42        #list of dispersion paramaters
43        self.disp_list=[]
44        try:
45            self.disp_list=self.model.getDispParamList()
46        except:
47            pass 
48        self.manager = None
49        self.parent  = parent
50        self.event_owner = None
51        # this panel does contain data .existing data allow a different drawing
52        #on set_model parameters
53        self.data=None
54        #panel interface
55        self.vbox  = wx.BoxSizer(wx.VERTICAL)
56        self.sizer11 = wx.BoxSizer(wx.HORIZONTAL)
57        #self.sizer10 = wx.GridBagSizer(5,5)
58        self.sizer9 = wx.GridBagSizer(5,5)
59        self.sizer8 = wx.GridBagSizer(5,5)
60        self.sizer7 = wx.GridBagSizer(5,5)
61        self.sizer6 = wx.GridBagSizer(5,5)
62        self.sizer5 = wx.GridBagSizer(5,5)
63        self.sizer4 = wx.GridBagSizer(5,5)
64       
65        #model selection
66        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
67        self.vbox.Add(self.sizer4)
68        #model description
69        self.vbox.Add(self.sizer11)
70        #model paramaters layer
71        self.vbox.Add(self.sizer5)
72        #polydispersion selected
73        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
74        self.vbox.Add(self.sizer6)
75        #combox box for type of dispersion
76        self.vbox.Add(self.sizer7)
77        #dispersion parameters layer
78        self.vbox.Add(self.sizer8)
79        # plotting range
80        self.vbox.Add(self.sizer9)
81        #close layer
82        #self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
83        #self.vbox.Add(self.sizer10)
84       
85     
86        #------------------ sizer 4  draw------------------------ 
87       
88       
89        # define combox box
90        self.modelbox = wx.ComboBox(self, -1)
91         # preview selected model name
92        self.prevmodel_name=name
93        #print "model view prev_model",name
94        self.modelbox.SetValue(self.prevmodel_name)
95        #enable model 2D draw
96        self.enable2D= False
97        #filling sizer2
98        ix = 0
99        iy = 1
100        self.sizer4.Add(wx.StaticText(self,-1,'Model'),(iy,ix),(1,1)\
101                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
102        ix += 1
103        self.sizer4.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
104        ix += 1
105        id = wx.NewId()
106        self.model_view =wx.Button(self,id,'View 2D')
107        self.model_view.Bind(wx.EVT_BUTTON, self.onModel2D,id=id)
108        self.model_view.SetToolTipString("View model in 2D")
109       
110        self.sizer4.Add(self.model_view,(iy,ix),(1,1),\
111                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
112       
113        self.model_view.Enable()
114        self.model_view.SetFocus()
115       
116        ix = 0
117        iy += 1
118        self.sizer4.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
119
120        #----------sizer6-------------------------------------------------
121        self.disable_disp = wx.RadioButton(self, -1, 'No', (10, 10), style=wx.RB_GROUP)
122        self.enable_disp = wx.RadioButton(self, -1, 'Yes', (10, 30))
123        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.disable_disp.GetId())
124        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.enable_disp.GetId())
125        ix= 0
126        iy=1
127        self.sizer6.Add(wx.StaticText(self,-1,'Polydispersity: '),(iy,ix),(1,1)\
128                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
129        ix += 1
130        self.sizer6.Add(self.enable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
131        ix += 1
132        self.sizer6.Add(self.disable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
133        ix =0
134        iy+=1
135        self.sizer6.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
136
137       
138        #---------sizer 9 draw----------------------------------------
139       
140         ## Q range
141        self.qmin_x= 0.001
142        self.qmax_x= 0.1
143        self.num_points= 100
144       
145       
146        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
147        self.qmin.SetValue(format_number(self.qmin_x))
148        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
149        self.qmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
150        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
151     
152        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
153        self.qmax.SetValue(format_number(self.qmax_x))
154        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
155        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
156        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
157     
158
159        self.npts    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
160        self.npts.SetValue(format_number(self.num_points))
161        self.npts.SetToolTipString("Number of point to plot.")
162        self.npts.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
163        self.npts.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
164       
165        ix = 0
166        iy = 1 
167        self.sizer9.Add(wx.StaticText(self, -1, 'Plotting Range'),(iy, ix),(1,1),\
168                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
169        ix += 1 
170        self.sizer9.Add(wx.StaticText(self, -1, 'Min'),(iy, ix),(1,1),\
171                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
172        ix += 1
173        self.sizer9.Add(wx.StaticText(self, -1, 'Max'),(iy, ix),(1,1),\
174                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
175        ix += 1
176        self.sizer9.Add(wx.StaticText(self, -1, 'Npts'),(iy, ix),(1,1),\
177                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
178        ix = 0
179        iy += 1
180        self.sizer9.Add(wx.StaticText(self, -1, 'Q range'),(iy, ix),(1,1),\
181                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
182        ix += 1
183        self.sizer9.Add(self.qmin,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
184        ix += 1
185        self.sizer9.Add(self.qmax,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
186        ix += 1
187        self.sizer9.Add(self.npts,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
188       
189        ix =0
190        iy+=1 
191        self.sizer9.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
192        #----------sizer 10 draw------------------------------------------------------
193        """
194        id = wx.NewId()
195        self.btClose =wx.Button(self,id,'Close')
196        self.btClose.Bind(wx.EVT_BUTTON, self.onClose,id=id)
197        self.btClose.SetToolTipString("Close page.")
198       
199        ix= 3
200        iy= 1
201        self.sizer10.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
202        ix +=1
203        self.sizer10.Add( self.btClose,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
204        ix =0
205        iy+=1
206        self.sizer10.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
207        """
208        # contains link between  model ,all its parameters, and panel organization
209        self.parameters=[]
210        self.fixed_param=[]
211        self.fittable_param=[]
212        self.polydisp= {}
213        #contains link between a model and selected parameters to fit
214        self.param_toFit=[]
215       
216        #dictionary of model name and model class
217        self.model_list_box={}
218        #Draw initial panel
219         #-----sizer 11--------------------model description------
220        if self.model!=None:
221            self.set_panel(self.model)
222        self.theta_cb=None
223       
224       
225        self.vbox.Layout()
226        self.vbox.Fit(self) 
227        self.SetSizer(self.vbox)
228        self.SetScrollbars(20,20,55,40)
229       
230        self.Centre()
231        self.Layout()
232        self.parent.GetSizer().Layout()
233       
234    def _set_dispersion(self, par, disp_model):
235        """
236            Utility method to set a dispersion model while making
237            sure that the dispersion model object doesn't go out
238            of scope. The models should be cleaned up so we don't
239            have to do this.
240        """
241        # Store the object to make it persist outside the scope of this method
242        #TODO: refactor model to clean this up?
243        self._disp_obj_dict[par] = disp_model
244                   
245        # Set the new model as the dispersion object for the selected parameter
246        self.model.set_dispersion(par, disp_model)
247       
248    def set_model_description(self, model):
249       
250        if model !=None and str(model.description)!=""and self.data==None:
251            self.sizer11.Clear(True)
252            self.box_description= wx.StaticBox(self, -1, 'Model Description')
253            boxsizer1 = wx.StaticBoxSizer(self.box_description, wx.VERTICAL)
254            boxsizer1.SetMinSize((320,20))
255            self.description = wx.StaticText(self,-1,str(model.description))
256            boxsizer1.Add(self.description, 0, wx.EXPAND) 
257            self.sizer11.Add(boxsizer1,1, wx.EXPAND | wx.ALL, 2)
258     
259       
260    def set_owner(self,owner):
261        """
262            set owner of fitpage
263            @param owner: the class responsible of plotting
264        """
265        self.event_owner=owner   
266   
267 
268    def set_manager(self, manager):
269        """
270             set panel manager
271             @param manager: instance of plugin fitting
272        """
273        self.manager = manager 
274       
275    def populate_box(self, dict):
276        """
277            Populate each combox box of each page
278            @param page: the page to populate
279        """
280        id=0
281        self.model_list_box=dict
282        list_name=[]
283        for item in  self.model_list_box.itervalues():
284            name = item.__name__
285            if hasattr(item, "name"):
286                name = item.name
287            list_name.append(name)
288        list_name.sort() 
289         
290        for name in list_name:
291            self.modelbox.Insert(name,int(id))
292            id+=1
293        wx.EVT_COMBOBOX(self.modelbox,-1, self._on_select_model) 
294        return 0
295   
296
297    def Set_DipersParam(self, event):
298        """
299            This method is called when the user changes the state
300            of the "dispersity" radio buttons.
301           
302            #TODO: correct the spelling mistake in the name of this method, start name with lowercase.
303        """
304        if self.enable_disp.GetValue():
305            # The user selected to use dispersion/averaging
306            if len(self.disp_list)==0:
307                # This model contains no parameter to which we can apply dispersion/averaging
308                ix=0
309                iy=1
310                self.fittable_param=[]
311                self.fixed_param=[]
312                self.sizer8.Clear(True)
313                model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
314                self.sizer7.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
315                self.vbox.Layout()
316                self.SetScrollbars(20,20,55,40)
317                self.Layout()
318                self.parent.GetSizer().Layout()
319                return 
320            else:
321                # Show the default dispersion/averaging sub-panel
322                self.populate_disp_box()
323                self.set_panel_dispers(self.disp_list)
324               
325        else:
326            # The user selected not to use dispersion/averaging           
327            # Make sure all parameters have the default Gaussian
328            # dispersion object with only a single point (no dispersion).
329            for p in self.model.dispersion.keys():
330                disp_model = GaussianDispersion()
331                self._set_dispersion(p, disp_model)
332                   
333            # Redraw the model
334            self._draw_model()
335               
336            self.fittable_param=[]       
337            self.fixed_param=[]
338            self.sizer7.Clear(True)
339            self.sizer8.Clear(True)
340            self.vbox.Layout()
341            self.SetScrollbars(20,20,55,40)
342            self.Layout()
343            self.parent.GetSizer().Layout()
344           
345    def populate_disp_box(self):
346        self.sizer7.Clear(True)
347        if len(self.disp_list)>0:
348            ix=0
349            iy=1
350            model_disp = wx.StaticText(self, -1, 'Model Disp')
351            self.sizer7.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
352            ix += 1 
353            # set up the combox box
354            id = 0
355            import sans.models.dispersion_models 
356            self.polydisp= sans.models.dispersion_models.models
357            self.disp_box = wx.ComboBox(self, -1)
358            self.disp_box.SetValue("GaussianModel")
359            for k,v in self.polydisp.iteritems():
360                if str(v)=="MyModel":
361                    # Remove the option until the rest of the code is ready for it
362                    #self.disp_box.Insert("Select customized Model",id)
363                    pass 
364                else:
365                    self.disp_box.Insert(str(v),id)         
366                id+=1
367           
368            wx.EVT_COMBOBOX(self.disp_box,-1, self._on_select_Disp) 
369            self.sizer7.Add(self.disp_box,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
370            self.vbox.Layout()
371            self.SetScrollbars(20,20,55,40)
372            self.Layout()
373            self.parent.GetSizer().Layout() 
374           
375           
376    def set_range(self, qmin_x, qmax_x, npts):
377        """
378            Set the range for the plotted models
379            @param qmin: minimum Q
380            @param qmax: maximum Q
381            @param npts: number of Q bins
382        """
383        # Set the data members
384        self.qmin_x = qmin_x
385        self.qmax_x = qmax_x
386        self.num_points = npts
387       
388        # Set the controls
389        self.qmin.SetValue(format_number(self.qmin_x))
390        self.qmax.SetValue(format_number(self.qmax_x))
391        self.npts.SetValue(format_number(self.num_points))
392    def checkFitRange(self):
393        """
394            Check the validity of fitting range
395            @note: qmin should always be less than qmax or else each control box
396            background is colored in pink.
397        """
398       
399        flag = True
400        valueMin = self.qmin.GetValue()
401        valueMax = self.qmax.GetValue()
402        # Check for possible values entered
403        #print "fitpage: checkfitrange:",valueMin,valueMax
404        try:
405            if (float(valueMax)> float(valueMin)):
406                self.qmax.SetBackgroundColour(wx.WHITE)
407                self.qmin.SetBackgroundColour(wx.WHITE)
408            else:
409                flag = False
410                self.qmin.SetBackgroundColour("pink")
411                self.qmax.SetBackgroundColour("pink")     
412        except:
413            flag = False
414            self.qmin.SetBackgroundColour("pink")
415            self.qmax.SetBackgroundColour("pink")
416           
417        self.qmin.Refresh()
418        self.qmax.Refresh()
419        return flag
420   
421
422       
423    def onClose(self,event):
424        """ close the page associated with this panel"""
425        self.parent.onClose()
426       
427 
428       
429    def onModel2D(self, event):
430        """
431         call manager to plot model in 2D
432        """
433        # If the 2D display is not currently enabled, plot the model in 2D
434        # and set the enable2D flag.
435        if self.enable2D==False:
436            self.enable2D=True
437            self._draw_model()
438            self.model_view.Disable()
439           
440   
441    def select_model(self, model, name):
442        """
443            Select a new model
444            @param model: model object
445        """
446        self.model = model
447        self.parent.model_page.name = name
448        self.parent.draw_model_name = name
449       
450        self.set_panel(model)
451        self._draw_model(name)
452       
453        # Select the model from the combo box
454        items = self.modelbox.GetItems()
455        for i in range(len(items)):
456            if items[i]==name:
457                self.modelbox.SetSelection(i)
458                self.model_view.SetFocus()
459               
460    def _on_select_Disp(self,event):
461        """
462             allow selecting different dispersion
463             self.disp_list should change type later .now only gaussian
464        """
465        type =event.GetString()
466        self.set_panel_dispers( self.disp_list,type )
467               
468    def _on_select_model(self,event):
469        """
470            react when a model is selected from page's combo box
471            post an event to its owner to draw an appropriate theory
472        """
473        self.disable_disp.SetValue(True)
474        self.sizer8.Clear(True)
475        self.sizer7.Clear(True)       
476        self.vbox.Layout()
477        self.SetScrollbars(20,20,55,40)
478        self.Layout()
479        self.parent.GetSizer().Layout()
480        for item in self.model_list_box.itervalues():
481            name = item.__name__
482            if hasattr(item, "name"):
483                name = item.name
484            if name ==event.GetString():
485                model=item()
486                self.model= model
487                self.set_panel(model)
488                self.name= name
489                self.model_view.SetFocus()
490                self.parent.model_page.name=name
491                self.parent.draw_model_name=name
492               
493                self._draw_model(name)
494           
495           
496    def get_model_box(self): 
497        """ return reference to combox box self.model"""
498        return self.modelbox
499
500   
501    def get_param_list(self):
502        """
503            @return self.param_toFit: list containing  references to TextCtrl
504            checked.Theses TextCtrl will allow reference to parameters to fit.
505            @raise: if return an empty list of parameter fit will nnote work
506            properly so raise ValueError,"missing parameter to fit"
507        """
508        if self.param_toFit !=[]:
509            return self.param_toFit
510        else:
511            raise ValueError,"missing parameter to fit"
512       
513       
514    def set_panel(self,model):
515        """
516            Build the panel from the model content
517            @param model: the model selected in combo box for fitting purpose
518        """
519       
520        self.sizer5.Clear(True)
521        self.parameters = []
522        self.param_toFit=[]
523        self.fixed_param=[]
524        self.model = model
525       
526        self.set_model_description( self.model) 
527       
528        keys = self.model.getParamList()
529        #list of dispersion paramaters
530        self.disp_list=self.model.getDispParamList()
531       
532        keys.sort()
533        ik=0
534        im=1
535       
536        iy = 1
537        ix = 0
538        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
539        if self.data!=None:
540            wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
541            self.cb1.SetValue(False)
542        else:
543            self.cb1.Disable()
544            self.cb1.Hide()
545       
546        self.sizer5.Add(self.cb1,(iy, ix),(1,1),\
547                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
548        ix +=1
549        self.text2_2 = wx.StaticText(self, -1, 'Values')
550        self.sizer5.Add(self.text2_2,(iy, ix),(1,1),\
551                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
552        ix +=2
553        self.text2_3 = wx.StaticText(self, -1, 'Errors')
554        self.sizer5.Add(self.text2_3,(iy, ix),(1,1),\
555                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
556        self.text2_3.Hide() 
557       
558       
559        ix +=1
560        self.text2_4 = wx.StaticText(self, -1, 'Units')
561        self.sizer5.Add(self.text2_4,(iy, ix),(1,1),\
562                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
563        self.text2_4.Hide()
564        disp_list=self.model.getDispParamList()
565        for item in keys:
566            if not item in disp_list:
567                iy += 1
568                ix = 0
569   
570                cb = wx.CheckBox(self, -1, item, (10, 10))
571                if self.data!=None:
572                    cb.SetValue(False)
573                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
574                else:
575                    cb.Disable()
576                self.sizer5.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
577               
578                ix += 1
579                value= self.model.getParam(item)
580                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
581                ctl1.SetValue(str (format_number(value)))
582                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
583                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
584                self.sizer5.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
585               
586                ix += 1
587                text2=wx.StaticText(self, -1, '+/-')
588                self.sizer5.Add(text2,(iy, ix),(1,1),\
589                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
590                text2.Hide() 
591                ix += 1
592                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
593                self.sizer5.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
594                ctl2.Hide()
595               
596                ix +=1
597                # Units
598                try:
599                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
600                except:
601                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
602                self.sizer5.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
603           
604                self.parameters.append([cb,ctl1,text2,ctl2])
605               
606        iy+=1
607        self.sizer5.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
608       
609        #Display units text on panel
610        for item in keys:   
611            if self.model.details[item][0]!='':
612                self.text2_4.Show()
613                break
614            else:
615                self.text2_4.Hide()
616       
617        self.vbox.Layout()
618        self.SetScrollbars(20,20,55,40)
619        self.Layout()
620        self.parent.GetSizer().Layout()
621       
622       
623       
624    def _selectDlg(self):
625        import os
626        dlg = wx.FileDialog(self, "Choose a weight file", os.getcwd(), "", "*.*", wx.OPEN)
627        path = None
628        if dlg.ShowModal() == wx.ID_OK:
629            path = dlg.GetPath()
630        dlg.Destroy()
631        return path
632    def read_file(self, path):
633        try:
634            if path==None:
635                wx.PostEvent(self.parent.parent, StatusEvent(status=\
636                            " Selected Distribution was not loaded: %s"%path))
637                return None, None
638            input_f = open(path, 'r')
639            buff = input_f.read()
640            lines = buff.split('\n')
641           
642            angles = []
643            weights=[]
644            for line in lines:
645                toks = line.split()
646                if len(toks)==2:
647                    try:
648                        angle = float(toks[0])
649                        weight = float(toks[1])
650                    except:
651                        # Skip non-data lines
652                        pass
653                    angles.append(angle)
654                    weights.append(weight)
655            return numpy.array(angles), numpy.array(weights)
656        except:
657            raise 
658       
659         
660    def select_disp_angle(self, event): 
661        """
662            Event for when a user select a parameter to average over.
663            @param event: check box event
664        """
665       
666       
667        # Go through the list of dispersion check boxes to identify which one has changed
668        for p in self.disp_cb_dict:
669            # Catch which one of the box was just checked or unchecked.
670            if event.GetEventObject() == self.disp_cb_dict[p]:             
671
672               
673                if self.disp_cb_dict[p].GetValue() == True:
674                    # The user wants this parameter to be averaged.
675                    # Pop up the file selection dialog.
676                    path = self._selectDlg()
677                   
678                    # If nothing was selected, just return
679                    if path is None:
680                        self.disp_cb_dict[p].SetValue(False)
681                        return
682                   
683                    try:
684                        values,weights = self.read_file(path)
685                    except:
686                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
687                            "Could not read input file"))
688                        return
689                   
690                    # If any of the two arrays is empty, notify the user that we won't
691                    # proceed
692                    if values is None or weights is None:
693                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
694                            "The loaded %s distrubtion is corrupted or empty" % p))
695                        return
696                       
697                    # Tell the user that we are about to apply the distribution
698                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
699                            "Applying loaded %s distribution: %s" % (p, path))) 
700                   
701                    # Create the dispersion objects
702                    disp_model = ArrayDispersion()
703                    disp_model.set_weights(values, weights)
704                    self._set_dispersion(p, disp_model)
705                   
706                    # Redraw the model
707                    self._draw_model()
708                         
709                else:
710                    # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
711                    disp_model = GaussianDispersion()
712                    self._set_dispersion(p, disp_model)
713                   
714                    # Redraw the model
715                    self._draw_model()
716        return
717
718                     
719                     
720                     
721    def set_panel_dispers(self, disp_list, type="GaussianModel" ):
722        """
723        """
724       
725        self.fittable_param=[]
726        self.fixed_param=[]
727       
728        ix=0
729        iy=1
730                ### this will become a separate method
731        #TODO: don't hard code text values to be shown on the interface
732        if type== "Select customized Model":
733            ix=0
734            iy=1
735            self.sizer8.Clear(True)       
736            disp1 = wx.StaticText(self, -1, 'Array Dispersion')
737            self.sizer8.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
738           
739            # Look for model parameters to which we can apply an ArrayDispersion model
740            # Add a check box for each parameter.
741            self.disp_cb_dict = {}
742            for p in self.model.dispersion.keys():
743                ix+=1 
744                self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
745               
746                wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
747                self.sizer8.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
748           
749            ix =0
750            iy +=1 
751            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
752            self.vbox.Layout()
753            self.SetScrollbars(20,20,55,40)
754            self.Layout()
755            self.parent.GetSizer().Layout() 
756           
757        if type== "GaussianModel" :
758
759            self.sizer8.Clear(True)
760            disp = wx.StaticText(self, -1, 'Dispersion')
761            self.sizer8.Add(disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
762            ix += 1 
763            values = wx.StaticText(self, -1, 'Values')
764            self.sizer8.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
765            ix +=2
766            self.text2_3 = wx.StaticText(self, -1, 'Errors')
767            self.sizer8.Add(self.text2_3,(iy, ix),(1,1),\
768                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
769            self.text2_3.Hide() 
770           
771            ix += 1 
772            npts = wx.StaticText(self, -1, 'Npts')
773            self.sizer8.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
774            ix += 1 
775            nsigmas = wx.StaticText(self, -1, 'Nsigmas')
776            self.sizer8.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
777           
778            disp_list.sort()
779            #print disp_list,self.model.dispersion
780            for item in self.model.dispersion.keys():
781                name1=item+".width"
782                name2=item+".npts"
783                name3=item+".nsigmas"
784                iy += 1
785               
786                # Make sure the dispersion model is Gaussian
787                if not self.model.dispersion[item]['type'] == 'gaussian': 
788                    disp_model = GaussianDispersion()
789                    self._set_dispersion(item, disp_model)
790               
791                # Create the interface
792                for p in self.model.dispersion[item].keys():
793                    #print "name 1 2 3", name1, name2, name3
794                    if p=="width":
795                        ix = 0
796                        cb = wx.CheckBox(self, -1, name1, (10, 10))
797                        if self.data !=None:
798                            cb.SetValue(False)
799                            wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
800                        else:
801                            cb.Disable()
802                        self.sizer8.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
803                        ix = 1
804                        value= self.model.getParam(name1)
805                        ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
806                        ctl1.SetValue(str (format_number(value)))
807                        ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
808                        ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
809                        self.sizer8.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
810                       
811                        ix = 2
812                        text2=wx.StaticText(self, -1, '+/-')
813                        self.sizer8.Add(text2,(iy, ix),(1,1),\
814                                        wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
815                        text2.Hide() 
816                        ix = 3
817                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
818                        self.sizer8.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
819                        ctl2.Hide()
820                        self.fittable_param.append([cb,ctl1,text2,ctl2])
821                       
822                       
823                    elif p=="npts":
824                            ix =4 
825                            value= self.model.getParam(name2)
826                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
827                            Tctl.SetValue(str (format_number(value)))
828                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
829                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
830                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
831                            self.fixed_param.append([name2, Tctl])
832                    elif p=="nsigmas":
833                            ix =5 
834                            value= self.model.getParam(name3)
835                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
836                            Tctl.SetValue(str (format_number(value)))
837                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
838                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
839                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
840                            self.fixed_param.append([name3, Tctl])
841                wx.PostEvent(self.parent.parent, StatusEvent(status=\
842                            " Selected Distribution: Gaussian"))   
843            ix =0
844            iy +=1 
845            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
846            self.vbox.Layout()
847            self.SetScrollbars(20,20,55,40)
848            self.Layout()
849            self.parent.GetSizer().Layout() 
850         
851    def checkFitValues(self,val_min, val_max):
852        """
853            Check the validity of input values
854        """
855        flag = True
856        min_value = val_min.GetValue()
857        max_value = val_max.GetValue()
858        # Check for possible values entered
859        if min_value.lstrip().rstrip() =="-inf":
860            min_value= -numpy.inf
861        if max_value.lstrip().rstrip() =="+inf":
862            max_value= numpy.inf
863        if  min_value==-numpy.inf and max_value== numpy.inf:
864            val_min.SetBackgroundColour(wx.WHITE)
865            val_min.Refresh()
866            val_max.SetBackgroundColour(wx.WHITE)
867            val_max.Refresh()
868            return flag
869        elif max_value== numpy.inf:
870            try:
871                float(min_value)
872                val_min.SetBackgroundColour(wx.WHITE)
873                val_min.Refresh()
874            except:
875                flag = False
876                val_min.SetBackgroundColour("pink")
877                val_min.Refresh()
878            return flag
879        elif min_value==-numpy.inf:
880            try:
881                float(max_value)
882                val_max.SetBackgroundColour(wx.WHITE)
883                val_max.Refresh()
884            except:
885                flag = False
886                val_max.SetBackgroundColour("pink")
887                val_max.Refresh()
888            return flag
889        else:   
890            if (float(min_value)< float(max_value)):
891                val_min.SetBackgroundColour(wx.WHITE)
892                val_min.Refresh()
893            else:
894                flag = False
895                val_min.SetBackgroundColour("pink")
896                val_min.Refresh()
897            return flag   
898           
899       
900    def _onparamEnter(self,event):
901        """
902            when enter value on panel redraw model according to changed
903        """
904        self.set_model_parameter()
905       
906    def set_model_parameter(self):
907        """
908        """
909        if len(self.parameters) !=0 and self.model !=None:
910            # Flag to register when a parameter has changed.
911            is_modified = False
912            for item in self.fittable_param:
913                try:
914                     name=str(item[0].GetLabelText())
915                     value= float(item[1].GetValue())
916                     # If the value of the parameter has changed,
917                     # update the model and set the is_modified flag
918                     if value != self.model.getParam(name):
919                         self.model.setParam(name,value)
920                         is_modified = True
921                         
922                except:
923                    #raise
924                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
925                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
926                    return 
927               
928               
929            for item in self.fixed_param:
930                try:
931                     name=str(item[0])
932                     value= float(item[1].GetValue())
933                     # If the value of the parameter has changed,
934                     # update the model and set the is_modified flag
935                     if value != self.model.getParam(name):
936                         self.model.setParam(name,value)
937                         is_modified = True
938                         
939                except:
940                    raise
941                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
942                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
943               
944            for item in self.parameters:
945                try:
946                     name=str(item[0].GetLabelText())
947                     value= float(item[1].GetValue())
948                     # If the value of the parameter has changed,
949                     # update the model and set the is_modified flag
950                     if value != self.model.getParam(name):
951                         self.model.setParam(name,value)
952                         is_modified = True
953                   
954                except:
955                    #raise
956                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
957                           "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
958                    return
959               
960               
961            # Here we should check whether the boundaries have been modified.
962            # If qmin and qmax have been modified, update qmin and qmax and
963            # set the is_modified flag to True
964            if float(self.qmin.GetValue()) != self.qmin_x:
965                self.qmin_x = float(self.qmin.GetValue())
966                is_modified = True
967            if float(self.qmax.GetValue()) != self.qmax_x:
968                self.qmax_x = float(self.qmax.GetValue())
969                is_modified = True
970           
971            if float(self.npts.GetValue()) !=  self.num_points:
972                self.num_points = float(self.npts.GetValue())
973                is_modified = True
974         
975            if is_modified:
976                self._draw_model()           
977           
978    def _draw_model(self, name=None):
979        """
980            Method to draw or refresh a plotted model.
981            The method will use the data member from the model page
982            to build a call to the fitting perspective manager.
983           
984            [Note to coder: This way future changes will be done in only one place.]
985        """
986        if name==None:
987            name= self.model.name
988       
989        self.manager.draw_model(self.model, name, data=self.data,
990                                qmin=self.qmin_x, qmax=self.qmax_x,
991                                qstep= self.num_points,
992                                enable2D=self.enable2D)
993       
994    def select_param(self,event):
995        """
996       
997        """
998        pass
999    def select_all_param(self,event): 
1000        """
1001       
1002        """
1003        pass
1004    def select_all_param_helper(self):
1005        """
1006             Allows selecting or delecting button
1007        """
1008        self.param_toFit=[]
1009        if  self.parameters !=[]:
1010            if  self.cb1.GetValue()==True:
1011                for item in self.parameters:
1012                    item[0].SetValue(True)
1013                    list= [item[0],item[1],item[2],item[3]]
1014                    self.param_toFit.append(list )
1015                if len(self.fittable_param)>0:
1016                    for item in self.fittable_param:
1017                        item[0].SetValue(True)
1018                        list= [item[0],item[1],item[2],item[3]]
1019                        self.param_toFit.append(list )
1020            else:
1021                for item in self.parameters:
1022                    item[0].SetValue(False)
1023                for item in self.fittable_param:
1024                    item[0].SetValue(False)
1025                self.param_toFit=[]
1026               
1027               
1028       
Note: See TracBrowser for help on using the repository browser.