"""
This module provide GUI for the neutron scattering length density calculator
"""
import wx
import math
import sys
from sas.guiframe.panel_base import PanelBase
from sas.guiframe.utils import format_number
from sas.guiframe.utils import check_float
from sas.guiframe.events import StatusEvent
# the calculator default value for wavelength is 6
#import periodictable
from periodictable import formula
from periodictable.xsf import xray_energy
from periodictable.xsf import xray_sld_from_atoms
from periodictable.nsf import neutron_scattering
from sas.perspectives.calculator import calculator_widgets as widget
WAVELENGTH = 6.0
_BOX_WIDTH = 76
_STATICBOX_WIDTH = 350
_SCALE = 1e-6
#SLD panel size
if sys.platform.count("win32") > 0:
_STATICBOX_WIDTH = 350
PANEL_SIZE = 400
FONT_VARIANT = 0
else:
_STATICBOX_WIDTH = 380
PANEL_SIZE = 410
FONT_VARIANT = 1
[docs]class SldPanel(wx.Panel, PanelBase):
"""
Provides the SLD calculator GUI.
"""
## Internal nickname for the window, used by the AUI manager
window_name = "SLD Calculator"
## Name to appear on the window title bar
window_caption = "SLD Calculator"
## Flag to tell the AUI manager to put this panel in the center pane
CENTER_PANE = True
def __init__(self, parent, base=None, *args, **kwds):
"""
"""
wx.Panel.__init__(self, parent, *args, **kwds)
PanelBase.__init__(self)
#Font size
self.SetWindowVariant(variant=FONT_VARIANT)
# Object that receive status event
self.base = base
self.wavelength = WAVELENGTH
#layout attribute
self.compound_ctl = None
self.density_ctl = None
self.compound = ""
self.density = ""
self.wavelength_ctl = None
self.neutron_sld_real_ctl = None
self.neutron_sld_im_ctl = None
self.mo_ka_sld_real_ctl = None
self.mo_ka_sld_im_ctl = None
self.cu_ka_sld_real_ctl = None
self.cu_ka_sld_im_ctl = None
self.neutron_abs_ctl = None
self.neutron_inc_ctl = None
self.neutron_length_ctl = None
self.button_calculate = None
#Draw the panel
self._do_layout()
self.SetAutoLayout(True)
self.Layout()
def _do_layout(self):
"""
Draw window content
"""
unit_a = '[A]'
unit_density = '[g/cm^(3)]'
unit_sld = '[1/A^(2)]'
unit_cm1 = '[1/cm]'
unit_cm = '[cm]'
sizer_input = wx.GridBagSizer(5, 5)
sizer_output = wx.GridBagSizer(5, 5)
sizer_button = wx.BoxSizer(wx.HORIZONTAL)
sizer1 = wx.BoxSizer(wx.HORIZONTAL)
sizer2 = wx.BoxSizer(wx.HORIZONTAL)
sizer3 = wx.BoxSizer(wx.HORIZONTAL)
#---------inputs----------------
inputbox = wx.StaticBox(self, -1, "Input")
boxsizer1 = wx.StaticBoxSizer(inputbox, wx.VERTICAL)
boxsizer1.SetMinSize((_STATICBOX_WIDTH, -1))
compound_txt = wx.StaticText(self, -1, 'Compound ')
self.compound_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH*2, -1))
density_txt = wx.StaticText(self, -1, 'Density ')
self.density_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, -1))
unit_density_txt = wx.StaticText(self, -1, unit_density)
wavelength_txt = wx.StaticText(self, -1, 'Wavelength ')
self.wavelength_ctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH, -1))
self.wavelength_ctl.SetValue(str(self.wavelength))
unit_a_txt = wx.StaticText(self, -1, unit_a)
iy = 0
ix = 0
sizer_input.Add(compound_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_input.Add(self.compound_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_input.Add(density_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_input.Add(self.density_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix +=1
sizer_input.Add(unit_density_txt,(iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_input.Add(wavelength_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_input.Add(self.wavelength_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_input.Add(unit_a_txt, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
boxsizer1.Add(sizer_input)
sizer1.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10)
#---------Outputs sizer--------
outputbox = wx.StaticBox(self, -1, "Output")
boxsizer2 = wx.StaticBoxSizer(outputbox, wx.VERTICAL)
boxsizer2.SetMinSize((_STATICBOX_WIDTH, -1))
i_complex = '- i'
neutron_sld_txt = wx.StaticText(self, -1, 'Neutron SLD')
self.neutron_sld_real_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.neutron_sld_real_ctl.SetEditable(False)
self.neutron_sld_real_ctl.SetToolTipString("Neutron SLD real.")
self.neutron_sld_im_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.neutron_sld_im_ctl.SetEditable(False)
self.neutron_sld_im_ctl.SetToolTipString("Neutron SLD imaginary.")
neutron_sld_units_txt = wx.StaticText(self, -1, unit_sld)
cu_ka_sld_txt = wx.StaticText(self, -1, 'Cu Ka SLD')
self.cu_ka_sld_real_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.cu_ka_sld_real_ctl.SetEditable(False)
self.cu_ka_sld_real_ctl.SetToolTipString("Cu Ka SLD real.")
self.cu_ka_sld_im_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.cu_ka_sld_im_ctl.SetEditable(False)
self.cu_ka_sld_im_ctl.SetToolTipString("Cu Ka SLD imaginary.")
cu_ka_sld_units_txt = wx.StaticText(self, -1, unit_sld)
mo_ka_sld_txt = wx.StaticText(self, -1, 'Mo Ka SLD')
self.mo_ka_sld_real_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.mo_ka_sld_real_ctl.SetEditable(False)
self.mo_ka_sld_real_ctl.SetToolTipString("Mo Ka SLD real.")
self.mo_ka_sld_im_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.mo_ka_sld_im_ctl.SetEditable(False)
self.mo_ka_sld_im_ctl.SetToolTipString("Mo Ka SLD imaginary.")
mo_ka_sld_units_txt = wx.StaticText(self, -1, unit_sld)
neutron_inc_txt = wx.StaticText(self, -1, 'Neutron Inc. Xs')
self.neutron_inc_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.neutron_inc_ctl.SetEditable(False)
self.neutron_inc_ctl.SetToolTipString("Neutron Inc. Xs")
neutron_inc_units_txt = wx.StaticText(self, -1, unit_cm1)
neutron_abs_txt = wx.StaticText(self, -1, 'Neutron Abs. Xs')
self.neutron_abs_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.neutron_abs_ctl.SetEditable(False)
self.neutron_abs_ctl.SetToolTipString("Neutron Abs. Xs")
neutron_abs_units_txt = wx.StaticText(self, -1, unit_cm1)
neutron_length_txt = wx.StaticText(self, -1, 'Neutron 1/e length')
self.neutron_length_ctl = wx.TextCtrl(self, -1,
size=(_BOX_WIDTH, -1))
self.neutron_length_ctl.SetEditable(False)
self.neutron_length_ctl.SetToolTipString("Neutron 1/e length")
neutron_length_units_txt = wx.StaticText(self, -1, unit_cm)
iy = 0
ix = 0
sizer_output.Add(neutron_sld_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.neutron_sld_real_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(wx.StaticText(self, -1, i_complex),
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(self.neutron_sld_im_ctl,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(neutron_sld_units_txt,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_output.Add(cu_ka_sld_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.cu_ka_sld_real_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(wx.StaticText(self, -1, i_complex),
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(self.cu_ka_sld_im_ctl,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(cu_ka_sld_units_txt,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_output.Add(mo_ka_sld_txt,(iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.mo_ka_sld_real_ctl,(iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(wx.StaticText(self, -1, i_complex),
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(self.mo_ka_sld_im_ctl,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 1
sizer_output.Add(mo_ka_sld_units_txt,
(iy, ix), (1, 1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_output.Add(neutron_inc_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.neutron_inc_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer_output.Add(neutron_inc_units_txt,(iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_output.Add(neutron_abs_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.neutron_abs_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer_output.Add(neutron_abs_units_txt, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
iy += 1
ix = 0
sizer_output.Add(neutron_length_txt, (iy, ix), (1, 1),
wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
ix += 1
sizer_output.Add(self.neutron_length_ctl, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
ix += 2
sizer_output.Add(neutron_length_units_txt, (iy, ix), (1, 1),
wx.EXPAND|wx.ADJUST_MINSIZE, 0)
boxsizer2.Add(sizer_output)
sizer2.Add(boxsizer2, 0, wx.EXPAND|wx.ALL, 10)
#-----Button sizer------------
id = wx.NewId()
self.button_calculate = wx.Button(self, id, "Calculate")
self.button_calculate.SetToolTipString("Calculate SLD.")
self.Bind(wx.EVT_BUTTON, self.calculateSld, id=id)
sizer_button.Add((250, 20), 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0)
sizer_button.Add(self.button_calculate, 0, wx.RIGHT|wx.ADJUST_MINSIZE, 20)
sizer3.Add(sizer_button)
#---------layout----------------
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(sizer1)
vbox.Add(sizer2)
vbox.Add(sizer3)
vbox.Fit(self)
self.SetSizer(vbox)
[docs] def calculate_xray_sld(self, element):
"""
Get an element and compute the corresponding SLD for a given formula
:param element: elements a string of existing atom
"""
myformula = formula(str(element))
if len(myformula.atoms) != 1:
return
element = myformula.atoms.keys()[0]
energy = xray_energy(element.K_alpha)
self.sld_formula = formula(str(self.compound), density=self.density)
atom = self.sld_formula.atoms
return xray_sld_from_atoms(atom, density=self.density, energy= energy)
[docs] def calculate_sld_helper(self, element, density, molecule_formula):
"""
Get an element and compute the corresponding SLD for a given formula
:param element: elements a string of existing atom
"""
element_formula = formula(str(element))
if len(element_formula.atoms) != 1:
return
element = element_formula.atoms.keys()[0]
energy = xray_energy(element.K_alpha)
atom = molecule_formula.atoms
return xray_sld_from_atoms(atom, density=density, energy=energy)
[docs] def calculateSld(self, event):
"""
Calculate the neutron scattering density length of a molecule
"""
self.clear_outputs()
try:
#Check validity user inputs
flag, msg = self.check_inputs()
if self.base is not None and msg.lstrip().rstrip() != "":
msg = "SLD Calculator: %s" % str(msg)
wx.PostEvent(self.base, StatusEvent(status=msg))
if not flag:
return
#get ready to compute
self.sld_formula = formula(self.compound,
density=self.density)
(sld_real, sld_im, _), (_, absorp, incoh), \
length = neutron_scattering(compound=self.compound,
density=self.density,
wavelength=self.wavelength)
cu_real, cu_im = self.calculate_sld_helper(element="Cu",
density=self.density,
molecule_formula=self.sld_formula)
mo_real, mo_im = self.calculate_sld_helper(element="Mo",
density=self.density,
molecule_formula=self.sld_formula)
# set neutron sld values
val = format_number(sld_real * _SCALE)
self.neutron_sld_real_ctl.SetValue(val)
val = format_number(math.fabs(sld_im) * _SCALE)
self.neutron_sld_im_ctl.SetValue(val)
# Compute the Cu SLD
self.cu_ka_sld_real_ctl.SetValue(format_number(cu_real *_SCALE))
val = format_number(math.fabs(cu_im )* _SCALE)
self.cu_ka_sld_im_ctl.SetValue(val)
# Compute the Mo SLD
self.mo_ka_sld_real_ctl.SetValue(format_number(mo_real *_SCALE))
val = format_number(math.fabs(mo_im)* _SCALE)
self.mo_ka_sld_im_ctl.SetValue(val)
# set incoherence and absorption
self.neutron_inc_ctl.SetValue(format_number(incoh))
self.neutron_abs_ctl.SetValue(format_number(absorp))
# Neutron length
self.neutron_length_ctl.SetValue(format_number(length))
# display wavelength
self.wavelength_ctl.SetValue(str(self.wavelength))
except:
if self.base is not None:
msg = "SLD Calculator: %s"%(sys.exc_value)
wx.PostEvent(self.base, StatusEvent(status=msg))
if event is not None:
event.Skip()
[docs] def clear_outputs(self):
"""
Clear the outputs textctrl
"""
self.neutron_sld_real_ctl.SetValue("")
self.neutron_sld_im_ctl.SetValue("")
self.mo_ka_sld_real_ctl.SetValue("")
self.mo_ka_sld_im_ctl.SetValue("")
self.cu_ka_sld_real_ctl.SetValue("")
self.cu_ka_sld_im_ctl.SetValue("")
self.neutron_abs_ctl.SetValue("")
self.neutron_inc_ctl.SetValue("")
self.neutron_length_ctl.SetValue("")
[docs]class SldWindow(widget.CHILD_FRAME):
"""
"""
def __init__(self, parent=None, title="SLD Calculator",
base=None, manager=None,
size=(PANEL_SIZE, PANEL_SIZE), *args, **kwds):
"""
"""
kwds['title'] = title
kwds['size'] = size
widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
"""
"""
self.parent = parent
self.base = base
self.manager = manager
self.panel = SldPanel(self, base=base)
self.Bind(wx.EVT_CLOSE, self.on_close)
self.SetPosition((25, 150))
self.Show(True)
[docs] def on_close(self, event):
"""
On close event
"""
if self.manager != None:
self.manager.sld_frame = None
self.Destroy()
[docs]class ViewApp(wx.App):
"""
"""
[docs] def OnInit(self):
"""
"""
widget.CHILD_FRAME = wx.Frame
frame = SldWindow(None, title='SLD Calculator')
frame.Show(True)
self.SetTopWindow(frame)
return True
if __name__ == "__main__":
app = ViewApp(0)
app.MainLoop()