k_weight.py 7.01 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
25
26
27
28
29
# 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/07/2019"

30
31
import functools
import logging
payno's avatar
payno committed
32
33

from Orange.widgets import gui
payno's avatar
payno committed
34
from Orange.widgets.settings import Setting
35
from Orange.widgets.widget import OWWidget
36
37
from Orange.widgets.widget import Input, Output
import Orange.data
payno's avatar
payno committed
38
from silx.gui import qt
payno's avatar
payno committed
39
import est.core.process.pymca.k_weight
payno's avatar
payno committed
40
from orangecontrib.est.process import _ProcessForOrangeMixIn, ProcessRunnable
payno's avatar
payno committed
41
42
43
from est.core.types import XASObject
from orangecontrib.est.progress import QProgress
from orangecontrib.est.utils import Converter
payno's avatar
payno committed
44

payno's avatar
payno committed
45
46
47
_logger = logging.getLogger(__file__)


payno's avatar
payno committed
48
49
50
51
class KWeightWindow(qt.QMainWindow):
    def __init__(self, parent=None):
        qt.QMainWindow.__init__(self, parent)

52
        # k wright widget
payno's avatar
payno committed
53
        self._k_widget = qt.QWidget(parent=self)
payno's avatar
payno committed
54
        self._k_widget.setLayout(qt.QHBoxLayout())
payno's avatar
payno committed
55
        self._k_widget.layout().addWidget(qt.QLabel("k weight"))
