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

Last change on this file since 6c7ebb88 was 9f3db13, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 6 years ago

Removed Recalculate button. Added check for 0 < eps for wavelengths so
the denominators are happy. Simplified signalling. SASVIEW-1142

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