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

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

Fixed problem with the selection of the number of points for 2D plot. Also fixed the related problem of the 1D plot being replotted with the wrong number of points after the 2D plot is first displayed.

  • Property mode set to 100644
File size: 16.1 KB
Line 
1import sys
2import wx
3import wx.lib
4import numpy
5import copy
6
7from sans.guicomm.events import StatusEvent   
8(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
9_BOX_WIDTH = 80
10
11def format_number(value, high=False):
12    """
13        Return a float in a standardized, human-readable formatted string
14    """
15    try: 
16        value = float(value)
17    except:
18        print "returning 0"
19        return "0"
20   
21    if high:
22        return "%-6.4g" % value
23    else:
24        return "%-5.3g" % value
25
26   
27class ModelPage(wx.ScrolledWindow):
28    """
29        FitPanel class contains fields allowing to display results when
30        fitting  a model and one data
31        @note: For Fit to be performed the user should check at least one parameter
32        on fit Panel window.
33 
34    """
35    ## Internal name for the AUI manager
36    window_name = "Fit page"
37    ## Title to appear on top of the window
38    window_caption = "Fit Page"
39   
40   
41    def __init__(self, parent,model,name, *args, **kwargs):
42        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
43        """
44            Initialization of the Panel
45        """
46        #self.scroll = wx.ScrolledWindow(self)
47        self.manager = None
48        self.parent  = parent
49        self.event_owner=None
50        #panel interface
51        self.vbox  = wx.BoxSizer(wx.VERTICAL)
52        self.sizer3 = wx.GridBagSizer(5,5)
53        self.sizer1 = wx.GridBagSizer(5,5)
54        self.sizer2 = wx.GridBagSizer(5,5)
55        self.sizer4 = wx.GridBagSizer(5,5)
56        self.sizer5 = wx.GridBagSizer(5,5)
57        self.static_line_1 = wx.StaticLine(self, -1)
58        self.modelbox = wx.ComboBox(self, -1)
59        id = wx.NewId()
60        self.vbox.Add(self.sizer3)
61        self.vbox.Add(self.sizer1)
62        self.vbox.Add(self.sizer2)
63        self.vbox.Add(self.static_line_1, 0, wx.EXPAND, 0)
64        self.vbox.Add(self.sizer5)
65        self.vbox.Add(self.sizer4)
66       
67        id = wx.NewId()
68        self.btClose =wx.Button(self,id,'Close')
69        self.btClose.Bind(wx.EVT_BUTTON, self.onClose,id=id)
70        self.btClose.SetToolTipString("Close page.")
71        ix = 1
72        iy = 1 
73        self.sizer4.Add(wx.StaticText(self, -1, 'Min'),(iy, ix),(1,1),\
74                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
75        ix += 1
76        self.sizer4.Add(wx.StaticText(self, -1, 'Max'),(iy, ix),(1,1),\
77                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
78        ix += 1
79        self.sizer4.Add(wx.StaticText(self, -1, 'Npts'),(iy, ix),(1,1),\
80                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
81        ix = 0
82        iy += 1
83        self.sizer4.Add(wx.StaticText(self, -1, 'x range'),(iy, ix),(1,1),\
84                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
85        ## Q range
86        self.qmin= 0.001
87        self.qmax= 0.1
88        self.num_points= 100
89       
90        ix += 1
91        self.xmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
92        self.xmin.SetValue(format_number(self.qmin))
93        self.xmin.SetToolTipString("Minimun value of x in linear scale.")
94        self.xmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
95        self.xmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
96        self.sizer4.Add(self.xmin,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
97       
98       
99        ix += 1
100        self.xmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
101        self.xmax.SetValue(format_number(self.qmax))
102        self.xmax.SetToolTipString("Maximum value of x in linear scale.")
103        self.xmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
104        self.xmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
105        self.sizer4.Add(self.xmax,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
106        ix += 1
107        self.npts    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
108        self.npts.SetValue(format_number(self.num_points))
109        self.npts.SetToolTipString("Number of point to plot.")
110        self.npts.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
111        self.npts.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
112       
113        self.sizer4.Add(self.npts,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
114        ix = 0
115        iy += 1
116        self.sizer4.Add((20,20),(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
117        ix +=3
118        self.sizer4.Add( self.btClose,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
119        ix = 0
120        iy = 1
121        self.sizer3.Add(wx.StaticText(self,-1,'Model'),(iy,ix),(1,1)\
122                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
123        ix += 1
124        self.sizer3.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
125        #ix = 0
126        #iy += 1
127        ix += 1
128        id = wx.NewId()
129        self.model_view =wx.Button(self,id,'View 2D')
130        self.model_view.Bind(wx.EVT_BUTTON, self.onModel2D,id=id)
131        self.model_view.SetToolTipString("View model in 2D")
132        self.sizer3.Add(self.model_view,(iy,ix),(1,1),\
133                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
134        # contains link between  model ,all its parameters, and panel organization
135        self.parameters=[]
136        #contains link between a model and selected parameters to fit
137        self.param_toFit=[]
138        # model on which the fit would be performed
139        self.model=model
140        try:
141            #print"init modelpage",model.name
142            self.set_panel(model)
143        except:
144            raise
145        # preview selected model name
146        self.prevmodel_name=name
147        #print "model view prev_model",name
148        self.modelbox.SetValue(self.prevmodel_name)
149        # flag to check if the user has selected a new model in the combox box
150        self.model_hasChanged=False
151        #dictionary of model name and model class
152        self.model_list_box={}
153       
154        #enable model 2D draw
155        self.enable2D= False
156        # Data1D to make a deep comparison between 2 Data1D for checking data
157        #change
158        self.vbox.Layout()
159        self.vbox.Fit(self) 
160       
161        self.SetSizer(self.vbox)
162        self.SetScrollbars(20,20,55,40)
163        self.Centre()
164       
165       
166    def onClose(self,event):
167        """ close the page associated with this panel"""
168        self.GrandParent.onClose()
169       
170    def set_owner(self,owner):
171        """
172            set owner of fitpage
173            @param owner: the class responsible of plotting
174        """
175        self.event_owner=owner   
176   
177 
178    def set_manager(self, manager):
179        """
180             set panel manager
181             @param manager: instance of plugin fitting
182        """
183        self.manager = manager
184       
185    def onModel2D(self, event):
186        """
187         call manager to plot model in 2D
188        """
189        # If the 2D display is not currently enabled, plot the model in 2D
190        # and set the enable2D flag.
191        if self.enable2D==False:
192            self.enable2D=True
193            self.manager.draw_model(model=self.model,
194                                    name=self.model.name,
195                                    description=None,
196                                    enable2D=self.enable2D,
197                                    qmin=float(self.qmin),
198                                    qmax=float(self.qmax),
199                                    qstep= self.num_points)
200       
201           
202    def populate_box(self, dict):
203        """
204            Populate each combox box of each page
205            @param page: the page to populate
206        """
207        id=0
208        self.model_list_box=dict
209        list_name=[]
210        for item in  self.model_list_box.itervalues():
211            name = item.__name__
212            if hasattr(item, "name"):
213                name = item.name
214            list_name.append(name)
215        list_name.sort()   
216        for name in list_name:
217            self.modelbox.Insert(name,int(id))
218            id+=1
219        wx.EVT_COMBOBOX(self.modelbox,-1, self._on_select_model) 
220        return 0
221   
222 
223   
224    def _on_select_model(self,event):
225        """
226            react when a model is selected from page's combo box
227            post an event to its owner to draw an appropriate theory
228        """
229        self.model_view.SetFocus()
230        for item in self.model_list_box.itervalues():
231            name = item.__name__
232            if hasattr(item, "name"):
233                name = item.name
234            if name ==event.GetString():
235                model=item()
236                #print "fitpage: _on_select_model model name",name ,event.GetString()
237                self.model= model
238                self.set_panel(model)
239                print "name in model page", name,event.GetString()
240                self.name= name
241                self.manager.draw_model(model, name)
242               
243           
244           
245    def get_model_box(self): 
246        """ return reference to combox box self.model"""
247        return self.modelbox
248
249   
250    def get_param_list(self):
251        """
252            @return self.param_toFit: list containing  references to TextCtrl
253            checked.Theses TextCtrl will allow reference to parameters to fit.
254            @raise: if return an empty list of parameter fit will nnote work
255            properly so raise ValueError,"missing parameter to fit"
256        """
257        if self.param_toFit !=[]:
258            return self.param_toFit
259        else:
260            raise ValueError,"missing parameter to fit"
261       
262       
263    def set_panel(self,model):
264        """
265            Build the panel from the model content
266            @param model: the model selected in combo box for fitting purpose
267        """
268       
269        self.sizer2.Clear(True)
270        self.sizer1.Clear(True)
271        self.sizer5.Clear(True)
272        self.parameters = []
273        self.param_toFit=[]
274        self.model = model
275        keys = self.model.getParamList()
276        keys.sort()
277        description=None
278        if hasattr(self.model,'description'):
279            description =model.description
280        disp_list=self.model.getDispParamList()
281        ip=0
282        iq=1
283        if len(disp_list)>0:
284            disp = wx.StaticText(self, -1, 'Dispersion')
285            self.sizer5.Add(disp,( iq, ip),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
286            ip += 1 
287            values = wx.StaticText(self, -1, 'Values')
288            self.sizer5.Add(values,( iq, ip),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
289           
290        disp_list.sort()
291        #print "went here",self.model.name,model.description
292        iy = 1
293        ix = 0
294        self.cb0 = wx.StaticText(self, -1,'Model Description:')
295        self.sizer1.Add(self.cb0,(iy, ix),(1,1),\
296                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
297        iy += 1
298       
299        self.cb01 = wx.StaticText(self, -1,str(description),style=wx.ALIGN_LEFT)
300        self.cb01.Wrap(400) 
301        #self.cb01 = wx.StaticText(self, -1,str(description),(45, 25),style=wx.ALIGN_LEFT)
302       
303        self.sizer1.Add(self.cb01,(iy, ix),(1,1),\
304                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
305        ix = 0
306        iy = 1
307        self.cb1 = wx.StaticText(self, -1,'Parameters')
308        self.sizer2.Add(self.cb1,(iy, ix),(1,1),\
309                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
310        ix +=1
311        self.text2_2 = wx.StaticText(self, -1, 'Values')
312        self.sizer2.Add(self.text2_2,(iy, ix),(1,1),\
313                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
314        ix +=1
315        self.text2_4 = wx.StaticText(self, -1, 'Units')
316        self.sizer2.Add(self.text2_4,(iy, ix),(1,1),\
317                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
318        self.text2_4.Hide()
319        for item in keys:
320            if not item in disp_list:
321                iy += 1
322                ix = 0
323                cb=wx.StaticText(self, -1, item)
324                self.sizer2.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
325                ix += 1
326                value= self.model.getParam(item)
327                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
328                ctl1.SetValue(str (format_number(value)))
329                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
330                ctl1.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
331                self.sizer2.Add(ctl1, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
332                ix +=1
333               
334                # Units
335                try:
336                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
337                except:
338                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
339                self.sizer2.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
340            else:
341                ip = 0
342                iq += 1
343                cb = wx.CheckBox(self, -1, item, (10, 10))
344                cb.SetValue(False)
345                self.sizer5.Add( cb,( iq, ip),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
346                wx.EVT_CHECKBOX(self, cb.GetId(), self._on_select_model)
347               
348                ip += 1
349                value= self.model.getParam(item)
350                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
351                ctl1.SetValue(str (format_number(value)))
352                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
353                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
354                self.sizer5.Add(ctl1, (iq,ip),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
355            #save data
356            self.parameters.append([cb,ctl1])
357        iy+=1
358        self.sizer2.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
359       
360        #Display units text on panel
361        for item in keys:   
362            if self.model.details[item][0]!='':
363                self.text2_4.Show()
364                break
365            else:
366                self.text2_4.Hide()
367        self.vbox.Layout()
368        self.GrandParent.GetSizer().Layout()
369       
370       
371    def _onparamEnter(self,event):
372        """
373            when enter value on panel redraw model according to changed
374        """
375        self.set_model_parameter()
376       
377    def set_model_parameter(self):
378        if len(self.parameters) !=0 and self.model !=None:
379            # Flag to register when a parameter has changed.
380            is_modified = False
381            for item in self.parameters:
382                try:
383                     name=str(item[0].GetLabelText())
384                     value= float(item[1].GetValue())
385                     # If the value of the parameter has changed,
386                     # update the model and set the is_modified flag
387                     if value != self.model.getParam(name):
388                         self.model.setParam(name,value)
389                         is_modified = True
390                except:
391                     wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
392                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
393           
394            # Here we should check whether the boundaries have been modified.
395            # If qmin and qmax have been modified, update qmin and qmax and
396            # set the is_modified flag to True
397            if float(self.xmin.GetValue()) != self.qmin:
398                self.qmin = float(self.xmin.GetValue())
399                is_modified = True
400            if float(self.xmax.GetValue()) != self.qmax:
401                self.qmax = float(self.xmax.GetValue())
402                is_modified = True
403           
404            if float(self.npts.GetValue()) !=  self.num_points:
405                self.num_points = float(self.npts.GetValue())
406                is_modified = True
407         
408            if is_modified:
409                self.manager.draw_model(self.model, self.model.name, 
410                                        qmin=self.qmin, qmax=self.qmax,
411                                        qstep= self.num_points,
412                                        enable2D=self.enable2D)
413           
414           
415           
416           
417             
Note: See TracBrowser for help on using the repository browser.