ft.py 9.74 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
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/07/2019"


31
32
33
import functools
import logging

payno's avatar
payno committed
34
from Orange.widgets import gui
payno's avatar
payno committed
35
from Orange.widgets.settings import Setting
36
from Orange.widgets.widget import OWWidget
37
38
from Orange.widgets.widget import Input, Output
import Orange.data
payno's avatar
payno committed
39
40
41
from PyMca5.PyMcaGui.physics.xas.XASFourierTransformParameters import (
    XASFourierTransformParameters,
)
42
43
44
from silx.gui import qt
from silx.gui.plot import LegendSelector

payno's avatar
payno committed
45
import est.core.process.pymca.ft
46
from orangecontrib.est.process import _ProcessForOrangeMixIn
payno's avatar
payno committed
47
48
49
50
from est.core.types import XASObject
from est.gui.XasObjectViewer import XasObjectViewer, ViewType
from est.gui.XasObjectViewer import _normalized_exafs, _ft_window_plot
from est.gui.XasObjectViewer import _ft_intensity_plot, _ft_imaginary_plot
payno's avatar
payno committed
51

payno's avatar
payno committed
52
53
from orangecontrib.est.progress import QProgress
from orangecontrib.est.utils import Converter
payno's avatar
payno committed
54
from orangecontrib.est.widgets.container import _ParameterWindowContainer
payno's avatar
payno committed
55

payno's avatar
payno committed
56
57
58
_logger = logging.getLogger(__file__)


payno's avatar
payno committed
59
60
61
class FTWindow(qt.QMainWindow):
    def __init__(self, parent=None):
        qt.QMainWindow.__init__(self, parent)
62
63

        # xas object viewer
payno's avatar
payno committed
64
65
66
        self.xasObjViewer = XasObjectViewer(
            mapKeys=["Mu"], spectrumPlots=("FTWindow", "FTIntensity")
        )
67
        self.xasObjViewer._spectrumViews[0]._plotWidget.getXAxis().setLabel("K")
68

payno's avatar
payno committed
69
70
71
72
73
74
        self.xasObjViewer._spectrumViews[1]._plotWidget.getXAxis().setLabel(
            "R (Angstrom)"
        )
        self.xasObjViewer._spectrumViews[1]._plotWidget.getYAxis().setLabel(
            "Arbitrary Units"
        )
75
        self.setCentralWidget(self.xasObjViewer)
payno's avatar
payno committed
76
77
78
        self._pymcaWindow = _ParameterWindowContainer(
            parent=self, parametersWindow=XASFourierTransformParameters
        )
payno's avatar
payno committed
79
80
        dockWidget = qt.QDockWidget(parent=self)

81
        # pymca window
payno's avatar
payno committed
82
83
84
85
        dockWidget.setWidget(self._pymcaWindow)
        self.addDockWidget(qt.Qt.RightDockWidgetArea, dockWidget)
        dockWidget.setAllowedAreas(qt.Qt.RightDockWidgetArea | qt.Qt.LeftDockWidgetArea)
        dockWidget.setFeatures(qt.QDockWidget.NoDockWidgetFeatures)
86

87
        # legend selectors
payno's avatar
payno committed
88
        self.legendDockWidget1 = LegendSelector.LegendsDockWidget(
89
            parent=self, plot=self.xasObjViewer._spectrumViews[0]._plotWidget
payno's avatar
payno committed
90
91
92
93
        )
        self.legendDockWidget1.setAllowedAreas(
            qt.Qt.RightDockWidgetArea | qt.Qt.LeftDockWidgetArea
        )