payno's avatar
payno committed
56
57
58
59
60
61
62
63
        self._k_spin_box = qt.QSpinBox(parent=self)
        self._k_spin_box.setRange(0, 3)
        self._k_widget.layout().addWidget(self._k_spin_box)
        dockWidget = qt.QDockWidget(parent=self)
        dockWidget.setWidget(self._k_widget)
        self.addDockWidget(qt.Qt.RightDockWidgetArea, dockWidget)
        dockWidget.setAllowedAreas(qt.Qt.RightDockWidgetArea | qt.Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(qt.QDockWidget.NoDockWidgetFeatures)
64

65
66
        self.setWindowFlags(qt.Qt.Widget)

payno's avatar
payno committed
67

68
69
class KWeightOW(
    _ProcessForOrangeMixIn,
70
    OWWidget,
71
):
payno's avatar
payno committed
72
73
74
    """
    Widget used for signal extraction
    """
payno's avatar
payno committed
75

payno's avatar
payno committed
76
    name = "k weight"
payno's avatar
payno committed
77
    id = "orange.widgets.est.pymca.k_weight"
78
    description = "Progress k weight"
payno's avatar
payno committed
79
    icon = "icons/k_weight.png"
80
    priority = 2
payno's avatar
payno committed
81
82
83
84
85
    category = "esrfWidgets"
    keywords = ["spectroscopy", "signal", "k", "weight"]

    want_main_area = True
    resizing_enabled = True
86
    allows_cycle = False
87
    ewokstaskclass = est.core.process.pymca.k_weight.PyMca_k_weight
payno's avatar
payno committed
88

payno's avatar
payno committed
89
    _kWeightSetting = Setting(int(3))
90
91
    # kept for compatibility
    static_input = Setting({"xas_obj": None, "k_weight": 3})
payno's avatar
payno committed
92
93
    """Store the configuration of the PyMca XASClass"""

94
    class Inputs:
payno's avatar
payno committed
95
        xas_obj = Input("xas_obj", XASObject, default=True)
96
97
        # simple compatibility for some Orange widget and especialy the
        # 'spectroscopy add-on'
payno's avatar
payno committed
98
        data_table = Input("Data", Orange.data.Table)
99
100

    class Outputs:
101
        xas_obj = Output("xas_obj", XASObject)
102
103
104
        # by default we want to avoid sending 'Orange.data.Table' to avoid
        # loosing the XASObject flow process and results.

payno's avatar
payno committed
105
106
    def __init__(self):
        super().__init__()
107
        self._latest_xas_obj = None
payno's avatar
payno committed
108
        layout = gui.vBox(self.mainArea, "k weight").layout()
payno's avatar
payno committed
109
110
        self._window = KWeightWindow(parent=self)
        layout.addWidget(self._window)
payno's avatar
payno committed
111

112
113
114
        # progress
        self._progress = gui.ProgressBar(self, 100)

payno's avatar
payno committed
115
        # manage settings
116
117
118
119
120
        k_weight = self.static_input.get("k_weight")
        if k_weight == 3:
            k_weight = self._kWeightSetting
        if k_weight != 3:
            self._window._k_spin_box.setValue(k_weight)
payno's avatar
payno committed
121

payno's avatar
payno committed
122
123
124
        # signal / slot connection
        self._window._k_spin_box.valueChanged.connect(self._updateProcess)

125
        # self.handleNewSignals()
126

payno's avatar
payno committed
127
    def _updateProcess(self, *arv, **kwargs):
payno's avatar
payno committed
128
        self._update_settings()
129
130
        if self._latest_xas_obj:
            self.process(self._latest_xas_obj)
payno's avatar
payno committed
131

132
133
134
135
136
137
138
    @Inputs.data_table
    def processFrmDataTable(self, data_table):
        if data_table is None:
            return
        self.process(Converter.toXASObject(data_table=data_table))

    @Inputs.xas_obj
139
140
    def process(self, xas_obj):
        if xas_obj is None:
payno's avatar
payno committed
141
142
            return

143
        if not self._canProcess():
payno's avatar
payno committed
144
145
146
147
            _logger.warning(
                "There is some processing on going already, will"
                "not process the new dataset"
            )
148

149
        self._latest_xas_obj = xas_obj
150
        self._startProcess()
151
152

        # setup the k weight process
153
        process_obj = QPyMca_k_weight(inputs={"xas_obj": xas_obj})
154
        process_obj._advancement.sigProgress.connect(self._setProgressValue)
155
156
157
        process_obj.set_properties(
            {"_kWeightSetting": self._window._k_spin_box.value()}
        )
payno's avatar
payno committed
158

159
160
        # update the processing thread
        thread = self.getProcessingThread()
161
        thread.init(process_obj=process_obj, xas_obj=self._latest_xas_obj)
payno's avatar
payno committed
162
163
164
        self._callback_finish = functools.partial(
            self._endProcess, self._latest_xas_obj
        )
165
166
167
        thread.finished.connect(self._callback_finish)
        # start processing
        thread.start(priority=qt.QThread.LowPriority)
payno's avatar
payno committed
168

payno's avatar
payno committed
169
170
    def _update_settings(self):
        self._kWeightSetting = self._window._k_spin_box.value()
171
172
173
174
        self.static_input = {
            "xas_obj": None,
            "k_weight": self._window._k_spin_box.value(),
        }
175
176
177
178
179

    def _setProgressValue(self, value):
        self._progress.widget.progressBarSet(value)


payno's avatar
payno committed
180
class QPyMca_k_weight(est.core.process.pymca.k_weight.PyMca_k_weight):
181
182
183
    """
    Normalization able to give advancement using qt.Signal and QThreadPool
    """
payno's avatar
payno committed
184

185
186
    def __init__(self, *args, **kwargs):
        est.core.process.pymca.k_weight.PyMca_k_weight.__init__(self, *args, **kwargs)
payno's avatar
payno committed
187
        self._advancement = QProgress("normalization")
188
189
190
191
192

    def _pool_process(self, xas_obj):
        self.pool = qt.QThreadPool()
        self.pool.setMaxThreadCount(5)
        for spectrum in xas_obj.spectra:
payno's avatar
payno committed
193
194
195
196
197
198
199
            assert "KWeight" in xas_obj.configuration
            runnable = ProcessRunnable(
                fct=est.core.process.pymca.k_weight.process_spectr_k,
                spectrum=spectrum,
                configuration=xas_obj.configuration,
                callback=self._advancement.increaseAdvancement,
            )
200
201
            self.pool.start(runnable)
        self.pool.waitForDone()