source: sasview/src/sas/qtgui/Calculators/SldPanel.py @ e0da307

Last change on this file since e0da307 was 5c0e717, checked in by Tim Snow <tim.snow@…>, 6 years ago

Adding more general x-ray SLD calculation funcitonality

Rather than using/limiting ourselves to Cu and Mo this approach lets you use any wavelength of x-ray radiation and display the SLD.

  • Property mode set to 100644
File size: 8.1 KB
Line 
1# global
2import logging
3from PyQt5 import QtCore
4from PyQt5 import QtGui
5from PyQt5 import QtWidgets
6
7from periodictable import formula as Formula
8from periodictable.xsf import xray_energy, xray_sld
9from periodictable.nsf import neutron_scattering
10
11import sas.qtgui.Utilities.GuiUtils as GuiUtils
12
13from sas.qtgui.UI import main_resources_rc
14
15# Local UI
16from sas.qtgui.Calculators.UI.SldPanel import Ui_SldPanel
17
18from sas.qtgui.Utilities.GuiUtils import enum
19
20MODEL = enum(
21    'MOLECULAR_FORMULA',
22    'MASS_DENSITY',
23    'NEUTRON_WAVELENGTH',
24    'NEUTRON_SLD_REAL',
25    'NEUTRON_SLD_IMAG',
26    'XRAY_WAVELENGTH',
27    'XRAY_SLD_REAL',
28    'XRAY_SLD_IMAG',
29    'NEUTRON_INC_XS',
30    'NEUTRON_ABS_XS',
31    'NEUTRON_LENGTH',
32)
33
34class SldResult(object):
35    def __init__(self, molecular_formula, mass_density,
36        neutron_wavelength, neutron_sld_real, neutron_sld_imag,
37        xray_wavelength, xray_sld_real, xray_sld_imag,
38        neutron_inc_xs, neutron_abs_xs, neutron_length):
39
40        self.molecular_formula = molecular_formula
41        self.mass_density = mass_density
42        self.neutron_wavelength = neutron_wavelength
43        self.neutron_sld_real = neutron_sld_real
44        self.neutron_sld_imag = neutron_sld_imag
45        self.xray_wavelength = xray_wavelength
46        self.xray_sld_real = xray_sld_real
47        self.xray_sld_imag = xray_sld_imag
48        self.neutron_inc_xs = neutron_inc_xs
49        self.neutron_abs_xs = neutron_abs_xs
50        self.neutron_length = neutron_length
51
52def sldAlgorithm(molecular_formula, mass_density, neutron_wavelength, xray_wavelength):
53
54    xray_sld_real, xray_sld_imag = xray_sld(
55            compound=molecular_formula,
56            density=mass_density,
57            wavelength=xray_wavelength)
58
59    (neutron_sld_real, neutron_sld_imag, _), (_, neutron_abs_xs, neutron_inc_xs), neutron_length = \
60        neutron_scattering(
61            compound=molecular_formula,
62            density=mass_density,
63            wavelength=neutron_wavelength)
64
65    SCALE = 1e-6
66
67    # neutron sld
68    scaled_neutron_sld_real = SCALE * neutron_sld_real
69    scaled_neutron_sld_imag = SCALE * abs(neutron_sld_imag)
70
71    # xray sld
72    scaled_xray_sld_real = SCALE * xray_sld_real
73    scaled_xray_sld_imag = SCALE * abs(xray_sld_imag)
74
75
76    return SldResult(
77        molecular_formula, mass_density,
78        neutron_wavelength, scaled_neutron_sld_real, scaled_neutron_sld_imag,
79        xray_wavelength, scaled_xray_sld_real, scaled_xray_sld_imag,
80        neutron_inc_xs, neutron_abs_xs, neutron_length)
81
82
83class SldPanel(QtWidgets.QDialog):
84
85    def __init__(self, parent=None):
86        super(SldPanel, self).__init__()
87
88        self.manager = parent
89
90        self.setupUi()
91        self.setupModel()
92        self.setupMapper()
93
94    def _getOutputs(self):
95        return {
96            MODEL.NEUTRON_SLD_REAL: self.ui.editNeutronSldReal,
97            MODEL.NEUTRON_SLD_IMAG: self.ui.editNeutronSldImag,
98            MODEL.XRAY_SLD_REAL: self.ui.editXraySldReal,
99            MODEL.XRAY_SLD_IMAG: self.ui.editXraySldImag,
100            MODEL.NEUTRON_INC_XS: self.ui.editNeutronIncXs,
101            MODEL.NEUTRON_ABS_XS: self.ui.editNeutronAbsXs,
102            MODEL.NEUTRON_LENGTH: self.ui.editNeutronLength
103        }
104
105    def setupUi(self):
106        self.ui = Ui_SldPanel()
107        self.ui.setupUi(self)
108
109        # set validators
110        # TODO: GuiUtils.FormulaValidator() crashes with Qt5 - fix
111        #self.ui.editMolecularFormula.setValidator(GuiUtils.FormulaValidator(self.ui.editMolecularFormula))
112
113        rx = QtCore.QRegExp("[+\-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?")
114        self.ui.editMassDensity.setValidator(QtGui.QRegExpValidator(rx, self.ui.editMassDensity))
115        self.ui.editNeutronWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editNeutronWavelength))
116        self.ui.editXrayWavelength.setValidator(QtGui.QRegExpValidator(rx, self.ui.editXrayWavelength))
117
118        # signals
119        self.ui.helpButton.clicked.connect(self.displayHelp)
120        self.ui.closeButton.clicked.connect(self.closePanel)
121        self.ui.recalculateButton.clicked.connect(self.calculateSLD)
122
123    def calculateSLD(self):
124        self.recalculateSLD()
125
126    def setupModel(self):
127        self.model = QtGui.QStandardItemModel(self)
128        self.model.setItem(MODEL.MOLECULAR_FORMULA , QtGui.QStandardItem())
129        self.model.setItem(MODEL.MASS_DENSITY      , QtGui.QStandardItem())
130        self.model.setItem(MODEL.NEUTRON_WAVELENGTH, QtGui.QStandardItem())
131        self.model.setItem(MODEL.XRAY_WAVELENGTH   , QtGui.QStandardItem())
132
133        for key in list(self._getOutputs().keys()):
134            self.model.setItem(key, QtGui.QStandardItem())
135
136        self.model.dataChanged.connect(self.dataChanged)
137
138        self.ui.editMassDensity.textEdited.connect(self.recalculateSLD)
139        self.ui.editMolecularFormula.textEdited.connect(self.recalculateSLD)
140        self.ui.editNeutronWavelength.textEdited.connect(self.recalculateSLD)
141        self.ui.editXrayWavelength.textEdited.connect(self.recalculateSLD)
142
143        self.modelReset()
144
145    def setupMapper(self):
146        self.mapper = QtWidgets.QDataWidgetMapper(self)
147        self.mapper.setModel(self.model)
148        self.mapper.setOrientation(QtCore.Qt.Vertical)
149        self.mapper.addMapping(self.ui.editMolecularFormula , MODEL.MOLECULAR_FORMULA)
150        self.mapper.addMapping(self.ui.editMassDensity      , MODEL.MASS_DENSITY)
151        self.mapper.addMapping(self.ui.editNeutronWavelength, MODEL.NEUTRON_WAVELENGTH)
152        self.mapper.addMapping(self.ui.editXrayWavelength   , MODEL.XRAY_WAVELENGTH)
153
154        for key, edit in self._getOutputs().items():
155            self.mapper.addMapping(edit, key)
156
157        self.mapper.toFirst()
158
159    def dataChanged(self, top, bottom):
160        update = False
161        for index in range(top.row(), bottom.row() + 1):
162            if (index == MODEL.MOLECULAR_FORMULA) or (index == MODEL.MASS_DENSITY) or (index == MODEL.NEUTRON_WAVELENGTH) or (index == MODEL.XRAY_WAVELENGTH):
163                update = True
164
165        # calculation
166        if update:
167            self.recalculateSLD()
168
169    def recalculateSLD(self):
170        formula = self.ui.editMolecularFormula.text()
171        density = self.ui.editMassDensity.text()
172        neutronWavelength = self.ui.editNeutronWavelength.text()
173        xrayWavelength = self.ui.editXrayWavelength.text()
174
175        if len(formula) > 0 and len(density) > 0 and len(neutronWavelength) > 0 and len(xrayWavelength) > 0:
176            try:
177                results = sldAlgorithm(str(formula), float(density), float(neutronWavelength), float(xrayWavelength))
178
179                def format(value):
180                    return ("%-5.3g" % value).strip()
181
182                self.model.item(MODEL.NEUTRON_SLD_REAL).setText(format(results.neutron_sld_real))
183                self.model.item(MODEL.NEUTRON_SLD_IMAG).setText(format(results.neutron_sld_imag))
184
185                self.model.item(MODEL.XRAY_SLD_REAL).setText(format(results.xray_sld_real))
186                self.model.item(MODEL.XRAY_SLD_IMAG).setText(format(results.xray_sld_imag))
187
188                self.model.item(MODEL.NEUTRON_INC_XS).setText(format(results.neutron_inc_xs))
189                self.model.item(MODEL.NEUTRON_ABS_XS).setText(format(results.neutron_abs_xs))
190                self.model.item(MODEL.NEUTRON_LENGTH).setText(format(results.neutron_length))
191
192                return
193
194            except Exception as e:
195                pass
196
197        for key in list(self._getOutputs().keys()):
198            self.model.item(key).setText("")
199
200    def modelReset(self):
201        #self.model.beginResetModel()
202        try:
203            self.model.item(MODEL.MOLECULAR_FORMULA ).setText("H2O")
204            self.model.item(MODEL.MASS_DENSITY      ).setText("1.0")
205            self.model.item(MODEL.NEUTRON_WAVELENGTH).setText("6.0")
206            self.model.item(MODEL.XRAY_WAVELENGTH   ).setText("1.0")
207            self.recalculateSLD()
208        finally:
209            pass
210        #self.model.endResetModel()
211
212    def displayHelp(self):
213        location = "/user/qtgui/Calculators/sld_calculator_help.html"
214        self.manager.showHelp(location)
215
216
217    def closePanel(self):
218        """
219        close the window containing this panel
220        """
221        self.close()
222
Note: See TracBrowser for help on using the repository browser.