xas_input.py 9.41 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
25
26
27
28
29
30
# 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.
#
# ###########################################################################*/

__authors__ = ["H. Payno"]
__license__ = "MIT"
__date__ = "06/11/2019"


31
import logging
32
from Orange.widgets import gui
33
from Orange.widgets.settings import Setting
34
from Orange.widgets.widget import OWWidget
35
from Orange.widgets.widget import Output
36
from silx.gui import qt
37
from silx.io.url import DataUrl
payno's avatar
payno committed
38
import est.core.io
39
import est.core.process.ignoreprocess
40
import est.core.process.io
41
from est.gui.xas_object_definition import XASObjectWindow
42
from est.core.types import XASObject
43

44
45
_logger = logging.getLogger(__file__)

payno's avatar
payno committed
46
47
48

_DEBUG = False

49

50
class XASInputOW(
51
    OWWidget,
52
):
53
54
55
    """
    Widget used for signal extraction
    """
payno's avatar
payno committed
56

57
    name = "xas input"
58
    id = "orange.widgets.xas.utils.xas_input"
59
    description = "Read .dat file and convert it to spectra"
60
61
62
63
    icon = "icons/input.png"
    priority = 0
    category = "esrfWidgets"
    keywords = ["spectroscopy", "signal", "input", "file"]
64

65
66
    want_main_area = True
    resizing_enabled = True
67
    allows_cycle = False
68
    ewokstaskclass = est.core.process.io.ReadXasObject
69

70
    _spec_file_setting = Setting(tuple())
71
72
73
    _spectra_url_setting = Setting(str())
    _energy_url_setting = Setting(str())
    _configuration_url_setting = Setting(str())
74
    _dimensions_setting = Setting(tuple())
75
    _energy_unit_settings = Setting(str())
76
77
78
79
    _I0_url_setting = Setting(str())
    _I1_url_setting = Setting(str())
    _I2_url_setting = Setting(str())
    _mu_ref_url_setting = Setting(str())
80

81
    class Outputs:
82
        xas_obj = Output("xas_obj", XASObject)
83
84
85
        # by default we want to avoid sending 'Orange.data.Table' to avoid
        # loosing the XASObject flow process and results.

86
87
88
89
90
    def __init__(self):
        super().__init__()
        self._inputWindow = qt.QWidget(parent=self)
        self._inputWindow.setLayout(qt.QGridLayout())

91
        self._inputDialog = XASObjectWindow(parent=self)
92
        self._inputWindow.layout().addWidget(self._inputDialog, 0, 0, 1, 2)
93

94
95
96
97
98
        # add the apply button
        types = qt.QDialogButtonBox.Ok
        self._buttons = qt.QDialogButtonBox(parent=self)
        self._buttons.setStandardButtons(types)
        self.layout().addWidget(self._buttons)
99

100
101
102
103
        spacer = qt.QWidget(parent=self)
        spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
        self._inputWindow.layout().addWidget(spacer, 2, 0)

payno's avatar
payno committed
104
        layout = gui.vBox(self.mainArea, "input").layout()
105
106
        layout.addWidget(self._inputWindow)

107
108
109
110
        try:
            self._loadSettings()
        except:
            pass
111

112
        # expose api
113
        self.apply = self._emitNewFile
114

115
        # signal / slot connection
116
117
        self._buttons.accepted.connect(self.hide)
        self._buttons.accepted.connect(self._emitNewFile)
118
        self._inputDialog.getMainWindow().editingFinished.connect(self._storeSettings)
119
        self.setFileSelected = self._inputDialog.setDatFile
120

121
        # self.handleNewSignals()
122

123
    def _emitNewFile(self, *args, **kwargs):
124
125
126
        try:
            xas_obj = self._inputDialog.buildXASObject()
        except ValueError as e:
payno's avatar
payno committed
127
            qt.QMessageBox.warning(self, "", str(e))
128
        else:
129
            if _DEBUG is True and xas_obj.n_spectrum > 100:
payno's avatar
payno committed
130
                from est.core.process.roi import ROIProcess, _ROI
payno's avatar
payno committed
131

payno's avatar
payno committed
132
133
134
                roiProcess = ROIProcess()
                roiProcess.setRoi(origin=(0, 0), size=(10, 10))
                xas_obj = roiProcess.process(xas_obj)
135
            self.Outputs.xas_obj.send(xas_obj)
136

137
    def _loadSettings(self):
payno's avatar
payno committed
138
        input_type = est.io.InputType.hdf5_spectra
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

        if len(self._spec_file_setting) == 0:
            input_spec_file = None
            input_energy_col_name = None
            input_abs_col_name = None
            input_monitor_col_name = None
            scan_title = None
        else:
            (
                input_spec_file,
                input_energy_col_name,
                input_abs_col_name,
                input_monitor_col_name,
                scan_title,
            ) = self._spec_file_setting
        if input_spec_file is not None:
            if input_spec_file.endswith(".xmu"):
