Commit 6f3e552e authored by Henri Payno's avatar Henri Payno
Browse files

[pymca / larch] normalize the process autobk vs exafs

parent 9fe65439
......@@ -77,12 +77,12 @@ class TestSimplePyMcaWorkflow(OrangeWorflowTest):
def setUpClass(cls):
OrangeWorflowTest.setUpClass()
# create widgets
xasInputNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.xas_input.XASInputOW')
xasNormalizationNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.normalization.NormalizationOW')
xasEXAFSNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.exafs.ExafsOW')
xasKWeightNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.k_weight.KWeightOW')
xasFTNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.ft.FTOW')
xasOutputNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.xas_output.XASOutputOW')
xasInputNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.utils.xas_input.XASInputOW')
xasNormalizationNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.pymca.normalization.NormalizationOW')
xasEXAFSNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.pymca.exafs.ExafsOW')
xasKWeightNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.pymca.k_weight.KWeightOW')
xasFTNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.pymca.ft.FTOW')
xasOutputNode = cls.addWidget(cls, 'orangecontrib.xas.widgets.pymca.utils.xas_output.XASOutputOW')
cls.processOrangeEvents(cls)
......
......@@ -114,7 +114,7 @@ class AutobkWindow(qt.QMainWindow):
self._updateLegendView()
def getNCurves(self):
return len(self.xasObjViewer._spectrumViews._plot.getAllCurves())
return len(self.xasObjViewer._spectrumViews[0]._plot.getAllCurves())
def _updateLegendView(self):
index, viewType = self.xasObjViewer.getViewType()
......@@ -159,9 +159,10 @@ class AutobkOW(_ProcessForOrangeMixIn, OWWidget):
self._window._parametersWindow.setParameters(self._larchSettings)
# connect signals / slots
# TODO
self._window._parametersWindow.sigChanged.connect(self._updateProcess)
def _updateProcess(self):
"""Update settings keeping current xas obj"""
self._update_settings()
if self._latest_xas_obj:
self.process(self._latest_xas_obj)
......
......@@ -115,7 +115,7 @@ class MbackOW(_ProcessForOrangeMixIn, OWWidget):
Widget used for signal extraction
"""
name = "mback"
id = "orange.widgets.xas.larch.mback"
id = "orange.widgets.xas.larch.mback.MbackOW"
description = "Match mu(E) data for tabulated f''(E) using the MBACK " \
"algorithm and, optionally, the Lee & Xiang extension"
icon = "icons/mback.png"
......
......@@ -48,7 +48,7 @@ from orangecontrib.xas.progress import QProgress
_logger = logging.getLogger(__file__)
class MbackWindow(qt.QMainWindow):
class _PreEdgeWindow(qt.QMainWindow):
def __init__(self, parent=None):
qt.QMainWindow.__init__(self, parent)
......@@ -95,13 +95,16 @@ class MbackWindow(qt.QMainWindow):
self.legendDockWidget.setVisible(viewType is ViewType.spectrum)
self.xasObjViewer._mapView.keySelectionDocker.setVisible(viewType is ViewType.map)
def getNCurves(self):
return len(self.xasObjViewer._spectrumViews[0]._plot.getAllCurves())
class MPreEdgeOW(_ProcessForOrangeMixIn, OWWidget):
class PreEdgeOW(_ProcessForOrangeMixIn, OWWidget):
"""
Widget used for signal extraction
"""
name = "pre edge"
id = "orange.widgets.xas.larch.pre_edge"
id = "orange.widgets.xas.larch.pre_edge.PreEdgeOW"
description = """
pre edge subtraction, normalization for XAFS
This performs a number of steps:
......@@ -131,7 +134,7 @@ class MPreEdgeOW(_ProcessForOrangeMixIn, OWWidget):
def __init__(self):
super().__init__()
self._latest_xas_obj = None
self._window = MbackWindow(parent=self)
self._window = _PreEdgeWindow(parent=self)
layout = gui.vBox(self.mainArea, 'pre edge').layout()
layout.addWidget(self._window)
self._window.xasObjViewer.setWindowTitle('spectra')
......
......@@ -142,7 +142,7 @@ class MbackWindow(qt.QMainWindow):
self.xasObjViewer._mapView.keySelectionDocker.setVisible(viewType is ViewType.map)
class MXFTFOW(_ProcessForOrangeMixIn, OWWidget):
class XFTFOW(_ProcessForOrangeMixIn, OWWidget):
"""
Widget used for signal extraction
"""
......
......@@ -98,6 +98,7 @@ class XASInputOW(OWWidget):
# signal / slot connection
self._startPB.pressed.connect(self._emitNewFile)
self._inputDialog.editingFinished.connect(self._storeSettings)
self.setFileSelected = self._inputDialog.setDatFile
def _emitNewFile(self, *args, **kwargs):
try:
......
......@@ -57,13 +57,16 @@ def process_spectr_autobk(spectrum, configuration, overwrite=True,
_logger.error('Energy and or Mu is/are not specified, unable to '
'compute pre edge')
_conf = configuration
if 'autobk' in _conf:
_conf = _conf['autobk']
opts = {}
for opt_name in ('rbkg', 'nknots', 'e0', 'edge_step', 'kmin', 'kmax',
'kweight', 'dk', 'win', 'k_std', 'chi_std', 'nfft',
'kstep', 'pre_edge_kws', 'nclamp', 'clamp_lo', 'clamp_hi',
'calc_uncertainties', 'err_sigma'):
if opt_name in configuration:
opts[opt_name] = configuration[opt_name]
if opt_name in _conf:
opts[opt_name] = _conf[opt_name]
if _DEBUG is True:
assert isinstance(spectrum, Group)
......
......@@ -63,12 +63,12 @@ class TestLarchSpectrum(unittest.TestCase):
shutil.rmtree(self.outputdir)
def testProcess(self):
self.assertFalse(hasattr(self.spectrum, 'pre_edge'))
self.assertFalse(hasattr(self.spectrum, 'edge'))
self.assertTrue(self.spectrum.pre_edge is None)
self.assertTrue(self.spectrum.e0 is None)
conf, res_spectrum = process_spectr_pre_edge(self.spectrum,
self.configuration)
self.assertTrue(hasattr(res_spectrum, 'pre_edge'))
self.assertTrue(hasattr(res_spectrum, 'edge'))
self.assertTrue(self.spectrum.pre_edge is not None)
self.assertTrue(self.spectrum.e0 is not None)
@unittest.skipIf(has_larch is False, 'xraylarch not installed')
......
......@@ -65,7 +65,6 @@ def process_spectr_xftf(spectrum, configuration, overwrite=True, callback=None,
'window', 'rmax_out', 'nfft', 'kstep'):
if opt_name in _conf:
opts[opt_name] = _conf[opt_name]
if _DEBUG is True:
assert isinstance(spectrum, Group)
if overwrite:
......
......@@ -72,7 +72,6 @@ class TestEXAFSSingleSpectrum(unittest.TestCase):
def testDictAsInput(self):
"""Test succeed if the input is a dict"""
assert 'NormalizedBackground' in self.preproc_input_.spectra[0]
assert 'NormalizedBackground' in self.preproc_input_.spectra[0].extra_keys()
res = pymca_exafs(self.preproc_input_)
self.assertTrue(isinstance(res, XASObject))
self.assertTrue('EXAFSKValues' in res.spectra[0])
......
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2017-2019 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
__authors__ = ["H. Payno"]
__license__ = "MIT"
__date__ = "05/08/2019"
import unittest
# class TestMeldWorkflow_1(unittest.TestCase):
# """
# Test the following workflow: read_xmu -> pymca normalize ->
# """
# def
def suite():
test_suite = unittest.TestSuite()
# TODO: add test melting pymca process and larch process
......
......@@ -25,34 +25,248 @@
"""Tools to defining auto bk parameters"""
__authors__ = ["H. Payno"]
__license__ = "MIT"
__date__ = "05/08/2019"
from silx.gui import qt
# rbkg: distance (in Ang) for chi(R) above
# which the signal is ignored. Default = 1.
# e0: edge energy, in eV. If None, it will be determined.
# edge_step: edge step. If None, it will be determined.
# pre_edge_kws: keyword arguments to pass to pre_edge()
# nknots: number of knots in spline. If None, it will be determined.
# kmin: minimum k value [0]
# kmax: maximum k value [full data range].
# kweight: k weight for FFT. [1]
# dk: FFT window window parameter. [0.1]
# win: FFT window function name. ['hanning']
# nfft: array size to use for FFT [2048]
# kstep: k step size to use for FFT [0.05]
# k_std: optional k array for standard chi(k).
# chi_std: optional chi array for standard chi(k).
# nclamp: number of energy end-points for clamp [2]
# clamp_lo: weight of low-energy clamp [1]
# clamp_hi: weight of high-energy clamp [1]
# calc_uncertaintites: Flag to calculate uncertainties in
# mu_0(E) and chi(k) [True]
# err_sigma: sigma level for uncertainties in mu_0(E) and chi(k) [1]
# TODO: this should be moved in gui module
from xas.gui.larch.utils import _OptionalQDoubleSpinBox, _OptionalQIntSpinBox
import logging
_logger = logging.getLogger(__name__)
class _AutobkParameters(qt.QWidget):
"""
Widget for setting the configuration of the larch 'autobk' process
"""
sigChanged = qt.Signal()
"""Signal emitted when parameters changed"""
# TODO: group it with the xftf windows
_VALID_WINDOWS = ('kaiser', 'hanning', 'parzen', 'welch', 'gaussian', 'sine')
def __init__(self, parent=None):
qt.QWidget.__init__(self, parent)
self.setLayout(qt.QFormLayout())
# rbkg
self._rbkgSB = qt.QSpinBox(parent=self)
self._rbkgSB.setToolTip("distance (in Ang) for chi(R) above which the "
"signal is ignored")
self._rbkgSB.setValue(1)
self.layout().addRow(qt.QLabel('rbkg'), self._rbkgSB)
# e0
self._e0SB = _OptionalQDoubleSpinBox(parent=self)
self._e0SB.setToolTip("edge energy, in eV. If None, it will be "
"determined here.")
self._e0SB.setMinimum(0.0)
self._e0SB.setValue(2000.0)
self._e0SB.setValue(None)
self.layout().addRow(qt.QLabel('e0', parent=self), self._e0SB)
# edge step
self._edgeStepSB = _OptionalQDoubleSpinBox(parent=self)
self._edgeStepSB.setToolTip("edge step. If None, it will be determined.")
self._edgeStepSB.setValue(None)
self.layout().addRow(qt.QLabel('edge step', parent=self), self._edgeStepSB)
# for now we hide the n knots because it is not managed by larch
# # n knots
# self._nknotsSB = _OptionalQIntSpinBox(parent=self)
# self._nknotsSB.setMinimum(1)
# self._nknotsSB.setValue(3)
# self._nknotsSB.setToolTip("number of knots in spline. "
# "If None, it will be determined.")
# self._nknotsSB.setValue(None)
# self.layout().addRow(qt.QLabel('nknots', parent=self), self._nknotsSB)
# kmin
self._kminSB = qt.QSpinBox(parent=self)
self._kminSB.setToolTip("minimum k value.")
self._kminSB.setValue(0)
self.layout().addRow(qt.QLabel('kmin', parent=self), self._kminSB)
# kmax
self._kmaxSB = _OptionalQIntSpinBox(parent=self)
self._kmaxSB.setToolTip("minimum k value.")
self._kmaxSB.setValue(None)
self.layout().addRow(qt.QLabel('kmax', parent=self), self._kmaxSB)
# kweight
# TODO: this should be included in the workflow process
self._kweightSB = qt.QSpinBox(parent=self)
self._kweightSB.setToolTip("k weight")
self._kweightSB.setValue(1)
self.layout().addRow(qt.QLabel('k weight', parent=self), self._kweightSB)
# dk
self._dkSB = qt.QDoubleSpinBox(parent=self)
self._dkSB.setMinimum(0)
self._dkSB.setValue(0.1)
self._dkSB.setToolTip("FFT window window parameter")
self.layout().addRow(qt.QLabel('FFT window parameter', parent=self),
self._dkSB)
# window name
self._windowCB = qt.QComboBox(parent=self)
for winName in self._VALID_WINDOWS:
self._windowCB.addItem(winName)
index = self._windowCB.findText('hanning')
assert index >= 0
self._windowCB.setCurrentIndex(index)
self.layout().addRow(qt.QLabel('fft window type', parent=self),
self._windowCB)
# nfft
self._nfftSB = qt.QSpinBox(parent=self)
self._nfftSB.setMaximum(999999)
self._nfftSB.setValue(2048)
self._nfftSB.setToolTip('value to use for N_fft')
self.layout().addRow(qt.QLabel('N fft', parent=self), self._nfftSB)
# kstep
self._kstepSB = qt.QDoubleSpinBox(parent=self)
self._kstepSB.setToolTip('value to use for delta_k')
self._kstepSB.setValue(0.05)
self._kstepSB.setSingleStep(0.05)
self.layout().addRow(qt.QLabel('k step', parent=self), self._kstepSB)
# nclamp
self._nclampSB = qt.QSpinBox(parent=self)
self._nclampSB.setValue(4)
self._nclampSB.setToolTip('number of energy end-points for clamp')
self.layout().addRow(qt.QLabel('n clamp', parent=self),
self._nclampSB)
# clamp_lo
self._clampLoSB = qt.QSpinBox(parent=self)
self._clampLoSB.setValue(1)
self._clampLoSB.setToolTip('weight of low-energy clamp')
self.layout().addRow(qt.QLabel('clamp low', parent=self),
self._clampLoSB)
# clamp_hi
self._clampHiSB = qt.QSpinBox(parent=self)
self._clampHiSB.setValue(1)
self._clampHiSB.setToolTip('weight of high-energy clamp')
self.layout().addRow(qt.QLabel('clamp high', parent=self),
self._clampHiSB)
# calc uncertainties
self._calcUncertaintiesCB = qt.QCheckBox(parent=self)
self._calcUncertaintiesCB.setChecked(True)
self._calcUncertaintiesCB.setToolTip('alculate uncertainties in '
'mu_0(E) and chi(k)')
self.layout().addRow(qt.QLabel('calculate uncertainties', parent=self),
self._calcUncertaintiesCB)
# err sigma
self._errSignalSB = qt.QSpinBox(parent=self)
self._errSignalSB.setValue(1)
self.layout().addRow(qt.QLabel('sigma uncertainties level', parent=self),
self._errSignalSB)
# expose API
self.getRbkg = self._rbkgSB.value
self.setRbkg = self._rbkgSB.setValue
self.getE0 = self._e0SB.getValue
self.setE0 = self._e0SB.setValue
self.getEdgeStep = self._edgeStepSB.getValue
self.setEdgeStep = self._edgeStepSB.setValue
# self.getKNots = self._nknotsSB.getValue
# self.setKNots = self._nknotsSB.setValue
self.getKMin = self._kminSB.value
self.setKMin = self._kminSB.setValue
self.getKMax = self._kmaxSB.getValue
self.setKMax = self._kmaxSB.setValue
self.getKWeight = self._kweightSB.value
self.setKWeight = self._kweightSB.setValue
self.getDk = self._dkSB.value
self.setDk = self._dkSB.setValue
self.getWindow = self._windowCB.currentText
self.setWindow = self.setWindow
self.getNfft = self._nfftSB.value
self.setNfft = self._nfftSB.setValue
self.getKStep = self._kstepSB.value
self.setKStep = self._kstepSB.setValue
self.getNClamp = self._nclampSB.value
self.setNClamp = self._nclampSB.setValue
self.getClampLow = self._clampLoSB.value
self.setClampLow = self._clampLoSB.setValue
self.getClampHigh = self._clampHiSB.value
self.setClampHigh = self._clampHiSB.setValue
self.isCalcUncertainties = self._calcUncertaintiesCB.isChecked
self.setCalcUncertainties = self._calcUncertaintiesCB.setChecked
self.getSigmaErr = self._errSignalSB.value
self.setSigmaErr = self._errSignalSB.setValue
# connect signal / slots
self._rbkgSB.valueChanged.connect(self._parametersChanged)
self._e0SB.sigChanged.connect(self._parametersChanged)
self._edgeStepSB.sigChanged.connect(self._parametersChanged)
# self._nknotsSB.sigChanged.connect(self._parametersChanged)
self._kminSB.valueChanged.connect(self._parametersChanged)
self._kmaxSB.sigChanged.connect(self._parametersChanged)
self._kweightSB.valueChanged.connect(self._parametersChanged)
self._dkSB.valueChanged.connect(self._parametersChanged)
self._windowCB.currentTextChanged.connect(self._parametersChanged)
self._nfftSB.valueChanged.connect(self._parametersChanged)
self._kstepSB.valueChanged.connect(self._parametersChanged)
self._nclampSB.valueChanged.connect(self._parametersChanged)
self._clampLoSB.valueChanged.connect(self._parametersChanged)
self._clampHiSB.valueChanged.connect(self._parametersChanged)
self._calcUncertaintiesCB.toggled.connect(self._parametersChanged)
self._errSignalSB.valueChanged.connect(self._parametersChanged)
def getParameters(self):
return {}
return {
'rbkg': self.getRbkg(),
'e0': self.getE0(),
'edge_step': self.getEdgeStep(),
# 'nknots': self.getKNots(),
'kmin': self.getKMin(),
'kmax': self.getKMax(),
'kweight': self.getKWeight(),
'dk': self.getDk(),
'win': self.getWindow(),
'nfft': self.getNfft(),
'kstep': self.getKStep(),
'nclamp': self.getNClamp(),
'clamp_lo': self.getClampLow(),
'clamp_hi': self.getClampHigh(),
'calc_uncertaintites': self.isCalcUncertainties(),
'err_sigma': self.getSigmaErr(),
}
def setParameters(self, parameters):
return
assert isinstance(parameters, dict)
for key, value in parameters.items():
if key == 'rbkg':
self.setRbkg(value)
elif key == 'e0':
self.setE0(value)
elif key == 'edge_step':
self.setEdgeStep(value)
elif key == 'knots':
self.setKNots(value)
elif key == 'kmin':
self.setKMin(value)
elif key == 'kmax':
self.setKMax(value)
elif key == 'kweight':
self.setKWeight(value)
elif key == 'dk':
self.setDk(value)
elif key == 'win':
self.setWindow(value)
elif key == 'nfft':
self.setNfft(value)
elif key == 'kstep':
self.setKStep(value)
elif key == 'nclamp':
self.setNClamp(value)
elif key == 'clamp_lo':
self.setClampLow(value)
elif key == 'clamp_hi':
self.setClampHigh(value)
elif key == 'calc_uncertaintites':
self.setCalcUncertainties(value)
elif key == 'err_sigma':
self.setSigmaErr(value)
def setWindow(self, window):
assert window in self._VALID_WINDOWS
index = self._windowCB.findText(window)
if index >= 0:
self._windowCB.setCurrentIndex(index)
else:
_logger.warning(window + ' not found.')
def _parametersChanged(self, *args, **kwargs):
self.sigChanged.emit()
\ No newline at end of file
......@@ -38,7 +38,8 @@ class _MXFTFParameters(qt.QWidget):
sigChanged = qt.Signal()
"""Signal emitted when parameters changed"""
_VALID_WNDOWS = ('kaiser', 'hanning', 'parzen', 'welch', 'gaussian', 'sine')
_VALID_WINDOWS = ('kaiser', 'hanning', 'parzen', 'welch', 'gaussian',
'sine')
def __init__(self, parent=None):
qt.QWidget.__init__(self, parent)
......@@ -62,7 +63,7 @@ class _MXFTFParameters(qt.QWidget):
self.layout().addRow(qt.QLabel('k weight', parent=self), self._kWeightSB)
# dk1
self._dk1SB = qt.QSpinBox(parent=self)
self._dk1SB.setValue(0)
self._dk1SB.setValue(1)
self._dk1SB.setToolTip('tapering parameter for FT Window')
self.layout().addRow(qt.QLabel('dk', parent=self), self._dk1SB)
# dk2
......@@ -78,7 +79,7 @@ class _MXFTFParameters(qt.QWidget):
self.layout().addRow(qt.QLabel('phase', parent=self), self._withPhaseCB)
# window
self._windowCB = qt.QComboBox(parent=self)
for winName in self._VALID_WNDOWS:
for winName in self._VALID_WINDOWS:
self._windowCB.addItem(winName)
index = self._windowCB.findText('kaiser')
assert index >= 0
......@@ -92,6 +93,7 @@ class _MXFTFParameters(qt.QWidget):
self._rmax_outSB)
# nfft
self._nfftSB = qt.QSpinBox(parent=self)
self._nfftSB.setMaximum(999999)
self._nfftSB.setValue(2048)
self._nfftSB.setToolTip('value to use for N_fft')
self.layout().addRow(qt.QLabel('N fft', parent=self), self._nfftSB)
......@@ -99,6 +101,7 @@ class _MXFTFParameters(qt.QWidget):
self._kstepSB = qt.QDoubleSpinBox(parent=self)
self._kstepSB.setToolTip('value to use for delta_k')
self._kstepSB.setValue(0.05)
self._kstepSB.setSingleStep(0.05)
self.layout().addRow(qt.QLabel('k step', parent=self), self._kstepSB)
# expose API
......@@ -135,7 +138,7 @@ class _MXFTFParameters(qt.QWidget):
self._kstepSB.valueChanged.connect(self._valueChanged)
def setWindow(self, window):
assert window in self._VALID_WNDOWS
assert window in self._VALID_WINDOWS
index = self._windowCB.findText(window)
assert index >= 0
self._windowCB.setCurrentIndex(index)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment