xftf.py 9.21 KB
Newer Older
payno's avatar
payno committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2016-2017 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.
#
# ###########################################################################*/
25
"""wrapper to the larch xftf process"""
payno's avatar
payno committed
26

payno's avatar
payno committed
27
28
from est.core.types import Spectrum, XASObject
from est.core.process.process import Process
payno's avatar
payno committed
29
from est.core.process.process import _NexusSpectrumDef
30
from est.core.process.process import _NexusDatasetDef
payno's avatar
payno committed
31
from larch.xafs.xafsft import xftf
32
from est.core.utils.symbol import ANGSTROM_CHAR
payno's avatar
payno committed
33
import logging
payno's avatar
payno committed
34
import numpy
payno's avatar
payno committed
35

payno's avatar
payno committed
36
37
38
39
40
41
42
_logger = logging.getLogger(__name__)

_DEBUG = True
if _DEBUG:
    from larch.symboltable import Group


payno's avatar
payno committed
43
44
45
46
47
48
49
50
def process_spectr_xftf(
    spectrum,
    configuration,
    overwrite=True,
    callbacks=None,
    output=None,
    output_dict=None,
):
payno's avatar
payno committed
51
52
    """

53
54
55
56
57
58
59
    :param spectrum: spectrum to process
    :type: :class:`.Spectrum`
    :param configuration: configuration of the pymca normalization
    :type: dict
    :param overwrite: False if we want to return a new Spectrum instance
    :type: bool
    :param callback: callback to execute.
payno's avatar
payno committed
60
61
    :param output: list to store the result, needed for pool processing
    :type: multiprocessing.manager.list
62
63
64
    :param output_dict: key is input spectrum, value is index in the output
                        list.
    :type: dict
payno's avatar
payno committed
65
66
67
    :return: processed spectrum
    :rtype: tuple (configuration, spectrum)
    """
payno's avatar
payno committed
68
    _logger.debug("start xftf on spectrum (%s, %s)" % (spectrum.x, spectrum.y))
payno's avatar
payno committed
69
    assert isinstance(spectrum, Spectrum)
payno's avatar
payno committed
70
71
72
73
74
75
76
77
78
79
    if (
        not hasattr(spectrum, "k")
        or not hasattr(spectrum, "chi")
        or spectrum.k is None
        or spectrum.chi is None
    ):
        _logger.error(
            "k and/or chi is/are not specified, unable to compute "
            "xftf. Maybe you need to run autobk process before ?"
        )
payno's avatar
payno committed
80
        return None, None
81
    _conf = configuration
payno's avatar
payno committed
82
83
    if "xftf" in _conf:
        _conf = _conf["xftf"]
payno's avatar
payno committed
84
    opts = {}
payno's avatar
payno committed
85
86
87
88
89
90
91
92
93
94
95
96
    for opt_name in (
        "kmin",
        "kmax",
        "kweight",
        "dk",
        "dk2",
        "with_phase",
        "window",
        "rmax_out",
        "nfft",
        "kstep",
    ):
97
98
        if opt_name in _conf:
            opts[opt_name] = _conf[opt_name]
payno's avatar
payno committed
99
            if opt_name == "kweight":
100
                opts["kw"] = _conf[opt_name]
payno's avatar
payno committed
101
102
103
104
105
    if _DEBUG is True:
        assert isinstance(spectrum, Group)
    if overwrite:
        _spectrum = spectrum
    else:
106
        _spectrum = Spectrum().load_frm_dict(spectrum.to_dict())
107
    xftf(_spectrum, **opts)
payno's avatar
payno committed
108
    # handle chi(x) * k**k_weight plot with r max
payno's avatar
payno committed
109
110
111
112
113
    if hasattr(_spectrum, "k") and hasattr(_spectrum, "chi"):
        if "kweight" in opts:
            kweight = opts["kweight"]
        else:
            kweight = 0
payno's avatar
payno committed
114
115
116
117
        if (
            "_plot_chi_k_weighted_r_max" in _conf
            and _conf["_plot_chi_k_weighted_r_max"] is not None
        ):
118
            mask = _spectrum.k < _conf["_plot_chi_k_weighted_r_max"]
payno's avatar
payno committed
119
        else:
120
121
122
123
124
            mask = numpy.ones_like(_spectrum.k).astype(numpy.bool)
    _spectrum.masked_chi_weighted_k = _spectrum.chi[mask] * (
        _spectrum.k[mask] ** kweight
    )
    _spectrum.masked_k = _spectrum.k[mask]
payno's avatar
payno committed
125
126
127
    # handle ft plot with r max
    if hasattr(_spectrum, "r") and hasattr(_spectrum, "chir_mag"):
        if "_plot_chi_mag_r_max" in _conf and _conf["_plot_chi_mag_r_max"] is not None:
128
            mask = _spectrum.r < _conf["_plot_chi_mag_r_max"]
payno's avatar
payno committed
129
        else:
130
131
132
            mask = numpy.ones_like(_spectrum.r).astype(numpy.bool)
        _spectrum.masked_chir_mag = _spectrum.chir_mag[mask]
        _spectrum.masked_r = _spectrum.r[mask]
payno's avatar
payno committed
133

134
135
136
    if callbacks:
        for callback in callbacks:
            callback()
payno's avatar
payno committed
137
138
139
140
141
142
143
144
145
146
147
    return configuration, _spectrum


def larch_xftf(xas_obj):
    """

    :param xas_obj: object containing the configuration and spectra to process
    :type: Union[XASObject, dict]
    :return: spectra dict
    :rtype: XASObject
    """
