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

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

sansview: fixed problem with user-defined dispersion that returned I(q)=0 after switching back and forth between Gaussian and ArrayDispersion?. (Data array was going out of scope: refactor needed with C++/python layers)

  • Property mode set to 100644
File size: 40.5 KB
RevLine 
[1b07935d]1import sys
2import wx
3import wx.lib
4import numpy
5import copy
[81e4cf7]6import math
7from sans.models.dispersion_models import ArrayDispersion, GaussianDispersion
[26bf293]8
[1b07935d]9from sans.guicomm.events import StatusEvent   
[26bf293]10from sans.guiframe.utils import format_number
[1b07935d]11(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
12_BOX_WIDTH = 80
13
14
[26bf293]15
[fbc3e04]16
[f39511b]17class ModelPage(wx.ScrolledWindow):
[1b07935d]18    """
[fbc3e04]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.
[1b07935d]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"
[fbc3e04]29    name=""
30   
31    def __init__(self, parent,model,name, *args, **kwargs):
[f39511b]32        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
[1b07935d]33        """
34            Initialization of the Panel
35        """
[26bf293]36        # model on which the fit would be performed
37        self.model=model
[1fbb343]38       
[76dab10]39        ## Data member to store the dispersion object created
40        self._disp_obj_dict = {}
[fbc3e04]41
42        #list of dispersion paramaters
[bb1e07a]43        self.disp_list=[]
44        try:
45            self.disp_list=self.model.getDispParamList()
46        except:
47            pass 
[1b07935d]48        self.manager = None
49        self.parent  = parent
[26bf293]50        self.event_owner = None
51        # this panel does contain data .existing data allow a different drawing
52        #on set_model parameters
[fbc3e04]53        self.data=None
[1b07935d]54        #panel interface
55        self.vbox  = wx.BoxSizer(wx.VERTICAL)
[50c769e]56        self.sizer11 = wx.BoxSizer(wx.HORIZONTAL)
[51d47b5]57        #self.sizer10 = wx.GridBagSizer(5,5)
[26bf293]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)
[04edd0d]62        self.sizer5 = wx.GridBagSizer(5,5)
[26bf293]63        self.sizer4 = wx.GridBagSizer(5,5)
[fbc3e04]64       
[26bf293]65        #model selection
66        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
[00561739]67        self.vbox.Add(self.sizer4)
[50c769e]68        #model description
69        self.vbox.Add(self.sizer11)
[26bf293]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)
[fbc3e04]81        #close layer
82        #self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
83        #self.vbox.Add(self.sizer10)
84       
85     
[26bf293]86        #------------------ sizer 4  draw------------------------ 
[fbc3e04]87       
88       
[26bf293]89        # define combox box
90        self.modelbox = wx.ComboBox(self, -1)
91         # preview selected model name
[fbc3e04]92        self.prevmodel_name=name
[26bf293]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
[00561739]105        id = wx.NewId()
[26bf293]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")
[50c769e]109       
[26bf293]110        self.sizer4.Add(self.model_view,(iy,ix),(1,1),\
111                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[50c769e]112       
[ef8b580]113        self.model_view.Enable()
[26bf293]114        self.model_view.SetFocus()
[ef8b580]115       
[50c769e]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
[26bf293]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))
[fbc3e04]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())
[26bf293]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)
[d15c0202]129        ix += 1
[26bf293]130        self.sizer6.Add(self.enable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[d15c0202]131        ix += 1
[26bf293]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) 
[fbc3e04]136
137       
[26bf293]138        #---------sizer 9 draw----------------------------------------
[fbc3e04]139       
140         ## Q range
[26bf293]141        self.qmin_x= 0.001
142        self.qmax_x= 0.1
[d15c0202]143        self.num_points= 100
[24ea33c]144       
[00561739]145       
[26bf293]146        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
147        self.qmin.SetValue(format_number(self.qmin_x))
[e5af88b]148        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
[26bf293]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))
[e5af88b]154        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
[26bf293]155        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
156        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
157     
158
[d15c0202]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       
[dc317d1]165        ix = 0
[26bf293]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)
[1b07935d]178        ix = 0
[26bf293]179        iy += 1
[e5af88b]180        self.sizer9.Add(wx.StaticText(self, -1, 'Q range'),(iy, ix),(1,1),\
[26bf293]181                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[1b07935d]182        ix += 1
[26bf293]183        self.sizer9.Add(self.qmin,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[86c1832]184        ix += 1
[26bf293]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)
[fbc3e04]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       
[1b07935d]225        self.vbox.Layout()
226        self.vbox.Fit(self) 
227        self.SetSizer(self.vbox)
[f39511b]228        self.SetScrollbars(20,20,55,40)
[68dada4]229       
[fbc3e04]230        self.Centre()
231        self.Layout()
232        self.parent.GetSizer().Layout()
[bdb27e6]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       
[0b99881]248    def set_model_description(self, model):
[fbc3e04]249       
[50c769e]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     
[26bf293]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
[fbc3e04]297    def Set_DipersParam(self, event):
[07a93a1]298        """
[fbc3e04]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.
[07a93a1]303        """
[26bf293]304        if self.enable_disp.GetValue():
[07a93a1]305            # The user selected to use dispersion/averaging
[26bf293]306            if len(self.disp_list)==0:
[07a93a1]307                # This model contains no parameter to which we can apply dispersion/averaging
[26bf293]308                ix=0
309                iy=1
[6b44403]310                self.fittable_param=[]
311                self.fixed_param=[]
[26bf293]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:
[fbc3e04]321                # Show the default dispersion/averaging sub-panel
[888e62c]322                self.populate_disp_box()
323                self.set_panel_dispers(self.disp_list)
[e5af88b]324               
[26bf293]325        else:
[07a93a1]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()
[bdb27e6]331                self._set_dispersion(p, disp_model)
[07a93a1]332                   
333            # Redraw the model
334            self._draw_model()
[51d47b5]335               
[6b44403]336            self.fittable_param=[]       
337            self.fixed_param=[]
[26bf293]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
[ef8b580]355            import sans.models.dispersion_models 
356            self.polydisp= sans.models.dispersion_models.models
[26bf293]357            self.disp_box = wx.ComboBox(self, -1)
[ef8b580]358            self.disp_box.SetValue("GaussianModel")
359            for k,v in self.polydisp.iteritems():
[51d47b5]360                if str(v)=="MyModel":
[fbc3e04]361                    # Remove the option until the rest of the code is ready for it
[a38c284]362                    #self.disp_box.Insert("Select customized Model",id)
[047ed70]363                    pass 
[51d47b5]364                else:
[047ed70]365                    self.disp_box.Insert(str(v),id)         
[ef8b580]366                id+=1
[047ed70]367           
[26bf293]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)
[e5af88b]370            self.vbox.Layout()
371            self.SetScrollbars(20,20,55,40)
372            self.Layout()
373            self.parent.GetSizer().Layout() 
374           
375           
[26bf293]376    def set_range(self, qmin_x, qmax_x, npts):
[cfc68540]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
[26bf293]384        self.qmin_x = qmin_x
385        self.qmax_x = qmax_x
[cfc68540]386        self.num_points = npts
387       
388        # Set the controls
[26bf293]389        self.qmin.SetValue(format_number(self.qmin_x))
390        self.qmax.SetValue(format_number(self.qmax_x))
[cfc68540]391        self.npts.SetValue(format_number(self.num_points))
[26bf293]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        """
[fbc3e04]398       
[26bf293]399        flag = True
400        valueMin = self.qmin.GetValue()
401        valueMax = self.qmax.GetValue()
402        # Check for possible values entered
[fbc3e04]403        #print "fitpage: checkfitrange:",valueMin,valueMax
[26bf293]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   
[fbc3e04]421
422       
423    def onClose(self,event):
424        """ close the page associated with this panel"""
425        self.parent.onClose()
426       
427 
[dc317d1]428       
[f39511b]429    def onModel2D(self, event):
[86c1832]430        """
431         call manager to plot model in 2D
432        """
[24ea33c]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
[cfc68540]437            self._draw_model()
[e5af88b]438            self.model_view.Disable()
[24ea33c]439           
[86c1832]440   
[32d802f]441    def select_model(self, model, name):
[3dc83be]442        """
443            Select a new model
444            @param model: model object
445        """
[ef8b580]446        self.model = model
447        self.parent.model_page.name = name
448        self.parent.draw_model_name = name
[51d47b5]449       
[3dc83be]450        self.set_panel(model)
[32d802f]451        self._draw_model(name)
[3dc83be]452       
453        # Select the model from the combo box
454        items = self.modelbox.GetItems()
455        for i in range(len(items)):
[32d802f]456            if items[i]==name:
[3dc83be]457                self.modelbox.SetSelection(i)
[51d47b5]458                self.model_view.SetFocus()
[26bf293]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        """
[ef8b580]465        type =event.GetString()
466        self.set_panel_dispers( self.disp_list,type )
[fbc3e04]467               
[1b07935d]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        """
[26bf293]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()
[1b07935d]480        for item in self.model_list_box.itervalues():
[2dbb681]481            name = item.__name__
[86c1832]482            if hasattr(item, "name"):
483                name = item.name
[2dbb681]484            if name ==event.GetString():
[86c1832]485                model=item()
[b2c3225]486                self.model= model
[2dbb681]487                self.set_panel(model)
[86c1832]488                self.name= name
[51d47b5]489                self.model_view.SetFocus()
[ef8b580]490                self.parent.model_page.name=name
491                self.parent.draw_model_name=name
[51d47b5]492               
[32d802f]493                self._draw_model(name)
[d23544dc]494           
[1b07935d]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       
[2dbb681]514    def set_panel(self,model):
[1b07935d]515        """
516            Build the panel from the model content
517            @param model: the model selected in combo box for fitting purpose
518        """
[b491d6e]519       
[04edd0d]520        self.sizer5.Clear(True)
[1b07935d]521        self.parameters = []
522        self.param_toFit=[]
[26bf293]523        self.fixed_param=[]
[1b07935d]524        self.model = model
[50c769e]525       
526        self.set_model_description( self.model) 
527       
[1b07935d]528        keys = self.model.getParamList()
[26bf293]529        #list of dispersion paramaters
530        self.disp_list=self.model.getDispParamList()
531       
[1b07935d]532        keys.sort()
[26bf293]533        ik=0
534        im=1
[d171299]535       
[49b7efa]536        iy = 1
[26bf293]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),\
[1b07935d]547                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
548        ix +=1
549        self.text2_2 = wx.StaticText(self, -1, 'Values')
[26bf293]550        self.sizer5.Add(self.text2_2,(iy, ix),(1,1),\
[1b07935d]551                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
[26bf293]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() 
[f3113c9]557       
[fbc3e04]558       
[51d47b5]559        ix +=1
[1b07935d]560        self.text2_4 = wx.StaticText(self, -1, 'Units')
[26bf293]561        self.sizer5.Add(self.text2_4,(iy, ix),(1,1),\
[1b07935d]562                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
563        self.text2_4.Hide()
[26bf293]564        disp_list=self.model.getDispParamList()
[1b07935d]565        for item in keys:
[04edd0d]566            if not item in disp_list:
567                iy += 1
568                ix = 0
[26bf293]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               
[04edd0d]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)
[26bf293]583                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
584                self.sizer5.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
[04edd0d]585               
[26bf293]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()
[e9e914f]595               
[26bf293]596                ix +=1
[04edd0d]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)
[26bf293]602                self.sizer5.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
603           
[81e4cf7]604                self.parameters.append([cb,ctl1,text2,ctl2])
[04edd0d]605               
606        iy+=1
[26bf293]607        self.sizer5.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[04edd0d]608       
[1b07935d]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()
[51d47b5]616       
[1b07935d]617        self.vbox.Layout()
[68dada4]618        self.SetScrollbars(20,20,55,40)
[26bf293]619        self.Layout()
620        self.parent.GetSizer().Layout()
[51d47b5]621       
622       
623       
[ef8b580]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:
[51d47b5]634            if path==None:
635                wx.PostEvent(self.parent.parent, StatusEvent(status=\
636                            " Selected Distribution was not loaded: %s"%path))
637                return None, None
[ef8b580]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:
[fbc3e04]657            raise 
[51d47b5]658       
659         
660    def select_disp_angle(self, event): 
[81e4cf7]661        """
662            Event for when a user select a parameter to average over.
663            @param event: check box event
664        """
[fbc3e04]665       
666       
[81e4cf7]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
[aae8d23]702                    # Store the objects to make them persist outside the scope of this method
703                                #TODO: refactor model to clean this up?
704                    self._disp_obj_dict[p+'values']  = values
705                    self._disp_obj_dict[p+'weights'] = weights
[81e4cf7]706                    disp_model = ArrayDispersion()
707                    disp_model.set_weights(values, weights)
[bdb27e6]708                    self._set_dispersion(p, disp_model)
[81e4cf7]709                   
710                    # Redraw the model
711                    self._draw_model()
712                         
713                else:
714                    # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
715                    disp_model = GaussianDispersion()
[bdb27e6]716                    self._set_dispersion(p, disp_model)
[81e4cf7]717                   
718                    # Redraw the model
719                    self._draw_model()
720        return
[fbc3e04]721
722                     
723                     
[51d47b5]724                     
725    def set_panel_dispers(self, disp_list, type="GaussianModel" ):
[ed2ea6a]726        """
727        """
[26bf293]728       
[e5af88b]729        self.fittable_param=[]
730        self.fixed_param=[]
[51d47b5]731       
[26bf293]732        ix=0
733        iy=1
[ef8b580]734                ### this will become a separate method
[bdb27e6]735        #TODO: don't hard code text values to be shown on the interface
[51d47b5]736        if type== "Select customized Model":
737            ix=0
738            iy=1
739            self.sizer8.Clear(True)       
740            disp1 = wx.StaticText(self, -1, 'Array Dispersion')
741            self.sizer8.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
[ef8b580]742           
[81e4cf7]743            # Look for model parameters to which we can apply an ArrayDispersion model
744            # Add a check box for each parameter.
745            self.disp_cb_dict = {}
746            for p in self.model.dispersion.keys():
747                ix+=1 
748                self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
749               
750                wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
751                self.sizer8.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
[51d47b5]752           
753            ix =0
754            iy +=1 
755            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
756            self.vbox.Layout()
757            self.SetScrollbars(20,20,55,40)
758            self.Layout()
759            self.parent.GetSizer().Layout() 
[ef8b580]760           
[51d47b5]761        if type== "GaussianModel" :
762
[e5af88b]763            self.sizer8.Clear(True)
[26bf293]764            disp = wx.StaticText(self, -1, 'Dispersion')
765            self.sizer8.Add(disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
766            ix += 1 
767            values = wx.StaticText(self, -1, 'Values')
768            self.sizer8.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
769            ix +=2
770            self.text2_3 = wx.StaticText(self, -1, 'Errors')
771            self.sizer8.Add(self.text2_3,(iy, ix),(1,1),\
772                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
773            self.text2_3.Hide() 
774           
775            ix += 1 
776            npts = wx.StaticText(self, -1, 'Npts')
777            self.sizer8.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
778            ix += 1 
779            nsigmas = wx.StaticText(self, -1, 'Nsigmas')
780            self.sizer8.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
781           
782            disp_list.sort()
[b491d6e]783            #print disp_list,self.model.dispersion
[26bf293]784            for item in self.model.dispersion.keys():
785                name1=item+".width"
786                name2=item+".npts"
787                name3=item+".nsigmas"
788                iy += 1
[bdb27e6]789               
790                # Make sure the dispersion model is Gaussian
791                if not self.model.dispersion[item]['type'] == 'gaussian': 
792                    disp_model = GaussianDispersion()
793                    self._set_dispersion(item, disp_model)
794               
795                # Create the interface
[26bf293]796                for p in self.model.dispersion[item].keys():
797                    #print "name 1 2 3", name1, name2, name3
798                    if p=="width":
799                        ix = 0
800                        cb = wx.CheckBox(self, -1, name1, (10, 10))
801                        if self.data !=None:
802                            cb.SetValue(False)
803                            wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
804                        else:
805                            cb.Disable()
806                        self.sizer8.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
807                        ix = 1
808                        value= self.model.getParam(name1)
809                        ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
810                        ctl1.SetValue(str (format_number(value)))
811                        ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
812                        ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
813                        self.sizer8.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
814                       
815                        ix = 2
816                        text2=wx.StaticText(self, -1, '+/-')
817                        self.sizer8.Add(text2,(iy, ix),(1,1),\
818                                        wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
819                        text2.Hide() 
820                        ix = 3
821                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
822                        self.sizer8.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
823                        ctl2.Hide()
[94999eb]824                        self.fittable_param.append([cb,ctl1,text2,ctl2])
[26bf293]825                       
826                       
827                    elif p=="npts":
828                            ix =4 
829                            value= self.model.getParam(name2)
830                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
831                            Tctl.SetValue(str (format_number(value)))
832                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
833                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
834                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
835                            self.fixed_param.append([name2, Tctl])
836                    elif p=="nsigmas":
837                            ix =5 
838                            value= self.model.getParam(name3)
839                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
840                            Tctl.SetValue(str (format_number(value)))
841                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
842                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
843                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
844                            self.fixed_param.append([name3, Tctl])
[ef8b580]845                wx.PostEvent(self.parent.parent, StatusEvent(status=\
846                            " Selected Distribution: Gaussian"))   
[e5af88b]847            ix =0
848            iy +=1 
849            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)       
850            self.vbox.Layout()
851            self.SetScrollbars(20,20,55,40)
852            self.Layout()
853            self.parent.GetSizer().Layout() 
[ef8b580]854         
[51d47b5]855    def checkFitValues(self,val_min, val_max):
856        """
857            Check the validity of input values
858        """
859        flag = True
860        min_value = val_min.GetValue()
861        max_value = val_max.GetValue()
862        # Check for possible values entered
863        if min_value.lstrip().rstrip() =="-inf":
864            min_value= -numpy.inf
865        if max_value.lstrip().rstrip() =="+inf":
866            max_value= numpy.inf
867        if  min_value==-numpy.inf and max_value== numpy.inf:
868            val_min.SetBackgroundColour(wx.WHITE)
869            val_min.Refresh()
870            val_max.SetBackgroundColour(wx.WHITE)
871            val_max.Refresh()
872            return flag
873        elif max_value== numpy.inf:
874            try:
875                float(min_value)
876                val_min.SetBackgroundColour(wx.WHITE)
877                val_min.Refresh()
878            except:
879                flag = False
880                val_min.SetBackgroundColour("pink")
881                val_min.Refresh()
882            return flag
883        elif min_value==-numpy.inf:
884            try:
885                float(max_value)
886                val_max.SetBackgroundColour(wx.WHITE)
887                val_max.Refresh()
888            except:
889                flag = False
890                val_max.SetBackgroundColour("pink")
891                val_max.Refresh()
892            return flag
893        else:   
894            if (float(min_value)< float(max_value)):
895                val_min.SetBackgroundColour(wx.WHITE)
896                val_min.Refresh()
897            else:
898                flag = False
899                val_min.SetBackgroundColour("pink")
900                val_min.Refresh()
901            return flag   
[26bf293]902           
[1b07935d]903       
904    def _onparamEnter(self,event):
905        """
906            when enter value on panel redraw model according to changed
907        """
908        self.set_model_parameter()
909       
910    def set_model_parameter(self):
[ed2ea6a]911        """
912        """
[1b07935d]913        if len(self.parameters) !=0 and self.model !=None:
[24ea33c]914            # Flag to register when a parameter has changed.
915            is_modified = False
[e5af88b]916            for item in self.fittable_param:
917                try:
918                     name=str(item[0].GetLabelText())
919                     value= float(item[1].GetValue())
920                     # If the value of the parameter has changed,
921                     # update the model and set the is_modified flag
922                     if value != self.model.getParam(name):
923                         self.model.setParam(name,value)
924                         is_modified = True
925                         
926                except:
[fbc3e04]927                    #raise
[e5af88b]928                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
929                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
[ed2ea6a]930                    return 
931               
[e5af88b]932               
[26bf293]933            for item in self.fixed_param:
934                try:
935                     name=str(item[0])
936                     value= float(item[1].GetValue())
937                     # If the value of the parameter has changed,
938                     # update the model and set the is_modified flag
939                     if value != self.model.getParam(name):
940                         self.model.setParam(name,value)
941                         is_modified = True
942                         
943                except:
[fbc3e04]944                    raise
[e5af88b]945                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
[fbc3e04]946                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
[26bf293]947               
[db709e4]948            for item in self.parameters:
[a5aaec9]949                try:
950                     name=str(item[0].GetLabelText())
951                     value= float(item[1].GetValue())
952                     # If the value of the parameter has changed,
953                     # update the model and set the is_modified flag
954                     if value != self.model.getParam(name):
955                         self.model.setParam(name,value)
956                         is_modified = True
[ed2ea6a]957                   
[db709e4]958                except:
[ed2ea6a]959                    #raise
960                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
[fbc3e04]961                           "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
[ed2ea6a]962                    return
963               
964               
[db709e4]965            # Here we should check whether the boundaries have been modified.
966            # If qmin and qmax have been modified, update qmin and qmax and
967            # set the is_modified flag to True
[26bf293]968            if float(self.qmin.GetValue()) != self.qmin_x:
969                self.qmin_x = float(self.qmin.GetValue())
[a5aaec9]970                is_modified = True
[26bf293]971            if float(self.qmax.GetValue()) != self.qmax_x:
972                self.qmax_x = float(self.qmax.GetValue())
[a5aaec9]973                is_modified = True
[e9b4cc4]974           
[ea20505]975            if float(self.npts.GetValue()) !=  self.num_points:
976                self.num_points = float(self.npts.GetValue())
977                is_modified = True
[e9b4cc4]978         
[a5aaec9]979            if is_modified:
[cfc68540]980                self._draw_model()           
[2e10b70]981           
[32d802f]982    def _draw_model(self, name=None):
[cfc68540]983        """
984            Method to draw or refresh a plotted model.
985            The method will use the data member from the model page
986            to build a call to the fitting perspective manager.
[2e10b70]987           
[cfc68540]988            [Note to coder: This way future changes will be done in only one place.]
989        """
[32d802f]990        if name==None:
991            name= self.model.name
[26bf293]992       
993        self.manager.draw_model(self.model, name, data=self.data,
994                                qmin=self.qmin_x, qmax=self.qmax_x,
[cfc68540]995                                qstep= self.num_points,
996                                enable2D=self.enable2D)
[ef8b580]997       
[26bf293]998    def select_param(self,event):
[ed2ea6a]999        """
[fbc3e04]1000       
[ed2ea6a]1001        """
[26bf293]1002        pass
1003    def select_all_param(self,event): 
[ed2ea6a]1004        """
[fbc3e04]1005       
[ed2ea6a]1006        """
[26bf293]1007        pass
[94999eb]1008    def select_all_param_helper(self):
1009        """
[fbc3e04]1010             Allows selecting or delecting button
[94999eb]1011        """
1012        self.param_toFit=[]
1013        if  self.parameters !=[]:
1014            if  self.cb1.GetValue()==True:
1015                for item in self.parameters:
1016                    item[0].SetValue(True)
[e9e914f]1017                    list= [item[0],item[1],item[2],item[3]]
[94999eb]1018                    self.param_toFit.append(list )
1019                if len(self.fittable_param)>0:
1020                    for item in self.fittable_param:
1021                        item[0].SetValue(True)
1022                        list= [item[0],item[1],item[2],item[3]]
1023                        self.param_toFit.append(list )
1024            else:
1025                for item in self.parameters:
1026                    item[0].SetValue(False)
1027                for item in self.fittable_param:
1028                    item[0].SetValue(False)
1029                self.param_toFit=[]
[ef8b580]1030               
1031               
[26bf293]1032       
Note: See TracBrowser for help on using the repository browser.