source: sasview/src/sas/perspectives/calculator/sld_panel.py @ f89fa84

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 f89fa84 was 33f551f, checked in by butler, 10 years ago

minor fix on help button

  • Property mode set to 100644
File size: 20.8 KB
Line 
1"""
2This module provide GUI for the neutron scattering length density calculator
3
4"""
5
6import wx
7import math
8import sys
9
10from sas.guiframe.panel_base import PanelBase
11
12from sas.guiframe.utils import format_number
13from sas.guiframe.utils import check_float
14from sas.guiframe.events import StatusEvent 
15
16# the calculator default value for wavelength is 6
17#import periodictable
18from periodictable import formula
19from periodictable.xsf import xray_energy
20from periodictable.xsf import xray_sld_from_atoms
21from periodictable.nsf import neutron_scattering
22from sas.perspectives.calculator import calculator_widgets as widget   
23from sas.guiframe.documentation_window import DocumentationWindow
24       
25WAVELENGTH = 6.0
26_BOX_WIDTH = 76
27_STATICBOX_WIDTH = 350
28_SCALE = 1e-6
29
30#SLD panel size
31if sys.platform.count("win32") > 0:
32    _STATICBOX_WIDTH = 350
33    PANEL_SIZE = 400
34    FONT_VARIANT = 0
35else:
36    _STATICBOX_WIDTH = 380
37    PANEL_SIZE = 410
38    FONT_VARIANT = 1
39   
40class SldPanel(wx.Panel, PanelBase):
41    """
42    Provides the SLD calculator GUI.
43    """
44    ## Internal nickname for the window, used by the AUI manager
45    window_name = "SLD Calculator"
46    ## Name to appear on the window title bar
47    window_caption = "SLD Calculator"
48    ## Flag to tell the AUI manager to put this panel in the center pane
49    CENTER_PANE = True
50   
51    def __init__(self, parent, base=None, *args, **kwds):
52        """
53        """
54        wx.Panel.__init__(self, parent, *args, **kwds)
55        PanelBase.__init__(self)
56        #Font size
57        self.SetWindowVariant(variant=FONT_VARIANT)
58        # Object that receive status event
59        self.base = base
60        self.wavelength = WAVELENGTH
61        #layout attribute
62        self.compound_ctl = None
63        self.density_ctl = None
64        self.compound = ""
65        self.density = ""
66        self.wavelength_ctl = None
67        self.neutron_sld_real_ctl = None
68        self.neutron_sld_im_ctl = None
69        self.mo_ka_sld_real_ctl = None
70        self.mo_ka_sld_im_ctl = None
71        self.cu_ka_sld_real_ctl = None
72        self.cu_ka_sld_im_ctl = None
73        self.neutron_abs_ctl = None
74        self.neutron_inc_ctl = None
75        self.neutron_length_ctl = None
76        self.button_calculate = None
77        #Draw the panel
78        self._do_layout()
79        self.SetAutoLayout(True)
80        self.Layout()
81       
82    def _do_layout(self):
83        """
84        Draw window content
85        """
86        unit_a = '[A]'
87        unit_density = '[g/cm^(3)]'
88        unit_sld = '[1/A^(2)]'
89        unit_cm1 = '[1/cm]'
90        unit_cm = '[cm]'
91        sizer_input = wx.GridBagSizer(5, 5)
92        sizer_output = wx.GridBagSizer(5, 5)
93        sizer_button = wx.BoxSizer(wx.HORIZONTAL)
94        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
95        sizer2 = wx.BoxSizer(wx.HORIZONTAL)
96        sizer3 = wx.BoxSizer(wx.HORIZONTAL)
97        #---------inputs----------------
98        inputbox = wx.StaticBox(self, -1, "Input")
99        boxsizer1 = wx.StaticBoxSizer(inputbox, wx.VERTICAL)
100        boxsizer1.SetMinSize((_STATICBOX_WIDTH, -1))
101       
102        compound_txt = wx.StaticText(self, -1, 'Compound ')
103        self.compound_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH*2, -1))
104        density_txt = wx.StaticText(self, -1, 'Density ')
105        self.density_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, -1))
106        unit_density_txt = wx.StaticText(self, -1, unit_density)
107        wavelength_txt = wx.StaticText(self, -1, 'Wavelength ')
108        self.wavelength_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, -1))
109        self.wavelength_ctl.SetValue(str(self.wavelength))
110        unit_a_txt = wx.StaticText(self, -1, unit_a)
111        iy = 0
112        ix = 0
113        sizer_input.Add(compound_txt, (iy, ix), (1, 1),
114                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
115        ix += 1
116        sizer_input.Add(self.compound_ctl, (iy, ix), (1, 1),
117                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
118        iy += 1
119        ix = 0
120        sizer_input.Add(density_txt, (iy, ix), (1, 1),
121                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
122        ix += 1
123        sizer_input.Add(self.density_ctl, (iy, ix), (1, 1),
124                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
125        ix +=1
126        sizer_input.Add(unit_density_txt,(iy, ix), (1, 1),
127                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
128        iy += 1
129        ix = 0
130        sizer_input.Add(wavelength_txt, (iy, ix), (1, 1),
131                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
132        ix += 1
133        sizer_input.Add(self.wavelength_ctl, (iy, ix), (1, 1),
134                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
135        ix += 1
136        sizer_input.Add(unit_a_txt, (iy, ix), (1, 1),
137                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
138        boxsizer1.Add(sizer_input)
139        sizer1.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
140        #---------Outputs sizer--------
141        outputbox = wx.StaticBox(self, -1, "Output")
142        boxsizer2 = wx.StaticBoxSizer(outputbox, wx.VERTICAL)
143        boxsizer2.SetMinSize((_STATICBOX_WIDTH, -1))
144       
145        i_complex = '- i'
146        neutron_sld_txt = wx.StaticText(self, -1, 'Neutron SLD')
147        self.neutron_sld_real_ctl = wx.TextCtrl(self, -1,
148                                                 size=(_BOX_WIDTH, -1))
149        self.neutron_sld_real_ctl.SetEditable(False)
150        self.neutron_sld_real_ctl.SetToolTipString("Neutron SLD real.")
151        self.neutron_sld_im_ctl = wx.TextCtrl(self, -1, 
152                                              size=(_BOX_WIDTH, -1))
153        self.neutron_sld_im_ctl.SetEditable(False)
154        self.neutron_sld_im_ctl.SetToolTipString("Neutron SLD imaginary.")
155        neutron_sld_units_txt = wx.StaticText(self, -1, unit_sld)
156       
157        cu_ka_sld_txt = wx.StaticText(self, -1, 'Cu Ka SLD')
158        self.cu_ka_sld_real_ctl = wx.TextCtrl(self, -1,
159                                               size=(_BOX_WIDTH, -1))
160        self.cu_ka_sld_real_ctl.SetEditable(False)
161        self.cu_ka_sld_real_ctl.SetToolTipString("Cu Ka SLD real.")
162        self.cu_ka_sld_im_ctl = wx.TextCtrl(self, -1, 
163                                            size=(_BOX_WIDTH, -1))
164        self.cu_ka_sld_im_ctl.SetEditable(False)
165        self.cu_ka_sld_im_ctl.SetToolTipString("Cu Ka SLD imaginary.")
166        cu_ka_sld_units_txt = wx.StaticText(self, -1, unit_sld)
167       
168        mo_ka_sld_txt = wx.StaticText(self, -1, 'Mo Ka SLD')
169        self.mo_ka_sld_real_ctl = wx.TextCtrl(self, -1,
170                                               size=(_BOX_WIDTH, -1))
171        self.mo_ka_sld_real_ctl.SetEditable(False)
172        self.mo_ka_sld_real_ctl.SetToolTipString("Mo Ka SLD real.")
173        self.mo_ka_sld_im_ctl = wx.TextCtrl(self, -1,
174                                             size=(_BOX_WIDTH, -1))
175        self.mo_ka_sld_im_ctl.SetEditable(False)
176        self.mo_ka_sld_im_ctl.SetToolTipString("Mo Ka SLD imaginary.")
177        mo_ka_sld_units_txt = wx.StaticText(self, -1, unit_sld)
178       
179        neutron_inc_txt = wx.StaticText(self, -1, 'Neutron Inc. Xs')
180        self.neutron_inc_ctl = wx.TextCtrl(self, -1,
181                                            size=(_BOX_WIDTH, -1))
182        self.neutron_inc_ctl.SetEditable(False)
183        self.neutron_inc_ctl.SetToolTipString("Neutron Inc. Xs")
184        neutron_inc_units_txt = wx.StaticText(self, -1,  unit_cm1)
185       
186        neutron_abs_txt = wx.StaticText(self, -1, 'Neutron Abs. Xs')     
187        self.neutron_abs_ctl = wx.TextCtrl(self, -1, 
188                                           size=(_BOX_WIDTH, -1))
189        self.neutron_abs_ctl.SetEditable(False)
190        self.neutron_abs_ctl.SetToolTipString("Neutron Abs. Xs")
191        neutron_abs_units_txt = wx.StaticText(self, -1,  unit_cm1)
192     
193        neutron_length_txt = wx.StaticText(self, -1, 'Neutron 1/e length')
194        self.neutron_length_ctl = wx.TextCtrl(self, -1,
195                                               size=(_BOX_WIDTH, -1))
196        self.neutron_length_ctl.SetEditable(False)
197        self.neutron_length_ctl.SetToolTipString("Neutron 1/e length")
198        neutron_length_units_txt = wx.StaticText(self, -1,  unit_cm)
199     
200        iy = 0
201        ix = 0
202        sizer_output.Add(neutron_sld_txt, (iy, ix), (1, 1),
203                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
204        ix += 1
205        sizer_output.Add(self.neutron_sld_real_ctl, (iy, ix), (1, 1),
206                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
207        ix += 1
208        sizer_output.Add(wx.StaticText(self, -1, i_complex),
209                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
210        ix += 1
211        sizer_output.Add(self.neutron_sld_im_ctl,
212                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
213        ix += 1
214        sizer_output.Add(neutron_sld_units_txt,
215                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
216        iy += 1
217        ix = 0
218        sizer_output.Add(cu_ka_sld_txt, (iy, ix), (1, 1),
219                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
220        ix += 1
221        sizer_output.Add(self.cu_ka_sld_real_ctl, (iy, ix), (1, 1),
222                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
223        ix += 1
224        sizer_output.Add(wx.StaticText(self, -1, i_complex),
225                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
226        ix += 1
227        sizer_output.Add(self.cu_ka_sld_im_ctl,
228                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
229        ix += 1
230        sizer_output.Add(cu_ka_sld_units_txt,
231                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
232        iy += 1
233        ix = 0
234        sizer_output.Add(mo_ka_sld_txt,(iy, ix), (1, 1),
235                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
236        ix += 1
237        sizer_output.Add(self.mo_ka_sld_real_ctl,(iy, ix), (1, 1),
238                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
239        ix += 1
240        sizer_output.Add(wx.StaticText(self, -1, i_complex),
241                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
242        ix += 1
243        sizer_output.Add(self.mo_ka_sld_im_ctl,
244                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
245        ix += 1
246        sizer_output.Add(mo_ka_sld_units_txt,
247                         (iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
248        iy += 1
249        ix = 0
250        sizer_output.Add(neutron_inc_txt, (iy, ix), (1, 1),
251                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
252        ix += 1
253        sizer_output.Add(self.neutron_inc_ctl, (iy, ix), (1, 1),
254                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
255        ix += 2
256        sizer_output.Add(neutron_inc_units_txt,(iy, ix), (1, 1),
257                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
258        iy += 1
259        ix = 0
260        sizer_output.Add(neutron_abs_txt, (iy, ix), (1, 1),
261                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
262        ix += 1
263        sizer_output.Add(self.neutron_abs_ctl, (iy, ix), (1, 1),
264                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
265        ix += 2
266        sizer_output.Add(neutron_abs_units_txt, (iy, ix), (1, 1),
267                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
268        iy += 1
269        ix = 0
270        sizer_output.Add(neutron_length_txt, (iy, ix), (1, 1),
271                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
272        ix += 1
273        sizer_output.Add(self.neutron_length_ctl, (iy, ix), (1, 1),
274                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
275        ix += 2
276        sizer_output.Add(neutron_length_units_txt, (iy, ix), (1, 1),
277                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
278        boxsizer2.Add(sizer_output)
279        sizer2.Add(boxsizer2, 0, wx.EXPAND|wx.ALL, 10)
280        #-----Button  sizer------------
281   
282        id = wx.NewId()
283        self.button_calculate = wx.Button(self, id, "Calculate")
284        self.button_calculate.SetToolTipString("Calculate SLD.")
285        self.Bind(wx.EVT_BUTTON, self.calculateSld, id=id)   
286       
287        id = wx.NewId()
288        self.button_help = wx.Button(self, id, "HELP")
289        self.button_help.SetToolTipString("help on SLD calculator.")
290        self.Bind(wx.EVT_BUTTON, self.on_help, id=id)   
291       
292        sizer_button.Add((150, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
293        sizer_button.Add(self.button_calculate, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 20)
294        sizer_button.Add(self.button_help, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 20)
295        sizer3.Add(sizer_button)
296        #---------layout----------------
297        vbox  = wx.BoxSizer(wx.VERTICAL)
298        vbox.Add(sizer1)
299        vbox.Add(sizer2)
300        vbox.Add(sizer3)
301        vbox.Fit(self) 
302        self.SetSizer(vbox)
303       
304    def on_help(self, event):   
305        """
306        Bring up the SLD Documentation whenever
307        the HELP button is clicked.
308       
309        Calls DocumentationWindow with the path of the location within the
310        documentation tree (after /doc/ ....".  Note that when using old
311        versions of Wx (before 2.9) and thus not the release version of
312        installers, the help comes up at the top level of the file as
313        webbrowser does not pass anything past the # to the browser when it is
314        running "file:///...."
315   
316    :param evt: Triggers on clicking the help button
317    """
318               
319        _TreeLocation = "user/perspectives/calculator/sld_calculator_help.html"
320        _doc_viewer = DocumentationWindow(self, -1, \
321             _TreeLocation,"General Scattering Calculator Help")
322
323    def calculate_xray_sld(self, element):
324        """
325        Get an element and compute the corresponding SLD for a given formula
326       
327        :param element:  elements a string of existing atom
328       
329        """
330        myformula = formula(str(element))
331        if len(myformula.atoms) != 1:
332            return 
333        element = myformula.atoms.keys()[0] 
334        energy = xray_energy(element.K_alpha)
335       
336        self.sld_formula = formula(str(self.compound), density=self.density)
337        atom = self.sld_formula.atoms
338        return xray_sld_from_atoms(atom, density=self.density, energy= energy)
339   
340    def check_inputs(self):
341        """Check validity user inputs"""
342        flag = True
343        msg = ""
344        if check_float(self.density_ctl):
345            self.density = float(self.density_ctl.GetValue())
346        else:
347            flag = False
348            msg += "Error for Density value :expect float"
349   
350        self.wavelength = self.wavelength_ctl.GetValue()
351        if str(self.wavelength).lstrip().rstrip() == "":
352            self.wavelength = WAVELENGTH
353            self.wavelength_ctl.SetValue(str(WAVELENGTH))
354            self.wavelength_ctl.SetBackgroundColour(wx.WHITE)
355            self.wavelength_ctl.Refresh()
356            msg += "Default value for wavelength is 6.0"
357        else:
358            if check_float(self.wavelength_ctl):
359                self.wavelength = float(self.wavelength)
360            else:
361                flag = False
362                msg += "Error for wavelength value :expect float"
363               
364        self.compound = self.compound_ctl.GetValue().lstrip().rstrip()
365        if self.compound != "":
366            try :
367                formula(self.compound)
368                self.compound_ctl.SetBackgroundColour(wx.WHITE)
369                self.compound_ctl.Refresh()
370            except:
371                self.compound_ctl.SetBackgroundColour("pink")
372                self.compound_ctl.Refresh()
373                flag = False
374                msg += "Enter correct formula"
375        else:
376            self.compound_ctl.SetBackgroundColour("pink")
377            self.compound_ctl.Refresh()
378            flag = False
379            msg += "Enter a formula"
380        return flag, msg
381       
382    def calculate_sld_helper(self, element, density, molecule_formula):
383        """
384        Get an element and compute the corresponding SLD for a given formula
385       
386        :param element:  elements a string of existing atom
387       
388        """
389        element_formula = formula(str(element))
390        if len(element_formula.atoms) != 1:
391            return 
392        element = element_formula.atoms.keys()[0] 
393        energy = xray_energy(element.K_alpha)
394        atom = molecule_formula.atoms
395        return xray_sld_from_atoms(atom, density=density, energy=energy)
396
397
398    def calculateSld(self, event):
399        """
400            Calculate the neutron scattering density length of a molecule
401        """
402        self.clear_outputs()
403        try:
404            #Check validity user inputs
405            flag, msg = self.check_inputs()
406            if self.base is not None and msg.lstrip().rstrip() != "":
407                msg = "SLD Calculator: %s" % str(msg)
408                wx.PostEvent(self.base, StatusEvent(status=msg))
409            if not flag:
410               return 
411            #get ready to compute
412            self.sld_formula = formula(self.compound,
413                                            density=self.density)
414            (sld_real, sld_im, _), (_, absorp, incoh), \
415                        length = neutron_scattering(compound=self.compound,
416                                   density=self.density, 
417                                   wavelength=self.wavelength) 
418            cu_real, cu_im = self.calculate_sld_helper(element="Cu",
419                                                 density=self.density,
420                                        molecule_formula=self.sld_formula)
421            mo_real, mo_im = self.calculate_sld_helper(element="Mo", 
422                                                       density=self.density,
423                                     molecule_formula=self.sld_formula)
424            # set neutron sld values
425            val = format_number(sld_real * _SCALE)
426            self.neutron_sld_real_ctl.SetValue(val)
427            val = format_number(math.fabs(sld_im) * _SCALE)
428            self.neutron_sld_im_ctl.SetValue(val)
429            # Compute the Cu SLD
430            self.cu_ka_sld_real_ctl.SetValue(format_number(cu_real *_SCALE))
431            val = format_number(math.fabs(cu_im )* _SCALE)
432            self.cu_ka_sld_im_ctl.SetValue(val)
433            # Compute the Mo SLD
434            self.mo_ka_sld_real_ctl.SetValue(format_number(mo_real *_SCALE))
435            val = format_number(math.fabs(mo_im)* _SCALE)
436            self.mo_ka_sld_im_ctl.SetValue(val)
437            # set incoherence and absorption
438            self.neutron_inc_ctl.SetValue(format_number(incoh))
439            self.neutron_abs_ctl.SetValue(format_number(absorp))
440            # Neutron length
441            self.neutron_length_ctl.SetValue(format_number(length))
442            # display wavelength
443            self.wavelength_ctl.SetValue(str(self.wavelength))
444        except:
445            if self.base is not None:
446                msg = "SLD Calculator: %s"%(sys.exc_value)
447                wx.PostEvent(self.base, StatusEvent(status=msg))
448        if event is not None:
449            event.Skip()
450           
451    def clear_outputs(self):
452        """
453        Clear the outputs textctrl
454        """
455        self.neutron_sld_real_ctl.SetValue("")
456        self.neutron_sld_im_ctl.SetValue("")
457        self.mo_ka_sld_real_ctl.SetValue("")
458        self.mo_ka_sld_im_ctl.SetValue("")
459        self.cu_ka_sld_real_ctl.SetValue("")
460        self.cu_ka_sld_im_ctl.SetValue("")
461        self.neutron_abs_ctl.SetValue("")
462        self.neutron_inc_ctl.SetValue("")
463        self.neutron_length_ctl.SetValue("")
464       
465       
466class SldWindow(widget.CHILD_FRAME):
467    """
468    """
469    def __init__(self, parent=None, title="SLD Calculator",
470                  base=None, manager=None, 
471                  size=(PANEL_SIZE, PANEL_SIZE), *args, **kwds):
472        """
473        """
474        kwds['title'] = title
475        kwds['size'] = size
476        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
477        """
478        """
479        self.parent = parent
480        self.base = base
481        self.manager = manager
482        self.panel = SldPanel(self, base=base)
483        self.Bind(wx.EVT_CLOSE, self.on_close)
484        self.SetPosition((20, 10))
485        self.Show(True)
486   
487    def on_close(self, event):
488        """
489        On close event
490        """
491        if self.manager != None:
492            self.manager.sld_frame = None
493        self.Destroy()
494       
495       
496class ViewApp(wx.App):
497    """
498    """
499    def OnInit(self):
500        """
501        """
502        widget.CHILD_FRAME = wx.Frame
503        frame = SldWindow(None, title='SLD Calculator')   
504        frame.Show(True)
505        self.SetTopWindow(frame)
506        return True
507       
508
509if __name__ == "__main__": 
510    app = ViewApp(0)
511    app.MainLoop()     
Note: See TracBrowser for help on using the repository browser.