payno's avatar
payno committed
156
                input_type = est.io.InputType.xmu_spectrum
157
                self._inputDialog.setXmuFile(input_spec_file)
158
            else:
payno's avatar
payno committed
159
                input_type = est.io.InputType.dat_spectrum
160
161
162
163
164
165
166
167
168
                self._inputDialog.setDatFile(input_spec_file)
                if input_energy_col_name is not None:
                    self._inputDialog.setEnergyColName(input_energy_col_name)
                if input_abs_col_name is not None:
                    self._inputDialog.setAbsColName(input_abs_col_name)
                if scan_title is not None:
                    self._inputDialog.setScanTitle(scan_title)
                if input_monitor_col_name is not None:
                    self._inputDialog.setMonitorColName(input_monitor_col_name)
169
170

        def load_url(url_path, setter):
payno's avatar
payno committed
171
            if url_path != "":
172
173
174
                if isinstance(url_path, DataUrl):
                    url = url_path
                else:
175
                    url = DataUrl(url_path)
176
177

                try:
178
179
180
                    if url and url.is_valid():
                        setter(url.path())
                except ... as e:
payno's avatar
payno committed
181
                    logging.info("fail to load ", url_path)
182
183
184
185

        load_url(self._spectra_url_setting, self._inputDialog.setSpectraUrl)
        load_url(self._energy_url_setting, self._inputDialog.setEnergyUrl)
        load_url(self._configuration_url_setting, self._inputDialog.setConfigurationUrl)
186
187
188
189
190
191
192

        advanceHDF5Info = self._inputDialog.getAdvanceHdf5Information()
        load_url(self._I0_url_setting, advanceHDF5Info.setI0Url)
        load_url(self._I1_url_setting, advanceHDF5Info.setI1Url)
        load_url(self._I2_url_setting, advanceHDF5Info.setI2Url)
        load_url(self._mu_ref_url_setting, advanceHDF5Info.setMuRefUrl)

193
194
195
196
        if len(self._dimensions_setting) == 3:
            self._inputDialog.setDimensions(self._dimensions_setting)
        else:
            assert len(self._dimensions_setting) == 0
payno's avatar
payno committed
197
        self._inputDialog.getMainWindow().setEnergyUnit(self._energy_unit_settings)
198
199
200
201
202

        # set up
        self._inputDialog.setCurrentType(input_type)

    def _storeSettings(self):
203
        # handle single file input
204
205
206
207
208
209
210
211
        self._spec_file_setting = (
            self._inputDialog.getMainWindow().getDatFile(),
            self._inputDialog.getMainWindow().getEnergyColName(),
            self._inputDialog.getMainWindow().getAbsColName(),
            self._inputDialog.getMainWindow().getMonitorColName(),
            self._inputDialog.getMainWindow().getScanTitle(),
        )

212
        # handle spectra
213
        spectra_url = self._inputDialog.getMainWindow().getSpectraUrl()
214
215
216
217
        if spectra_url is not None:
            spectra_url = spectra_url.path()
        self._spectra_url_setting = spectra_url
        # handle energy
218
        energy_url = self._inputDialog.getMainWindow().getEnergyUrl()
219
220
221
222
223
        if energy_url is not None:
            assert energy_url.is_valid()
            energy_url = energy_url.path()
        self._energy_url_setting = energy_url
        # handle configuration
224
        configuration_url = self._inputDialog.getMainWindow().getConfigurationUrl()
225
226
227
        if configuration_url is not None:
            configuration_url = configuration_url.path()
        self._configuration_url_setting = configuration_url
228
        # save settings
229
        self._dimensions_setting = self._inputDialog.getMainWindow().getDimensions()
230
        # save energy
payno's avatar
payno committed
231
232
233
        self._energy_unit_settings = str(
            self._inputDialog.getMainWindow().getEnergyUnit()
        )
234
235
        # handle extra information like I0...
        advanceHDF5Info = self._inputDialog.getAdvanceHdf5Information()
236
237
238
239
240
241
242
243
244
245
246
247
        i0_url = advanceHDF5Info.getI0Url()
        if i0_url is not None:
            self._I0_url_setting = i0_url.path()
        i1_url = advanceHDF5Info.getI1Url()
        if i1_url is not None:
            self._I1_url_setting = i1_url.path()
        i2_url = advanceHDF5Info.getI2Url()
        if i2_url is not None:
            self._I2_url_setting = i2_url.path()
        mu_ref_url = advanceHDF5Info.getMuRefUrl()
        if mu_ref_url is not None:
            self._mu_ref_url_setting = mu_ref_url.path()
248
249
250

    def sizeHint(self):
        return qt.QSize(400, 200)