94
95
96
        self.legendDockWidget1.setFeatures(qt.QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(qt.Qt.RightDockWidgetArea, self.legendDockWidget1)

payno's avatar
payno committed
97
        self.legendDockWidget2 = LegendSelector.LegendsDockWidget(
98
            parent=self, plot=self.xasObjViewer._spectrumViews[1]._plotWidget
payno's avatar
payno committed
99
100
101
102
        )
        self.legendDockWidget2.setAllowedAreas(
            qt.Qt.RightDockWidgetArea | qt.Qt.LeftDockWidgetArea
        )
103
104
        self.legendDockWidget2.setFeatures(qt.QDockWidget.NoDockWidgetFeatures)
        self.addDockWidget(qt.Qt.RightDockWidgetArea, self.legendDockWidget2)
payno's avatar
payno committed
105

106
        # volume key selection
payno's avatar
payno committed
107
108
109
        self.addDockWidget(
            qt.Qt.RightDockWidgetArea, self.xasObjViewer._mapView.keySelectionDocker
        )
110

111
        # plot settings
112
113
114
        for ope in (_normalized_exafs, _ft_window_plot):
            self.xasObjViewer._spectrumViews[0].addCurveOperation(ope)

115
        for ope in (_ft_intensity_plot, _ft_imaginary_plot):
116
            self.xasObjViewer._spectrumViews[1].addCurveOperation(ope)
117

118
119
120
121
122
123
124
125
        self.setWindowFlags(qt.Qt.Widget)

        # connect signal / slot
        self.xasObjViewer.viewTypeChanged.connect(self._updateLegendView)

        # set up
        self._updateLegendView()

126
127
128
    def getNCurves(self):
        return len(self.plot.getAllCurves())

129
    def _updateLegendView(self):
130
131
132
        index, viewType = self.xasObjViewer.getViewType()
        self.legendDockWidget1.setVisible(viewType is ViewType.spectrum and index == 0)
        self.legendDockWidget2.setVisible(viewType is ViewType.spectrum and index == 1)
payno's avatar
payno committed
133
134
135
        self.xasObjViewer._mapView.keySelectionDocker.setVisible(
            viewType is ViewType.map
        )
136

payno's avatar
payno committed
137

138
class FTOW(_ProcessForOrangeMixIn, ewokstaskclass=est.core.process.pymca.ft.PyMca_ft):
payno's avatar
payno committed
139
140
141
    """
    Widget used for signal extraction
    """
payno's avatar
payno committed
142

payno's avatar
payno committed
143
    name = "fourier transform"
payno's avatar
payno committed
144
    id = "orange.widgets.est.pymca.ft"
145
    description = "Progress fourier transform"
payno's avatar
payno committed
146
    icon = "icons/ft.png"
147
    priority = 4
payno's avatar
payno committed
148
149
150
151
152
    category = "esrfWidgets"
    keywords = ["spectroscopy", "signal", "fourier", "transform", "fourier transform"]

    want_main_area = True
    resizing_enabled = True
153
    allows_cycle = False
payno's avatar
payno committed
154

payno's avatar
payno committed
155
    _pymcaSettings = Setting(dict())
156
157
    # kept for compatibility
    static_input = dict({"ft": None, "xas_obj": None})
payno's avatar
payno committed
158
    """Store the configuration of the PyMca XASClass"""
159
160
161
162
163
164
165
166
167
168
169
    #
    # class Inputs:
    #     xas_obj = Input("xas_obj", XASObject, default=True)
    #     # simple compatibility for some Orange widget and especialy the
    #     # 'spectroscopy add-on'
    #     data_table = Input("Data", Orange.data.Table)
    #
    # class Outputs:
    #     xas_obj = Output("xas_obj", XASObject)
    #     # by default we want to avoid sending 'Orange.data.Table' to avoid
    #     # loosing the XASObject flow process and results.
170

payno's avatar
payno committed
171
172
    def __init__(self):
        super().__init__()
173
        self._latest_xas_obj = None
174
        self._window = FTWindow(parent=self)
payno's avatar
payno committed
175
        layout = gui.vBox(self.mainArea, "fourier transform").layout()
payno's avatar
payno committed
176
177
        layout.addWidget(self._window)

payno's avatar
payno committed
178
        # manage settings
179
180
181
182
183
        pymca_settings = self.static_input.get("ft", None)
        if pymca_settings is None:
            pymca_settings = self._pymcaSettings
        if pymca_settings != dict():
            self._window._pymcaWindow.setParameters(pymca_settings)
payno's avatar
payno committed
184

payno's avatar
payno committed
185
        # signal / slot connection
186
187
        # connect signals / slots
        self._window._pymcaWindow.sigChanged.connect(self._updateProcess)
payno's avatar
payno committed
188

189
        # self.handleNewSignals()
190

payno's avatar
payno committed
191
    def _updateProcess(self, *arv, **kwargs):
payno's avatar
payno committed
192
        self._update_settings()
193
194
        if self._latest_xas_obj:
            self.process(xas_obj=self._latest_xas_obj)
payno's avatar
payno committed
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    #
    # @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
    # def process(self, xas_obj):
    #     if xas_obj is None:
    #         return
    #
    #     if not self._canProcess():
    #         _logger.warning(
    #             "There is some processing on going already, will"
    #             "not process the new dataset"
    #         )
    #
    #     self._latest_xas_obj = xas_obj
    #     self._startProcess()
    #
    #     # setup the ft process
    #     process_obj = QPyMca_ft(inputs={"xas_obj": xas_obj})
    #     process_obj._advancement.sigProgress.connect(self._setProgressValue)
    #     process_obj.set_properties(
    #         {"_pymcaSettings": self._window._pymcaWindow.getParameters()}
    #     )
    #
    #     # update the processing thread
    #     thread = self.getProcessingThread()
    #     thread.init(process_obj=process_obj, xas_obj=self._latest_xas_obj)
    #     self._callback_finish = functools.partial(
    #         self._endProcess, self._latest_xas_obj
    #     )
    #     thread.finished.connect(self._callback_finish)
    #
    #     # start processing
    #     thread.start(priority=qt.QThread.LowPriority)
payno's avatar
payno committed
234

payno's avatar
payno committed
235
236
    def _update_settings(self):
        self._pymcaSettings = self._window._pymcaWindow.getParameters()
237
238
239
240
        self.static_input = {
            "xas_obj": None,
            "ft": self._window._pymcaWindow.getParameters(),
        }
241

242
243
244
    #
    # def _setProgressValue(self, value):
    #     self._progress.widget.progressBarSet(value)
245
246


247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#
# class QPyMca_ft(est.core.process.pymca.ft.PyMca_ft):
#     """
#     Normalization able to give advancement using qt.Signal and QThreadPool
#     """
#
#     def __init__(self, *args, **kwargs):
#         est.core.process.pymca.ft.PyMca_ft.__init__(self, *args, **kwargs)
#         self._advancement = QProgress("normalization")
#
#     def _pool_process(self, xas_obj):
#         self.pool = qt.QThreadPool()
#         self.pool.setMaxThreadCount(5)
#         for spectrum in xas_obj.spectra:
#             runnable = ProcessRunnable(
#                 fct=est.core.process.pymca.ft.process_spectr_ft,
#                 spectrum=spectrum,
#                 configuration=xas_obj.configuration,
#                 callback=self._advancement.increaseAdvancement,
#             )
#             self.pool.start(runnable)
#         self.pool.waitForDone()