k_weight.py 6.7 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
90
91
    _kWeightSetting = Setting(int(3))
    """Store the configuration of the PyMca XASClass"""

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

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

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

110
111
112
        # progress
        self._progress = gui.ProgressBar(self, 100)

payno's avatar
payno committed
113
114
115
116
        # manage settings
        if self._kWeightSetting != 3:
            self._window._k_spin_box.setValue(self._kWeightSetting)

payno's avatar
payno committed
117
118
119
        # signal / slot connection
        self._window._k_spin_box.valueChanged.connect(self._updateProcess)

120
        # self.handleNewSignals()
121

payno's avatar
payno committed
122
    def _updateProcess(self, *arv, **kwargs):
payno's avatar
payno committed
123
        self._update_settings()
124
125
        if self._latest_xas_obj:
            self.process(self._latest_xas_obj)
payno's avatar
payno committed
126

127
128
129
130
131
132
133
    @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
134
135
    def process(self, xas_obj):
        if xas_obj is None:
payno's avatar
payno committed
136
137
            return

138
        if not self._canProcess():
payno's avatar
payno committed
139
140
141
142
            _logger.warning(
                "There is some processing on going already, will"
                "not process the new dataset"
            )
143

144
        self._latest_xas_obj = xas_obj
145
        self._startProcess()
146
147

        # setup the k weight process
148
        process_obj = QPyMca_k_weight(inputs={"xas_obj": xas_obj})
149
        process_obj._advancement.sigProgress.connect(self._setProgressValue)
150
151
152
        process_obj.set_properties(
            {"_kWeightSetting": self._window._k_spin_box.value()}
        )
payno's avatar
payno committed
153

154
155
        # update the processing thread
        thread = self.getProcessingThread()
156
        thread.init(process_obj=process_obj, xas_obj=self._latest_xas_obj)
payno's avatar
payno committed
157
158
159
        self._callback_finish = functools.partial(
            self._endProcess, self._latest_xas_obj
        )
160
161
162
        thread.finished.connect(self._callback_finish)
        # start processing
        thread.start(priority=qt.QThread.LowPriority)
payno's avatar
payno committed
163

payno's avatar
payno committed
164
165
    def _update_settings(self):
        self._kWeightSetting = self._window._k_spin_box.value()
166
167
168
169
170

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


payno's avatar
payno committed
171
class QPyMca_k_weight(est.core.process.pymca.k_weight.PyMca_k_weight):
172
173
174
    """
    Normalization able to give advancement using qt.Signal and QThreadPool
    """
payno's avatar
payno committed
175

176
177
    def __init__(self, *args, **kwargs):
        est.core.process.pymca.k_weight.PyMca_k_weight.__init__(self, *args, **kwargs)
payno's avatar
payno committed
178
        self._advancement = QProgress("normalization")
179
180
181
182
183

    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
184
185
186
187
188
189
190
            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,
            )
191
192
            self.pool.start(runnable)
        self.pool.waitForDone()