payno's avatar
payno committed
148
149
    mback_obj = Larch_xftf(inputs={"xas_obj": xas_obj})
    return mback_obj.run()
payno's avatar
payno committed
150
151


152
class Larch_xftf(
153
154
155
156
157
    Process,
    name="xftf",
    input_names=["xas_obj"],
    output_names=["xas_obj"],
    optional_input_names=["xftf"],
158
159
160
):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
payno's avatar
payno committed
161
        self._plot_settings = {}
payno's avatar
payno committed
162

163
    def set_properties(self, properties):
payno's avatar
payno committed
164
165
        if "_larchSettings" in properties:
            self._settings = properties["_larchSettings"]
payno's avatar
payno committed
166
167
        if "plot_settings" in properties:
            self._plot_settings = properties["plot_settings"]
payno's avatar
payno committed
168

169
170
    def run(self):
        xas_obj = self.inputs.xas_obj
171
        if xas_obj is None:
172
            raise ValueError("xas_obj should be provided")
payno's avatar
payno committed
173
        _xas_obj = self.getXasObject(xas_obj=xas_obj)
174
175
176
        if self.inputs.xftf:
            self.setConfiguration(self.inputs.xftf)
            _xas_obj.configuration["xftf"] = self.inputs.xftf
payno's avatar
payno committed
177
        elif "xftf" not in _xas_obj.configuration:
178
            self.setConfiguration({})
payno's avatar
payno committed
179
            _xas_obj.configuration["xftf"] = {}
payno's avatar
payno committed
180
181
182
183
184

        self._advancement.reset(max_=_xas_obj.n_spectrum)
        self._advancement.startProcess()
        self._pool_process(xas_obj=_xas_obj)
        self._advancement.endProcess()
payno's avatar
payno committed
185
        self.register_process(
payno's avatar
payno committed
186
187
            _xas_obj,
            data_keys=(
188
189
190
                _NexusDatasetDef(
                    "chir_im",
                    units="{}^(-3)".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
191
                    units_latex=r"\mathring{A}^{-3}",
192
                ),
193
194
                _NexusDatasetDef("chir_re"),
                _NexusDatasetDef(
195
196
                    "chir_mag",
                    units="{}^(-3)".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
197
                    units_latex=r"\mathring{A}^{-3}",
198
199
200
201
                ),
                _NexusDatasetDef(
                    "masked_chir_mag",
                    units="{}".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
202
                    units_latex=r"\mathring{A}",
203
204
                ),
                _NexusDatasetDef(
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
205
                    "r", units="{}".format(ANGSTROM_CHAR), units_latex=r"\mathring{A}"
206
207
208
209
                ),
                _NexusDatasetDef(
                    "masked_r",
                    units="{}".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
210
                    units_latex=r"\mathring{A}",
211
212
213
214
                ),
                _NexusDatasetDef(
                    "k",
                    units="{}^(-1)".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
215
                    units_latex=r"\mathring{A}^{-1}",
216
217
218
219
                ),
                _NexusDatasetDef(
                    "masked_k",
                    units="{}^(-1)".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
220
                    units_latex=r"\mathring{A}^{-1}",
221
222
223
224
                ),
                _NexusDatasetDef(
                    "masked_chi_weighted_k",
                    units="{}^(-2)".format(ANGSTROM_CHAR),
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
225
                    units_latex=r"\mathring{A}^{-2}",
226
                ),
payno's avatar
payno committed
227
228
229
230
231
232
233
            ),
            plots=(
                _NexusSpectrumDef(
                    signal="masked_chi_weighted_k",
                    axes=("masked_k",),
                    auxiliary_signals=None,
                    silx_style={"signal_scale_type": "linear"},
234
                    title="chi(k)*k^k_weight",
Wout De Nolf's avatar
flake8    
Wout De Nolf committed
235
                    title_latex=r"\chi(k).k^{k\_weight}",
payno's avatar
payno committed
236
237
                ),
                _NexusSpectrumDef(
payno's avatar
payno committed
238
239
                    signal="masked_chir_mag",
                    axes=("masked_r",),
payno's avatar
payno committed
240
241
                    auxiliary_signals=None,
                    silx_style={"signal_scale_type": "linear"},
242
                    title="chir_mag",
payno's avatar
payno committed
243
244
                ),
            ),
payno's avatar
payno committed
245
        )
payno's avatar
payno committed
246
        self.outputs.xas_obj = _xas_obj.to_dict()
payno's avatar
payno committed
247
248
249
250
        return _xas_obj

    def _pool_process(self, xas_obj):
        assert isinstance(xas_obj, XASObject)
251
252
253
254
255
256
257
258
259
        n_s = len(xas_obj.spectra.data.flat)
        for i_s, spectrum in enumerate(xas_obj.spectra):
            process_spectr_xftf(
                spectrum=spectrum,
                configuration=xas_obj.configuration,
                callbacks=self.callbacks,
                overwrite=True,
            )
            self.progress = i_s / n_s * 100.0
payno's avatar
payno committed
260
261
262
263
264
265

    def definition(self):
        return "xftf calculation"

    def program_version(self):
        import larch.version
payno's avatar
payno committed
266
267

        return larch.version.version_data()["larch"]
payno's avatar
payno committed
268

269
270
    @staticmethod
    def program_name():
payno's avatar
payno committed
271
        return "larch_xftf"
payno's avatar
payno committed
272

273
    __call__ = run