mback_norm.py 6.03 KB
Newer Older
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 mback-norm process"""
26

payno's avatar
payno committed
27
28
from est.core.types import Spectrum, XASObject
from est.core.process.process import Process
29
from est.core.process.process import _NexusDatasetDef
30
from larch.xafs.mback import mback_norm
31
from larch.xafs.pre_edge import preedge
32
import logging
payno's avatar
payno committed
33

34
35
36
37
38
39
40
_logger = logging.getLogger(__name__)

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


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

51
52
53
54
55
56
57
    :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.
58
59
    :param output: list to store the result, needed for pool processing
    :type: multiprocessing.manager.list
60
61
62
    :param output_dict: key is input spectrum, value is index in the output
                        list.
    :type: dict
63
64
65
    :return: processed spectrum
    :rtype: tuple (configuration, spectrum)
    """
payno's avatar
payno committed
66
    _logger.debug("start mback_norm on spectrum (%s, %s)" % (spectrum.x, spectrum.y))
67
    assert isinstance(spectrum, Spectrum)
payno's avatar
payno committed
68
69
70
71
72
    if not hasattr(spectrum, "norm"):
        _logger.error(
            "spectrum doesn't have norm. Maybe you meed to compute "
            "pre_edge first? Unable to compute mback_norm."
        )
73
        return None, None
payno's avatar
payno committed
74
75
76
77
78
    if not hasattr(spectrum, "pre_edge"):
        _logger.error(
            "spectrum doesn't have norm. Maybe you meed to compute "
            "pre_edge first? Unable to compute mback_norm."
        )
79
80
        return None, None

81
    _conf = configuration
payno's avatar
payno committed
82
83
    if "mback_norm" in _conf:
        _conf = _conf["mback_norm"]
84
    opts = {}
85
86
87
88
89
90
91
92
93

    if _DEBUG is True:
        assert isinstance(spectrum, Group)
    if overwrite:
        _spectrum = spectrum
    else:
        _spectrum = Spectrum().load_frm_dict(spectrum.to_dict())
    # TODO: computing each time preedge should be avoidable
    pre_edge_details = preedge(_spectrum.energy, _spectrum.mu)
payno's avatar
payno committed
94
95
96
97
98
99
100
101
102
103
104
    for opt_name in (
        "z",
        "edge",
        "e0",
        "pre1",
        "pre2",
        "norm1",
        "norm2",
        "nnorm",
        "nvict",
    ):
105
106
        if opt_name in _conf:
            opts[opt_name] = _conf[opt_name]
107
108
        elif pre_edge_details is not None and opt_name in pre_edge_details:
            opts[opt_name] = pre_edge_details[opt_name]
109
110

    mback_norm(_spectrum, group=_spectrum, **opts)
111
112
113
    if callbacks:
        for callback in callbacks:
            callback()
114
115
116
117
118
119
120
121
122
123
124
    return configuration, _spectrum


def larch_mback_norm(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
125
126
    mback_obj = Larch_mback_norm(inputs={"xas_obj": xas_obj})
    return mback_obj.run()
127

payno's avatar
payno committed
128

129
class Larch_mback_norm(
130
131
132
133
134
    Process,
    name="mback_norm",
    input_names=["xas_obj"],
    output_names=["xas_obj"],
    optional_input_names=["mback_norm"],
135
):
136
    def set_properties(self, properties):
payno's avatar
payno committed
137
138
        if "_larchSettings" in properties:
            self._settings = properties["_larchSettings"]
139

140
141
    def run(self):
        xas_obj = self.inputs.xas_obj
142
        if xas_obj is None:
143
            raise ValueError("xas_obj should be provided")
144
        _xas_obj = self.getXasObject(xas_obj=xas_obj)
145
146
147
        if self.inputs.mback_norm:
            self.setConfiguration(self.inputs.mback_norm)
            _xas_obj.configuration["mback_norm"] = self.inputs.mback_norm
148

149
        self.progress = 0.0
150
        self._pool_process(xas_obj=_xas_obj)
151
        self.progress = 100.0
152
153
154
155
        data_keys = [
            _NexusDatasetDef("mback_mu"),
            _NexusDatasetDef("norm_mback"),
        ]
payno's avatar
payno committed
156
157
        if _xas_obj.n_spectrum > 0 and hasattr(_xas_obj.spectra[0], "edge_step"):
            data_keys += ["norm"]
158
        self.register_process(_xas_obj, data_keys=data_keys)
159
        self.outputs.xas_obj = _xas_obj.to_dict()
160
161
162
163
        return _xas_obj

    def _pool_process(self, xas_obj):
        assert isinstance(xas_obj, XASObject)
164
165
166
167
168
169
170
171
172
        n_s = len(xas_obj.spectra.data.flat)
        for i_s, spectrum in enumerate(xas_obj.spectra):
            process_spectr_mback_norm(
                spectrum=spectrum,
                configuration=xas_obj.configuration,
                callbacks=self.callbacks,
                overwrite=True,
            )
            self.progress = i_s / n_s * 100.0
173
174
175
176
177
178

    def definition(self):
        return "mback norm calculation"

    def program_version(self):
        import larch.version
payno's avatar
payno committed
179
180

        return larch.version.version_data()["larch"]
181

182
183
    @staticmethod
    def program_name():
payno's avatar
payno committed
184
        return "larch_mback_norm"
185

186
    __call__ = run