diff --git a/doc/tutorials/example_larch.ows b/doc/tutorials/example_larch.ows index 7e792a797a21c3fe146f1ec69551236ff69ffbb8..fa486c15f5b2c8ff87b47c727a0e329959af4a87 100644 --- a/doc/tutorials/example_larch.ows +++ b/doc/tutorials/example_larch.ows @@ -8,10 +8,10 @@ - - - - + + + + A File widget. Double click to open it and select the dataset file. diff --git a/doc/tutorials/example_pymca.ows b/doc/tutorials/example_pymca.ows index a41e2a5a973e1e3cbb63513d3b864c7f6343011f..2f498e624798d46dcf30f3c7ad0d86f4c478dcda 100644 --- a/doc/tutorials/example_pymca.ows +++ b/doc/tutorials/example_pymca.ows @@ -9,11 +9,11 @@ - - - - - + + + + + A File widget. Double click to open it and select the dataset file. diff --git a/orangecontrib/xas/process.py b/orangecontrib/xas/process.py index a7d535194ba9c220141c5e7c40b7463420e47736..3bc1d51d160e934bafcc3e213ec32731d861655e 100644 --- a/orangecontrib/xas/process.py +++ b/orangecontrib/xas/process.py @@ -37,11 +37,13 @@ _logger = logging.getLogger(__file__) class _ProcessForOrangeMixIn(object): """ - Group processing and progress display in a common class for pymca process. + Group processing and progress display in a common class for xasObject + process. If this process own a widget to display the xas object then this one should be named '_window' """ + def __init__(self): # progress self._progress = gui.ProgressBar(self, 100) @@ -73,7 +75,7 @@ class _ProcessForOrangeMixIn(object): if hasattr(self, '_window') and hasattr(self._window, 'xasObjViewer'): self._window.xasObjViewer.setXASObj(xas_obj=xas_obj) # emit signal for the plot - self.send("spectra", xas_obj) + self.Outputs.res_xas_obj.send(xas_obj) def _canProcess(self): return self.__processingThread is None or not self.__processingThread.isRunning() diff --git a/orangecontrib/xas/test/test_larch_workflow.py b/orangecontrib/xas/test/test_larch_workflow.py index c39e835f8f6443c3bb5bde5c7a9da572f07e56ee..41fc0b7239755735030f82c4066ee019900a2bf4 100644 --- a/orangecontrib/xas/test/test_larch_workflow.py +++ b/orangecontrib/xas/test/test_larch_workflow.py @@ -88,11 +88,11 @@ class TestSimpleLarchWorkflow(OrangeWorflowTest): cls.processOrangeEvents(cls) - cls.link(cls, xasInputNode, "spectra", xasPreEdgeNode, "spectra") - cls.link(cls, xasPreEdgeNode, "spectra", xasAutobkNode, "spectra") - cls.link(cls, xasAutobkNode, "spectra", xasXFTFNode, "spectra") - cls.link(cls, xasXFTFNode, "spectra", xasMBackNormNode, "spectra") - cls.link(cls, xasMBackNormNode, "spectra", xasOutputNode, "spectra") + cls.link(cls, xasInputNode, "xas_obj", xasPreEdgeNode, "xas_obj") + cls.link(cls, xasPreEdgeNode, "xas_obj", xasAutobkNode, "xas_obj") + cls.link(cls, xasAutobkNode, "xas_obj", xasXFTFNode, "xas_obj") + cls.link(cls, xasXFTFNode, "xas_obj", xasMBackNormNode, "xas_obj") + cls.link(cls, xasMBackNormNode, "xas_obj", xasOutputNode, "xas_obj") cls.processOrangeEvents(cls) cls.xasInputWidget = cls.getWidgetForNode(cls, xasInputNode) diff --git a/orangecontrib/xas/test/test_pymca_workflow.py b/orangecontrib/xas/test/test_pymca_workflow.py index cb53c13ab3628783987c48fb952bfd23dd826ae0..fad06fce1dc64d5cd2b81cb0882be0c8fa3bcd92 100644 --- a/orangecontrib/xas/test/test_pymca_workflow.py +++ b/orangecontrib/xas/test/test_pymca_workflow.py @@ -86,11 +86,11 @@ class TestSimplePyMcaWorkflow(OrangeWorflowTest): cls.processOrangeEvents(cls) - cls.link(cls, xasInputNode, "spectra", xasNormalizationNode, "spectra") - cls.link(cls, xasNormalizationNode, "spectra", xasEXAFSNode, "spectra") - cls.link(cls, xasEXAFSNode, "spectra", xasKWeightNode, "spectra") - cls.link(cls, xasKWeightNode, "spectra", xasFTNode, "spectra") - cls.link(cls, xasFTNode, "spectra", xasOutputNode, "spectra") + cls.link(cls, xasInputNode, "xas_obj", xasNormalizationNode, "xas_obj") + cls.link(cls, xasNormalizationNode, "xas_obj", xasEXAFSNode, "xas_obj") + cls.link(cls, xasEXAFSNode, "xas_obj", xasKWeightNode, "xas_obj") + cls.link(cls, xasKWeightNode, "xas_obj", xasFTNode, "xas_obj") + cls.link(cls, xasFTNode, "xas_obj", xasOutputNode, "xas_obj") cls.processOrangeEvents(cls) cls.xasInputWidget = cls.getWidgetForNode(cls, xasInputNode) diff --git a/orangecontrib/xas/utils/converter.py b/orangecontrib/xas/utils/converter.py index 12649f72f7c34323e50cbdfe9c1901c1f1877389..3f8747776357ecd5be1330519201b54d89868d83 100644 --- a/orangecontrib/xas/utils/converter.py +++ b/orangecontrib/xas/utils/converter.py @@ -51,6 +51,10 @@ class Converter(object): @staticmethod def toDataTable(xas_object): + _logger.warning('casting xas_object to Orange.data.Table might bring ' + 'lost of some information (process flow, ' + 'treatment result...). Only keep energy and absorbed ' + 'beam information') spectra = XASObject._spectra_volume(xas_object.spectra, key='mu', dim_1=xas_object.dim1, diff --git a/orangecontrib/xas/widgets/larch/autobk.py b/orangecontrib/xas/widgets/larch/autobk.py index 68c2384c2237e2440e36dc55369f64a8fbbe3632..240418943f2c9c848f9a9382dbf154f5faa54c6f 100644 --- a/orangecontrib/xas/widgets/larch/autobk.py +++ b/orangecontrib/xas/widgets/larch/autobk.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt from silx.gui.plot import LegendSelector import xas.core.process.larch.autobk @@ -42,6 +44,7 @@ from xas.core.types import XASObject, Spectrum from xas.gui.XasObjectViewer import XasObjectViewer, _CurveOperation, ViewType from xas.gui.larch.autobk import _AutobkParameters from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -139,15 +142,22 @@ class AutobkOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.larch.autobk.Larch_autobk _settings = Setting(dict()) """Store the configuration of the PyMca XASClass""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -172,6 +182,13 @@ class AutobkOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._settings = self._window._parametersWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/larch/mback.py b/orangecontrib/xas/widgets/larch/mback.py index 37b742a5a63b36022205e5339da03c7fbaa56863..e0fa47324e04a94659138234f7952e6a565e2f95 100644 --- a/orangecontrib/xas/widgets/larch/mback.py +++ b/orangecontrib/xas/widgets/larch/mback.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt from silx.gui.plot import LegendSelector import xas.core.process.larch.mback @@ -43,6 +45,7 @@ from xas.gui.XasObjectViewer import XasObjectViewer, ViewType from xas.gui.larch.mback import _MBackParameters from orangecontrib.xas.progress import QProgress from xas.gui.XasObjectViewer import _plot_norm, _plot_raw, _plot_fpp, _plot_f2 +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -115,15 +118,22 @@ class MbackOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.larch.mback.Larch_mback _larchSettings = Setting(dict()) """Store the configuration of the larch configuration""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -147,6 +157,13 @@ class MbackOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._larchSettings = self._window._parametersWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/larch/mback_norm.py b/orangecontrib/xas/widgets/larch/mback_norm.py index 37bf74ff702cb6826e27146727bec7ca2e5b69d7..f71abd104d7542f87037f8228268120e7e220910 100644 --- a/orangecontrib/xas/widgets/larch/mback_norm.py +++ b/orangecontrib/xas/widgets/larch/mback_norm.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt from silx.gui.plot import LegendSelector import xas.core.process.larch.mback_norm @@ -43,6 +45,7 @@ from xas.gui.XasObjectViewer import XasObjectViewer, ViewType from xas.gui.XasObjectViewer import _plot_norm, _plot_mback_mu from xas.gui.larch.mback import _MBackParameters from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -115,15 +118,22 @@ class Mback_normOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.larch.mback_norm.Larch_mback_norm _larchSettings = Setting(dict()) """Store the configuration of the larch configuration""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -147,6 +157,13 @@ class Mback_normOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._larchSettings = self._window._parametersWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/larch/pre_edge.py b/orangecontrib/xas/widgets/larch/pre_edge.py index 541238381ecbf849344fbcc41c8fcf03976e635e..e37dcc0059b54282dcfe3f00b7646bd495e1253c 100644 --- a/orangecontrib/xas/widgets/larch/pre_edge.py +++ b/orangecontrib/xas/widgets/larch/pre_edge.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt from silx.gui.plot import LegendSelector import xas.core.process.larch.pre_edge @@ -44,6 +46,7 @@ from xas.gui.XasObjectViewer import (_plot_edge, _plot_norm, _plot_norm_area, _plot_post_edge, _plot_pre_edge) from xas.gui.larch.pre_edge import _MPreEdgeParameters from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -125,15 +128,22 @@ class PreEdgeOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.larch.pre_edge.Larch_pre_edge _larchSettings = Setting(dict()) """Store the configuration of the larch configuration""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -157,6 +167,13 @@ class PreEdgeOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._larchSettings = self._window._parametersWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/larch/xftf.py b/orangecontrib/xas/widgets/larch/xftf.py index 4749348801f2bf0d00690954d0e5078c87077d85..c44b845f38dcf7cb7722fa79bdafac0eff509e8d 100644 --- a/orangecontrib/xas/widgets/larch/xftf.py +++ b/orangecontrib/xas/widgets/larch/xftf.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt from silx.gui.plot import LegendSelector import xas.core.process.larch.xftf @@ -42,6 +44,7 @@ from xas.core.types import XASObject, Spectrum from xas.gui.XasObjectViewer import XasObjectViewer, _CurveOperation, ViewType from xas.gui.larch.xftf import _MXFTFParameters from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -163,15 +166,22 @@ class XFTFOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.larch.xftf.Larch_xftf _larchSettings = Setting(dict()) """Store the configuration of the larch configuration""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -195,6 +205,13 @@ class XFTFOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._larchSettings = self._window._parametersWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/pymca/exafs.py b/orangecontrib/xas/widgets/pymca/exafs.py index 9acf5992eee78a6b8d187d0f7bc0e74cb56e7510..38b5437e9b8d5669bc455fd7b1b9109e27583f18 100644 --- a/orangecontrib/xas/widgets/pymca/exafs.py +++ b/orangecontrib/xas/widgets/pymca/exafs.py @@ -34,6 +34,9 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data +from xas.core.types import XASObject from PyMca5.PyMcaGui.physics.xas.XASPostEdgeParameters import \ XASPostEdgeParameters from silx.gui import qt @@ -42,9 +45,11 @@ from silx.gui.plot import LegendSelector import xas.core.process.pymca.exafs from orangecontrib.xas.process import _ProcessForOrangeMixIn, \ ProcessRunnable -from xas.core.types import XASObject, Spectrum +from xas.core.types import Spectrum from xas.gui.XasObjectViewer import XasObjectViewer, _CurveOperation, ViewType from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter + _logger = logging.getLogger(__file__) @@ -165,14 +170,22 @@ class ExafsOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.pymca.exafs.PyMca_exafs _larchSettings = Setting(dict()) """Store the configuration of the PyMca XASClass""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -199,6 +212,13 @@ class ExafsOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._larchSettings = self._window._pymcaWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/pymca/ft.py b/orangecontrib/xas/widgets/pymca/ft.py index 89ddcc0bf003371ddd0b77e124e9ebefbaf0d846..aa14074b9c8f8befde87b67897c20d4ba99c99c3 100644 --- a/orangecontrib/xas/widgets/pymca/ft.py +++ b/orangecontrib/xas/widgets/pymca/ft.py @@ -34,6 +34,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from PyMca5.PyMcaGui.physics.xas.XASFourierTransformParameters import \ XASFourierTransformParameters from silx.gui import qt @@ -45,6 +47,7 @@ from orangecontrib.xas.process import _ProcessForOrangeMixIn, \ from xas.core.types import XASObject, Spectrum from xas.gui.XasObjectViewer import XasObjectViewer, _CurveOperation, ViewType from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -189,14 +192,22 @@ class FTOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.pymca.ft.PyMca_ft _pymcaSettings = Setting(dict()) """Store the configuration of the PyMca XASClass""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -219,6 +230,13 @@ class FTOW(_ProcessForOrangeMixIn, OWWidget): if self._latest_xas_obj: self.process(xas_obj=self._latest_xas_obj) + @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 diff --git a/orangecontrib/xas/widgets/pymca/k_weight.py b/orangecontrib/xas/widgets/pymca/k_weight.py index e58d31725349d0a2baed1f6c324f18ce2ebb1743..d2c6b76123989890569ef6b5eb4823ec7f2cba66 100644 --- a/orangecontrib/xas/widgets/pymca/k_weight.py +++ b/orangecontrib/xas/widgets/pymca/k_weight.py @@ -33,6 +33,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from silx.gui import qt import xas.core.process.pymca.k_weight @@ -40,6 +42,7 @@ from orangecontrib.xas.process import _ProcessForOrangeMixIn, \ ProcessRunnable from xas.core.types import XASObject from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -79,14 +82,22 @@ class KWeightOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.pymca.k_weight.PyMca_k_weight _kWeightSetting = Setting(int(3)) """Store the configuration of the PyMca XASClass""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -109,6 +120,13 @@ class KWeightOW(_ProcessForOrangeMixIn, OWWidget): if self._latest_xas_obj: self.process(self._latest_xas_obj) + @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 diff --git a/orangecontrib/xas/widgets/pymca/normalization.py b/orangecontrib/xas/widgets/pymca/normalization.py index 7dbce4dd2b08d4be10d66b9716aa7f20d4737f16..557d9dcad66daacfb6dc55f0f3f68e6b90f355d3 100644 --- a/orangecontrib/xas/widgets/pymca/normalization.py +++ b/orangecontrib/xas/widgets/pymca/normalization.py @@ -34,6 +34,8 @@ import logging from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data from PyMca5.PyMcaGui.physics.xas.XASNormalizationParameters import \ XASNormalizationParameters from silx.gui import qt @@ -46,6 +48,7 @@ from orangecontrib.xas.process import ProcessRunnable from xas.core.types import XASObject from xas.gui.XasObjectViewer import XasObjectViewer, ViewType from orangecontrib.xas.progress import QProgress +from orangecontrib.xas.utils import Converter _logger = logging.getLogger(__file__) @@ -116,15 +119,22 @@ class NormalizationOW(_ProcessForOrangeMixIn, OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, "process")] - - outputs = [("spectra", XASObject), ("curves", tuple)] - process_function = xas.core.process.pymca.normalization.PyMca_normalization _pymcaSettings = Setting(dict()) """Store the configuration of the PyMca XASClass""" + 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: + res_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. + def __init__(self): super().__init__() self._latest_xas_obj = None @@ -152,6 +162,13 @@ class NormalizationOW(_ProcessForOrangeMixIn, OWWidget): def _update_settings(self): self._pymcaSettings = self._window._pymcaWindow.getParameters() + @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 diff --git a/orangecontrib/xas/widgets/utils/converter.py b/orangecontrib/xas/widgets/utils/converter.py new file mode 100644 index 0000000000000000000000000000000000000000..684ed625b74cd9ae5c13e00eeb597a044817a7d7 --- /dev/null +++ b/orangecontrib/xas/widgets/utils/converter.py @@ -0,0 +1,69 @@ +# 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__ = "08/08/2019" + + +from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +from xas.core.types import XASObject +from orangecontrib.xas.utils import Converter +import Orange.data + + +class ConverterOW(OWWidget): + """ + Offer a conversion from XASObject to Orange.data.Table, commonly used + from Orange widget + """ + name = "converter xas_obj -> Table" + id = "orange.widgets.xas.utils.converter" + description = "convert a XASObject to a Orange.data.Table" + icon = "icons/converter.png" + priority = 5 + category = "esrfWidgets" + keywords = ["spectroscopy", "signal", "output", "file"] + + want_main_area = False + resizing_enabled = False + + class Inputs: + xas_obj = Input('xas_obj', XASObject, default=True) + # simple compatibility for some Orange widget and especialy the + # 'spectroscopy add-on' + + class Outputs: + res_data_table = Output('Data', Orange.data.Table) + # by default we want to avoid sending 'Orange.data.Table' to avoid + # loosing the XASObject flow process and results. + + @Inputs.xas_obj + def process(self, xas_object): + if xas_object is None: + return + data_table = Converter.toDataTable(xas_object=xas_object) + self.Outputs.res_data_table.send(data_table) \ No newline at end of file diff --git a/orangecontrib/xas/widgets/utils/icons/converter.png b/orangecontrib/xas/widgets/utils/icons/converter.png new file mode 100644 index 0000000000000000000000000000000000000000..50aca4d2d95b990a92b0e7e4839f732a74a509dd Binary files /dev/null and b/orangecontrib/xas/widgets/utils/icons/converter.png differ diff --git a/orangecontrib/xas/widgets/utils/icons/converter.svg b/orangecontrib/xas/widgets/utils/icons/converter.svg new file mode 100644 index 0000000000000000000000000000000000000000..23b7bd5de690f8e0ad89eecf32164371b1752d5c --- /dev/null +++ b/orangecontrib/xas/widgets/utils/icons/converter.svg @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/orangecontrib/xas/widgets/utils/roi.py b/orangecontrib/xas/widgets/utils/roi.py index ef373b61ec77031e2ca69240fd29125fa28460c3..02742c7c60a1504780f254872ab7a2ba3cfe0834 100644 --- a/orangecontrib/xas/widgets/utils/roi.py +++ b/orangecontrib/xas/widgets/utils/roi.py @@ -29,10 +29,12 @@ __date__ = "02/10/2018" import logging -from Orange.canvas.registry.description import InputSignal, OutputSignal from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Input, Output +import Orange.data +from orangecontrib.xas.utils import Converter from silx.gui import qt import xas.core.process.roi @@ -57,9 +59,6 @@ class RoiSelectionOW(OWWidget): category = "esrfWidgets" keywords = ["dataset", "data", "selection", "ROI", "Region of Interest"] - inputs = [InputSignal(name="spectra", type=XASObject, handler='process')] - outputs = [OutputSignal(name="spectra", type=XASObject)] - process_function = xas.core.process.roi.ROIProcess want_main_area = True @@ -69,6 +68,17 @@ class RoiSelectionOW(OWWidget): _roi_origin = Setting(tuple()) _roi_size = Setting(tuple()) + 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: + res_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. + def __init__(self): super().__init__() @@ -89,6 +99,13 @@ class RoiSelectionOW(OWWidget): self.setROI = self._widget.setROI self.getROI = self._widget.getROI + @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 @@ -112,7 +129,7 @@ class RoiSelectionOW(OWWidget): # we want to keep the raw data in roi object, to be able to resize # the roi (especially increase it size) xas_obj = roi_process.process(xas_obj=self._widget.getXasObject().copy()) - self.send("spectra", xas_obj) + self.Outputs.res_xas_obj.send(xas_obj) except Exception as e: _logger.error(e) else: diff --git a/orangecontrib/xas/widgets/utils/xas_input.py b/orangecontrib/xas/widgets/utils/xas_input.py index 37357a9dfb9c7524afe8d3d0c7b0bf304b082128..76ca5f0c7e45983cac5f89b1a1e5b5c789af194e 100644 --- a/orangecontrib/xas/widgets/utils/xas_input.py +++ b/orangecontrib/xas/widgets/utils/xas_input.py @@ -34,6 +34,7 @@ import os from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import Output from silx.gui import qt from silx.io.url import DataUrl @@ -62,8 +63,6 @@ class XASInputOW(OWWidget): want_main_area = True resizing_enabled = True - outputs = [("spectra", XASObject)] - _input_file_setting = Setting(str()) _spectra_url_setting = Setting(str()) _energy_url_setting = Setting(str()) @@ -71,6 +70,11 @@ class XASInputOW(OWWidget): process_function = xas.core.io.read_frm_file + class Outputs: + res_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. + def __init__(self): super().__init__() self._inputWindow = qt.QWidget(parent=self) @@ -111,7 +115,7 @@ class XASInputOW(OWWidget): roiProcess = ROIProcess() roiProcess.setRoi(origin=(0, 0), size=(10, 10)) xas_obj = roiProcess.process(xas_obj) - self.send("spectra", xas_obj) + self.Outputs.res_xas_obj.send(xas_obj) def _manageSettings(self): input_type = xas.io.InputType.hdf5_spectra diff --git a/orangecontrib/xas/widgets/utils/xas_output.py b/orangecontrib/xas/widgets/utils/xas_output.py index 43aaf00b038569209a2bf0aeb2b31f817555052e..1cb975e907aadd5193097cbb9c5232b0fa3ef09e 100644 --- a/orangecontrib/xas/widgets/utils/xas_output.py +++ b/orangecontrib/xas/widgets/utils/xas_output.py @@ -30,8 +30,9 @@ __date__ = "06/11/2019" from Orange.widgets import gui from Orange.widgets.widget import OWWidget -from silx.gui import qt from Orange.widgets.settings import Setting +from Orange.widgets.widget import Input +from silx.gui import qt from xas.core.types import XASObject import xas.core.io import logging @@ -54,11 +55,12 @@ class XASOutputOW(OWWidget): want_main_area = True resizing_enabled = True - inputs = [("spectra", XASObject, 'process')] - _output_file_setting = Setting(str()) process_function = xas.core.io.XASWriter + class Inputs: + xas_obj = Input('xas_obj', XASObject, default=True) + def __init__(self): super().__init__() self._outputWindow = qt.QWidget(parent=self) @@ -114,6 +116,7 @@ class XASOutputOW(OWWidget): def _getFileSelected(self): return self._inputLe.text() + @Inputs.xas_obj def process(self, xas_obj): if xas_obj is None: return diff --git a/xas/pushworkflowactors/test/test_workflow.py b/xas/pushworkflowactors/test/test_workflow.py index c028341599c2727ae5ef9151f3c8c900848208c1..d097aa32be7f2437aa240dc769e12f0fb23effab 100644 --- a/xas/pushworkflowactors/test/test_workflow.py +++ b/xas/pushworkflowactors/test/test_workflow.py @@ -66,14 +66,14 @@ class TestWorkflowFunctions(unittest.TestCase): read_task, normalization_task, exafs_task, k_weight_task, ft_task) links = [ - Link(source_node=read_task, source_channel='spectra', - sink_node=normalization_task, sink_channel='spectra'), - Link(source_node=normalization_task, source_channel='spectra', - sink_node=exafs_task, sink_channel='spectra'), - Link(source_node=exafs_task, source_channel='spectra', - sink_node=k_weight_task, sink_channel='spectra'), - Link(source_node=k_weight_task, source_channel='spectra', - sink_node=ft_task, sink_channel='spectra'), + Link(source_node=read_task, source_channel='xas_obj', + sink_node=normalization_task, sink_channel='xas_obj'), + Link(source_node=normalization_task, source_channel='xas_obj', + sink_node=exafs_task, sink_channel='xas_obj'), + Link(source_node=exafs_task, source_channel='xas_obj', + sink_node=k_weight_task, sink_channel='xas_obj'), + Link(source_node=k_weight_task, source_channel='xas_obj', + sink_node=ft_task, sink_channel='xas_obj'), ] self.scheme = Scheme(nodes=nodes, links=links)