source: sasview/theoryview/perspectives/theory/model_panel.py @ e4957fb

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 e4957fb was 243a8d4, checked in by Jae Cho <jhjcho@…>, 14 years ago

fixed a bug in polydisp tips

  • Property mode set to 100644
File size: 33.4 KB
Line 
1import os
2import wx
3import wx.lib.newevent
4import numpy
5import copy
6import math
7from sans.guiframe.panel_base import PanelBase
8from sans.models.dispersion_models import ArrayDispersion
9from sans.models.dispersion_models import GaussianDispersion
10from sans.guiframe.events import StatusEvent   
11from sans.guiframe.utils import format_number
12import basepage
13from basepage import BasicPage
14from basepage import PageInfoEvent
15(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
16
17_BOX_WIDTH = 76
18
19
20class ModelPanel(BasicPage, PanelBase):
21    """
22    FitPanel class contains fields allowing to display results when
23    fitting  a model and one data
24   
25    :note: For Fit to be performed the user should check at least
26        one parameter on fit Panel window.
27    """
28    ## Flag to tell the AUI manager to put this panel in the center pane
29    CENTER_PANE = True
30    ## Internal name for the AUI manager
31    window_name = "Theory model"
32    ## Title to appear on top of the window
33    window_caption = "Theory Model"
34   
35    def __init__(self, parent, page_info, model_list_box):
36        BasicPage.__init__(self, parent, page_info, model_list_box)
37        PanelBase.__init__(self, parent)
38        """
39        Initialization of the Panel
40        """
41        self._fill_model_sizer( self.sizer1) 
42        self._fill_range_sizer()
43        self.engine_type = None 
44        description = ""
45        if self.model != None:
46            description = self.model.description
47            self.select_model(self.model)
48            self.set_model_description(description, self.sizer2)
49           
50    def _on_display_description(self, event):
51        """
52        Show or Hide description
53       
54        :param event: wx.EVT_RADIOBUTTON
55       
56        """
57        self._on_display_description_helper()
58        self.SetupScrolling()
59        self.Refresh()
60
61    def _on_display_description_helper(self):
62        """
63        Show or Hide description
64       
65        :param event: wx.EVT_RADIOBUTTON
66       
67        """
68        ## Show description
69        if self.description_hide.GetValue():
70            self.sizer_description.Clear(True)
71        else:
72            description="Model contains no description"
73            if self.model != None:
74                description = self.model.description
75            if description.lstrip().rstrip() == "": 
76                description="Model contains no description"
77            self.description = wx.StaticText(self, -1, str(description))
78            self.sizer_description.Add(self.description, 1, 
79                                       wx.EXPAND|wx.ALL, 10)
80        self.Layout()
81   
82    def _fill_range_sizer(self):
83        """
84        Fill the sizer containing the plotting range
85        add  access to npts
86       
87        """
88        ##The following 3 lines are for Mac. Let JHC know before modifying..
89        title = "Plotted Q Range"
90        box_description = wx.StaticBox(self, -1, str(title))
91        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
92
93        sizer_npts= wx.GridSizer(1, 1, 5, 5)   
94        self.npts    = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20), 
95                                          style=wx.TE_PROCESS_ENTER)
96        self.npts.SetValue(format_number(self.num_points))
97        self.npts.SetToolTipString("Number of point to plot.")
98        sizer_npts.Add(wx.StaticText(self, -1, 'Npts'), 1, 
99                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 13)       
100        sizer_npts.Add(self.npts, 1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 10) 
101        self._set_range_sizer(title=title, box_sizer=boxsizer1, 
102                              object=sizer_npts)
103   
104    def _on_select_model(self, event): 
105        """
106        call back for model selection
107       
108        """   
109        self._on_select_model_helper() 
110        #Reset dispersity that was not done in _on_select_model_helper()
111        self._reset_dispersity()
112        self.select_model(self.model)
113       
114    def _fill_model_sizer(self, sizer):
115        """
116        fill sizer containing model info
117       
118        """
119        ##The following 3 lines are for Mac. Let JHC know before modifying..
120        title = "Model"
121        box_description = wx.StaticBox(self, -1, str(title))
122        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
123        id = wx.NewId()
124        self.model_view = wx.Button(self, id,'View 2D', size=(80, 23))
125        self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D, id=id)
126        self.model_view.SetToolTipString("View model in 2D")
127        ## class base method  to add view 2d button   
128        self._set_model_sizer(sizer=sizer, box_sizer=boxsizer1, 
129                              title=title, object=self.model_view)   
130   
131    #def _set_sizer_gaussian(self):
132    def _set_sizer_dispersion(self, dispersity):
133        """
134        draw sizer with gaussian, log or schulz dispersity parameters
135       
136        """
137        self.fittable_param = []
138        self.fixed_param = []
139        self.orientation_params_disp = []
140        #self.temp=[]
141        self.sizer4_4.Clear(True)
142        if self.model == None:
143            ##no model is selected
144            return
145        if not self.enable_disp.GetValue():
146            ## the user didn't select dispersity display
147            return 
148        self._reset_dispersity()
149        # Create the dispersion objects
150        for item in self.model.dispersion.keys():
151            #disp_model =  GaussianDispersion()
152            disp_model = dispersity()
153            self._disp_obj_dict[item] = disp_model
154            self.model.set_dispersion(item, disp_model)
155            self.state._disp_obj_dict[item] = disp_model
156        ix = 0
157        iy = 1
158        disp = wx.StaticText(self, -1, ' ')
159        self.sizer4_4.Add(disp,(iy, ix), (1, 1), 
160                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
161        ix += 1 
162        values = wx.StaticText(self, -1, 'PD[ratio] ')
163        polytext = "Polydispersity (= STD/mean); "
164        polytext +=  "the standard deviation over the mean value."
165        values.SetToolTipString(polytext)
166       
167        self.sizer4_4.Add(values, (iy, ix), (1, 1), 
168                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
169        ix += 1 
170        npts = wx.StaticText(self, -1, 'Npts')
171        hint_msg = "Number of sampling points for the numerical\n"
172        hint_msg += "integration over the distribution function."
173        npts.SetToolTipString(hint_msg)
174        self.sizer4_4.Add(npts, (iy, ix), (1, 1),
175                          wx.EXPAND|wx.ADJUST_MINSIZE, 0)
176        ix += 1 
177        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
178        hint_msg = "Number of sigmas between which the range\n"
179        hint_msg += "of the distribution function will be used for "
180        hint_msg += "weighting.\n The value '3' covers 99.5% for Gaussian "
181        hint_msg += "  distribution \n function. "
182        hint_msg += "Note: Not recommended to change this value."
183        nsigmas.SetToolTipString(hint_msg)
184        self.sizer4_4.Add(nsigmas, (iy, ix), 
185                          (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
186        for item in self.model.dispersion.keys():
187            if not item in self.model.orientation_params:
188                self.disp_cb_dict[item] = None
189                name0 = "Distribution of " + item
190                name1 = item + ".width"
191                name2=item+".npts"
192                name3=item+".nsigmas"
193                iy += 1
194                for p in self.model.dispersion[item].keys():
195                    if p == "width":
196                        ix = 0
197                        name = wx.StaticText(self, -1,  name0)
198                        self.sizer4_4.Add( name,( iy, ix),(1,1), 
199                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
200                        ix = 1
201                        value= self.model.getParam(name1)
202                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
203                                            style=wx.TE_PROCESS_ENTER)
204                        ctl1.SetLabel('PD[ratio]')
205                        poly_text = "Polydispersity (STD/mean) of %s\n" % item
206                        poly_text += "STD: the standard deviation"
207                        poly_text += " from the mean value."
208                        ctl1.SetToolTipString(poly_text)
209                        ctl1.SetValue(str (format_number(value)))
210                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
211                        self.fittable_param.append([None,name1,ctl1,None,
212                                                    None, None, None,None])
213                    elif p=="npts":
214                            ix =2
215                            value= self.model.getParam(name2)
216                            Tctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
217                                                style=wx.TE_PROCESS_ENTER)
218                           
219                            Tctl1.SetValue(str (format_number(value)))
220                            self.sizer4_4.Add(Tctl1, (iy,ix),(1,1),
221                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
222                            self.fixed_param.append([None,name2, Tctl1,None,None,
223                                                      None, None,None])
224                    elif p=="nsigmas":
225                            ix =3 
226                            value= self.model.getParam(name3)
227                            Tctl2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
228                                                style=wx.TE_PROCESS_ENTER)
229                           
230                            Tctl2.SetValue(str (format_number(value)))
231                            self.sizer4_4.Add(Tctl2, (iy,ix),(1,1),
232                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
233                            ix +=1
234                            self.sizer4_4.Add((20,20), (iy,ix),(1,1),
235                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
236                            self.fixed_param.append([None,name3, Tctl2,
237                                                     None,None, None, None,None])
238        first_orient  = True
239        for item in self.model.dispersion.keys():
240            if item in self.model.orientation_params:
241                self.disp_cb_dict[item]= None
242                name0="Distribution of " + item
243                name1=item+".width"
244                name2=item+".npts"
245                name3=item+".nsigmas"
246                iy += 1
247                for p in self.model.dispersion[item].keys():
248                    if p=="width":
249                        ix = 0
250                        name = wx.StaticText(self, -1,  name0)
251                        self.sizer4_4.Add( name,( iy, ix),(1,1), 
252                                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
253                        if not self.enable2D:
254                            name.Hide()
255                        else:
256                            name.Show(True)
257                        ix = 1
258                        value= self.model.getParam(name1)
259                        ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
260                                            style=wx.TE_PROCESS_ENTER)
261                        poly_tip = "Absolute Sigma for %s." % item
262                        ctl1.SetToolTipString(poly_tip)
263                        ctl1.SetValue(str (format_number(value)))
264                        if not self.enable2D:
265                            ctl1.Hide()
266                            ctl1.Disable()
267                        else:
268                            # in the case of 2D and angle parameter
269                            if first_orient:
270                                values.SetLabel('PD[ratio], Sig[deg]')
271                                poly_text = "PD(polydispersity for lengths):\n"
272                                poly_text +=  "It should be a value between"
273                                poly_text +=  "0 and 1\n"
274                                poly_text += "Sigma for angles: \n"
275                                poly_text += "It is the STD (ratio*mean)"
276                                poly_text += " of the distribution.\n " 
277                           
278                                values.SetToolTipString(poly_text)
279                                first_orient = False 
280                            ctl1.Show(True)
281                            ctl1.Enable()
282                        self.sizer4_4.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
283                        self.fittable_param.append([None,name1,ctl1,None,
284                                                    None, None, None,None])
285                        self.orientation_params_disp.append([None,name1,ctl1,None,
286                                                    None, None, None,None])
287                    elif p=="npts":
288                            ix =2
289                            value= self.model.getParam(name2)
290                            Tctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
291                                                style=wx.TE_PROCESS_ENTER)
292
293                            Tctl1.SetValue(str (format_number(value)))
294                            if not self.enable2D:
295                                Tctl1.Hide()
296                                Tctl1.Disable()
297                            else:
298                                Tctl1.Show(True)
299                                Tctl1.Enable()
300                            self.sizer4_4.Add(Tctl1, (iy,ix),(1,1),
301                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
302                            self.fixed_param.append([None,name2, Tctl1,None,None,
303                                                      None, None,None])
304                            self.orientation_params_disp.append([None,name2, Tctl1,None,None,
305                                                      None, None,None])
306                    elif p=="nsigmas":
307                            ix =3 
308                            value= self.model.getParam(name3)
309                            Tctl2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
310                                                style=wx.TE_PROCESS_ENTER)
311                           
312                            Tctl2.SetValue(str (format_number(value)))
313                            if not self.enable2D:
314                                Tctl2.Hide()
315                                Tctl2.Disable()
316                            else:
317                                Tctl2.Show(True)
318                                Tctl2.Enable()
319                            self.sizer4_4.Add(Tctl2, (iy,ix),(1,1),
320                                               wx.EXPAND|wx.ADJUST_MINSIZE, 0)
321                            ix +=1
322                            #self.sizer4_4.Add((20,20), (iy,ix),(1,1),
323                                               #wx.EXPAND|wx.ADJUST_MINSIZE, 0)
324                            self.fixed_param.append([None,name3, Tctl2,
325                                                     None,None, None, None,None])
326                            self.orientation_params_disp.append([None,name3, Tctl2,
327                                                     None,None, None, None,None])
328         
329        msg = " Selected Distribution: Gaussian"       
330        wx.PostEvent(self.parent, StatusEvent( status= msg )) 
331        self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict)   
332        ix =0
333        iy +=1 
334        #self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)   
335        self.sizer4_4.Layout()
336        self.sizer4.Layout()
337        self.SetupScrolling()
338             
339 
340    def _onModel2D(self, event):
341        """
342        call manager to plot model in 2D
343       
344        """
345        # If the 2D display is not currently enabled, plot the model in 2D
346        # and set the enable2D flag.
347
348        if self.fitrange:
349            self.enable2D = True
350 
351        if self.enable2D:
352            self._draw_model()
353            self.model_view.Disable()
354           
355            n = self.disp_box.GetCurrentSelection()
356            dispersity= self.disp_box.GetClientData(n)
357            #TODO:Find a better way to reinitialize the parameters containers
358            # when resetting the page and 2D view is enable
359            #self.set_model_param_sizer(self.model): called here is using a lot
360            #of for loops and redraw the sizer again .How to avoid it?
361            self.set_model_param_sizer(self.model)
362           
363            if len(self.orientation_params)>0:
364                for item in self.orientation_params:
365                    if item[2]!=None:     
366                        item[2].Enable()
367            # same as above why do we have to redraw the sizer of dispersity to get
368            # the appropriate value of parameters containers on reset page?
369            # Reset containers of dispersity parameters for the appropriate dispersity
370            #and model
371            if  self.disp_name.lower()in ["array","arraydispersion"]:               
372                self._set_sizer_arraydispersion() 
373            else:
374                self._set_sizer_dispersion(dispersity)
375                if len(self.orientation_params_disp)>0:
376                   
377                    for item in self.orientation_params_disp:
378                        if item[2]!=None:
379                            item[2].Enable()
380                           
381        self.state.enable2D =  copy.deepcopy(self.enable2D)
382        self.Layout()
383        ## post state to fit panel
384        #self._undo.Enable(True)
385        event = PageInfoEvent(page = self)
386        wx.PostEvent(self.parent, event)
387       
388    def _set_fun_box_list(self,fun_box):
389        """
390        Set the list of func for multifunctional models
391       
392        :param fun_box: function combo box
393        """
394        # Check if it is multi_functional model
395        if self.model.__class__ not in self.model_list_box["Multi-Functions"]:
396            return None
397        # Get the func name list
398        list = self.model.fun_list
399       
400        if len(list) == 0:
401            return None
402
403        # build function (combo)box
404        ind = 0
405        while(ind < len(list)):
406            for key, val in list.iteritems():
407                if (val == ind):
408                    fun_box.Append(key,val)
409                    break
410            ind += 1
411           
412    def _on_fun_box(self,event):
413        """
414        Select an func: Erf,Rparabola,LParabola...
415        """
416        fun_val = None
417        fun_box = event.GetEventObject()
418        name = fun_box.Name
419        value = fun_box.GetValue()
420        if self.model.fun_list.has_key(value):
421            fun_val = self.model.fun_list[value]
422       
423        self.model.setParam(name,fun_val)
424        # save state
425        self._copy_parameters_state(self.str_parameters, self.state.str_parameters)
426        # update params
427        #self._update_paramv_on_fit()
428
429        # draw
430        self._draw_model()
431        self.Refresh()
432        # get ready for new event
433        event.Skip()
434             
435    def set_data(self, list=[], state=None):
436        """
437        Receive  a list of data from gui_manager to plot theory
438        """
439        pass
440     
441    def reset_page(self, state):
442        """
443        reset the state
444       
445        """
446        self.reset_page_helper(state)
447       
448       
449    def select_model(self, model):
450        """
451        Select a new model
452       
453        :param model: model object
454       
455        """
456        self.model = model
457        if self.model !=None:
458            self.disp_list= self.model.getDispParamList()
459        self.set_model_param_sizer(self.model)
460        ## keep the sizer view consistent with the model menu selecting
461        self._set_model_sizer_selection( self.model )
462        self.enable_disp.SetValue(False)
463        self.disable_disp.SetValue(True)
464        self.set_dispers_sizer()
465       
466        self.model_view.SetFocus()
467        if self.model !=None:
468            self._draw_model()
469        self.state.structurecombobox = self.structurebox.GetCurrentSelection()
470        self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection()
471       
472        ## post state to fit panel
473        #self._undo.Enable(True)
474        event = PageInfoEvent(page = self)
475        wx.PostEvent(self.parent, event)               
476   
477   
478    def set_model_description(self,description,sizer):
479        """
480        fill a sizer with description
481       
482        :param description: of type string
483        :param sizer: wx.BoxSizer()
484       
485        """
486   
487        sizer.Clear(True)
488        box_description= wx.StaticBox(self, -1, 'Model Description')
489        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
490
491        sizer_selection=wx.BoxSizer(wx.HORIZONTAL)
492        self.description_hide = wx.RadioButton(self, -1, 'Hide', 
493                                               style=wx.RB_GROUP)
494        self.description_show = wx.RadioButton(self, -1, 'Show')
495       
496       
497        if description == "":
498            self.description_hide.SetValue(True)
499            description = " Description unavailable. Click for details"
500           
501        self.description = wx.StaticText( self,-1,str(description) )
502       
503        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
504                   id=self.description_hide.GetId() )
505       
506        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
507                   id=self.description_show.GetId() )
508        #MAC needs SetValue
509        self.description_hide.SetValue(True)
510       
511        self.model_description = wx.Button(self,-1, label="Details", size=(80,23))
512       
513        self.model_description.Bind(wx.EVT_BUTTON,self.on_button_clicked)
514        self.model_description.SetToolTipString("Click Model Functions in HelpWindow...")
515        self.model_description.SetFocus()
516        sizer_selection.Add( self.description_show )
517        sizer_selection.Add( (20,20)) 
518        sizer_selection.Add( self.description_hide )
519        sizer_selection.Add((20,20),0, wx.LEFT|wx.RIGHT|wx.EXPAND,75)
520        sizer_selection.Add( self.model_description )
521                     
522         
523        self.sizer_description=wx.BoxSizer(wx.HORIZONTAL)
524        self.sizer_description.Add( self.description, 1, wx.EXPAND | wx.ALL, 10 )
525        boxsizer1.Add( sizer_selection) 
526        boxsizer1.Add( (20,20)) 
527        boxsizer1.Add( self.sizer_description) 
528   
529        self._on_display_description(event=None)
530        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
531        sizer.Layout()
532   
533    def on_button_clicked(self,event):
534        """
535        On 'More details' button
536        """
537        from help_panel import  HelpWindow
538        import sans.models as models 
539        # Get models help model_function path
540        path = models.get_data_path(media='media')
541        model_path = os.path.join(path,"model_functions.html")
542       
543        if self.model == None:
544            name = 'FuncHelp'
545        else:
546            name = self.model.name
547        frame = HelpWindow(None, -1,  pageToOpen=model_path)   
548        frame.Show(True)
549        if frame.rhelp.HasAnchor(name):
550            frame.rhelp.ScrollToAnchor(name)
551        else:
552           msg= "Model does not contains an available description "
553           msg +="Please.Search in the Help window"
554           wx.PostEvent(self.parent, StatusEvent(status = msg ))
555
556                     
557    def set_range(self, qmin_x, qmax_x, npts):
558        """
559        Set the range for the plotted models
560       
561        :param qmin: minimum Q
562        :param qmax: maximum Q
563        :param npts: number of Q bins
564       
565        """
566        # Set the data members
567        self.qmin_x = qmin_x
568        self.qmax_x = qmax_x
569        self.num_points = npts
570        # Set the controls
571        #For qmin and qmax, do not use format_number.(If do, qmin and max could be different from what is in the data.)
572        self.qmin.SetValue(str(self.qmin_x))
573        self.qmax.SetValue(str(self.qmax_x))
574        self.npts.SetValue(format_number(self.num_points))
575       
576    def set_model_param_sizer(self, model):
577        """
578        Build the panel from the model content
579       
580        :param model: the model selected in combo box for fitting purpose
581       
582        """
583        self.sizer3.Clear(True)
584        self.parameters = []
585        self.str_parameters = []
586        self.param_toFit=[]
587        self.fixed_param=[]
588        self.orientation_params=[]
589        self.orientation_params_disp=[]
590        #self.temp=[]
591        if model ==None:
592            ##no model avaiable to draw sizer
593            self.sizer3.Layout()
594            self.SetupScrolling()
595            return
596        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
597        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
598        sizer = wx.GridBagSizer(5,5)
599       
600        self.model = model
601        self.set_model_description(self.model.description,self.sizer2)
602       
603        keys = self.model.getParamList()
604        ##list of dispersion parameters
605        self.disp_list=self.model.getDispParamList()
606       
607        def custom_compare(a,b):
608            """
609            Custom compare to order, first by alphabets then second by number.
610            """ 
611            # number at the last digit
612            a_last = a[len(a)-1]
613            b_last = b[len(b)-1]
614            # default
615            num_a = None
616            num_b = None
617            # split the names
618            a2 = a.lower().split('_')
619            b2 = b.lower().split('_')
620            # check length of a2, b2
621            len_a2 = len(a2)
622            len_b2 = len(b2)
623            # check if it contains a int number(<10)
624            try: 
625                num_a = int(a_last)
626            except: pass
627            try:
628                num_b = int(b_last)
629            except: pass
630            # Put 'scale' near the top; happens
631            # when numbered param name exists
632            if a == 'scale':
633                return -1
634            # both have a number   
635            if num_a != None and num_b != None:
636                if num_a > num_b: return -1
637                # same number
638                elif num_a == num_b: 
639                    # different last names
640                    if a2[len_a2-1] != b2[len_b2-1] and num_a != 0:
641                        return -cmp(a2[len_a2-1], b2[len_b2-1])
642                    else: 
643                        return cmp(a, b) 
644                else: return 1
645            # one of them has a number
646            elif num_a != None: return 1
647            elif num_b != None: return -1
648            # no numbers
649            else: return cmp(a.lower(), b.lower())
650
651        keys.sort(custom_compare)
652
653   
654        iy = 0
655        ix = 0
656        self.text1_2 = wx.StaticText(self, -1, 'Names')
657        sizer.Add(self.text1_2,(iy, ix),(1,1),\
658                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
659        ix +=1
660        self.text2_2 = wx.StaticText(self, -1, 'Values')
661        sizer.Add(self.text2_2,(iy, ix),(1,1),\
662                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
663        ix +=1
664        self.text2_4 = wx.StaticText(self, -1, '[Units]')
665        sizer.Add(self.text2_4,(iy, ix),(1,1),\
666                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
667        self.text2_4.Hide()
668       
669        for item in keys:
670            if not item in self.disp_list and not item in self.model.orientation_params:
671                iy += 1
672                ix = 0
673                if self.model.__class__ in self.model_list_box["Multi-Functions"]\
674                            and item in self.model.non_fittable:
675                    non_fittable_name = wx.StaticText(self, -1, item )
676                    sizer.Add(non_fittable_name,(iy, ix),(1,1),\
677                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
678                    ## add parameter value
679                    ix += 1
680                    value= self.model.getParam(item)
681                    if len(self.model.fun_list) > 0:
682                        num = item.split('_')[1][5:7]
683                        fun_box = wx.ComboBox(self, -1,size=(100,-1),style=wx.CB_READONLY, name = '%s'% item)
684                        self._set_fun_box_list(fun_box)
685                        fun_box.SetSelection(0)
686                        #self.fun_box.SetToolTipString("A function describing the interface")
687                        wx.EVT_COMBOBOX(fun_box,-1, self._on_fun_box)
688                    else:
689                        fun_box = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
690                                        style=wx.TE_PROCESS_ENTER, name ='%s'% item)
691                        fun_box.SetToolTipString("Hit 'Enter' after typing.")
692                        fun_box.SetValue(format_number(value))
693                    sizer.Add(fun_box, (iy,ix),(1,1), wx.EXPAND)
694                    ##[cb state, name, value, "+/-", error of fit, min, max , units]
695                    self.str_parameters.append([None,item, fun_box, \
696                                                None,None,None,None,None])
697                else:
698                    name = wx.StaticText(self, -1,item)
699                    sizer.Add( name,( iy, ix),(1,1),
700                                 wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
701   
702                    ix += 1
703                    value= self.model.getParam(item)
704                    ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
705                        style=wx.TE_PROCESS_ENTER)
706                   
707                    ctl1.SetValue(str (format_number(value)))
708                   
709                    sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
710                    ix +=1
711                    # Units
712                    if self.model.details.has_key(item):
713                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
714                    else:
715                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
716                    sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
717                    ##[cb state, name, value, "+/-", error of fit, min, max , units]
718                    self.parameters.append([None,item, ctl1,
719                                            None,None, None, None,None])
720        iy+=1
721        sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
722        iy += 1
723        ix = 0
724       
725        #Add tile for orientational angle parameters
726        for item in keys:
727            if item in self.model.orientation_params:       
728                orient_angle = wx.StaticText(self, -1, '[For 2D only]:')
729                sizer.Add(orient_angle,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
730                if not self.enable2D:
731                    orient_angle.Hide()
732                else:
733                    orient_angle.Show(True)
734                break
735                                         
736        for item  in self.model.orientation_params:
737            if not item in self.disp_list and item in keys:
738                iy += 1
739                ix = 0
740                name = wx.StaticText(self, -1,item)
741                sizer.Add( name,( iy, ix),(1,1),
742                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
743                if not self.enable2D:
744                    name.Hide()
745                else:
746                    name.Show(True)
747
748                ix += 1
749                value= self.model.getParam(item)
750                ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20),
751                    style=wx.TE_PROCESS_ENTER)
752               
753                ctl1.SetValue(str (format_number(value)))
754                if not self.enable2D:
755                    ctl1.Hide()
756                    ctl1.Disable()
757                else:
758                    ctl1.Show(True)
759                    ctl1.Enable()
760               
761                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
762                ix +=1
763                # Units
764                if self.model.details.has_key(item):
765                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
766                else:
767                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
768                if not self.enable2D:
769                    units.Hide()
770                else:
771                    units.Show(True)
772   
773                sizer.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
774                #Save 2D orient. params
775                #self.temp.append([name,ctl1,units,orient_angle])
776               
777                               
778                ##[cb state, name, value, "+/-", error of fit, min, max , units]
779                self.parameters.append([None,item, ctl1,
780                                        None,None, None, None,None])
781                self.orientation_params.append([None,item, ctl1,
782                                        None,None, None, None,None]) 
783        iy += 1
784       
785        #Display units text on panel
786        for item in keys:   
787            self.text2_4.Show()
788
789        boxsizer1.Add(sizer)
790        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
791        self.sizer3.Layout()
792        self.SetupScrolling()
793               
Note: See TracBrowser for help on using the repository browser.