tomwer 1.2.0a1__py3-none-any.whl → 1.2.0a3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orangecontrib/tomwer/tutorials/append_raw_darks_and_flats_frames_to_NXtomos.ows +44 -0
- orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth1.ows +55 -0
- orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth2.ows +48 -0
- orangecontrib/tomwer/tutorials/default_cor_search.ows +40 -0
- orangecontrib/tomwer/tutorials/hello_world_python_script.ows +50 -0
- orangecontrib/tomwer/tutorials/simple_slice_reconstruction_on_slurm.ows +50 -0
- orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +8 -8
- orangecontrib/tomwer/widgets/__init__.py +1 -1
- orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +0 -1
- orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +8 -6
- orangecontrib/tomwer/widgets/control/AdvancementOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -6
- orangecontrib/tomwer/widgets/control/DataListOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataListenerOW.py +4 -4
- orangecontrib/tomwer/widgets/control/DataSelectorOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataTransfertOW.py +7 -7
- orangecontrib/tomwer/widgets/control/DataValidatorOW.py +0 -1
- orangecontrib/tomwer/widgets/control/DataWatcherOW.py +0 -3
- orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +3 -2
- orangecontrib/tomwer/widgets/control/EmailOW.py +82 -0
- orangecontrib/tomwer/widgets/control/FilterOW.py +3 -3
- orangecontrib/tomwer/widgets/control/NXTomomillOW.py +1 -1
- orangecontrib/tomwer/widgets/control/NotifierOW.py +0 -1
- orangecontrib/tomwer/widgets/control/ReduceDarkFlatSelectorOW.py +93 -0
- orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +29 -5
- orangecontrib/tomwer/widgets/control/TimerOW.py +1 -2
- orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +0 -1
- orangecontrib/tomwer/widgets/control/VolumeSelector.py +0 -1
- orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +4 -10
- orangecontrib/tomwer/widgets/control/icons/email.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/email.svg +58 -0
- orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.png +0 -0
- orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.svg +199 -0
- orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +0 -1
- orangecontrib/tomwer/widgets/debugtools/ObjectInspectorOW.py +0 -1
- orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +1 -2
- orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +1 -2
- orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +0 -1
- orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +0 -1
- orangecontrib/tomwer/widgets/other/PythonScriptOW.py +29 -1
- orangecontrib/tomwer/widgets/other/TomoObjsHub.py +28 -0
- orangecontrib/tomwer/widgets/other/icons/hub.png +0 -0
- orangecontrib/tomwer/widgets/other/icons/hub.svg +113 -0
- orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +18 -12
- orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +0 -2
- orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +21 -6
- orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -7
- orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +18 -5
- orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +40 -13
- orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +37 -10
- orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +2 -3
- orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +5 -4
- orangecontrib/tomwer/widgets/stitching/StitcherOW.py +0 -1
- orangecontrib/tomwer/widgets/stitching/ZStitchingConfigOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
- orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +0 -1
- orangecontrib/tomwer/widgets/visualization/RadioStackOW.py +7 -5
- orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +1 -1
- orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -3
- orangecontrib/tomwer/widgets/visualization/SliceStackOW.py +7 -5
- orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +4 -4
- tomwer/__main__.py +139 -5
- tomwer/app/axis.py +16 -5
- tomwer/app/canvas_launcher/config.py +1 -1
- tomwer/app/canvas_launcher/mainwindow.py +164 -6
- tomwer/app/darkref.py +10 -181
- tomwer/app/darkrefpatch.py +10 -131
- tomwer/app/diffframe.py +11 -0
- tomwer/app/imagekeyeditor.py +12 -19
- tomwer/app/intensitynormalization.py +1 -0
- tomwer/app/lamino.py +7 -2
- tomwer/app/patchrawdarkflat.py +131 -0
- tomwer/app/radiostack.py +10 -0
- tomwer/app/reducedarkflat.py +205 -0
- tomwer/app/saaxis.py +27 -8
- tomwer/app/sadeltabeta.py +29 -8
- tomwer/app/samplemoved.py +11 -0
- tomwer/app/scanviewer.py +12 -0
- tomwer/app/sinogramviewer.py +11 -0
- tomwer/app/slicestack.py +11 -0
- tomwer/app/zstitching.py +12 -0
- tomwer/core/futureobject.py +4 -2
- tomwer/core/process/conditions/filters.py +26 -4
- tomwer/core/process/control/datadiscovery.py +4 -0
- tomwer/core/process/control/datawatcher/datawatcher.py +5 -1
- tomwer/core/process/control/email.py +148 -0
- tomwer/core/process/control/nxtomoconcatenate.py +9 -2
- tomwer/core/process/control/nxtomomill.py +58 -16
- tomwer/core/process/control/scanselector.py +4 -0
- tomwer/core/process/control/scantransfer.py +52 -23
- tomwer/core/process/control/test/test_concatenate_nxtomos.py +1 -0
- tomwer/core/process/control/test/test_email.py +52 -0
- tomwer/core/process/control/test/test_h52nx_process.py +106 -0
- tomwer/core/process/control/test/test_volume_link.py +5 -4
- tomwer/core/process/control/timer.py +27 -6
- tomwer/core/process/control/tomoobjserie.py +4 -0
- tomwer/core/process/control/volumeselector.py +4 -0
- tomwer/core/process/control/volumesymlink.py +47 -8
- tomwer/core/process/edit/darkflatpatch.py +49 -8
- tomwer/core/process/edit/imagekeyeditor.py +63 -13
- tomwer/core/process/reconstruction/axis/__init__.py +1 -1
- tomwer/core/process/reconstruction/axis/axis.py +61 -41
- tomwer/core/process/reconstruction/axis/params.py +4 -6
- tomwer/core/process/reconstruction/darkref/darkrefs.py +53 -16
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +12 -2
- tomwer/core/process/reconstruction/lamino/__init__.py +1 -1
- tomwer/core/process/reconstruction/lamino/tofu.py +22 -2
- tomwer/core/process/reconstruction/nabu/nabucommon.py +93 -14
- tomwer/core/process/reconstruction/nabu/nabuscores.py +70 -33
- tomwer/core/process/reconstruction/nabu/nabuslices.py +219 -41
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +240 -108
- tomwer/core/process/reconstruction/nabu/utils.py +10 -36
- tomwer/core/process/reconstruction/normalization/normalization.py +10 -3
- tomwer/core/process/reconstruction/saaxis/__init__.py +1 -0
- tomwer/core/process/reconstruction/saaxis/saaxis.py +564 -376
- tomwer/core/process/reconstruction/sadeltabeta/__init__.py +1 -0
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +481 -268
- tomwer/core/process/reconstruction/scores/params.py +21 -8
- tomwer/core/process/reconstruction/test/test_darkref_copy.py +2 -0
- tomwer/core/process/reconstruction/test/test_saaxis.py +21 -8
- tomwer/core/process/reconstruction/test/test_sadeltabeta.py +8 -5
- tomwer/core/process/script/python.py +7 -2
- tomwer/core/process/stitching/nabustitcher.py +10 -3
- tomwer/core/process/task.py +2 -9
- tomwer/core/process/test/test_axis.py +25 -15
- tomwer/core/process/test/test_conditions.py +6 -6
- tomwer/core/process/test/test_dark_and_flat.py +20 -15
- tomwer/core/process/test/test_data_transfer.py +8 -8
- tomwer/core/process/test/test_data_watcher.py +1 -1
- tomwer/core/process/test/test_lamino.py +6 -6
- tomwer/core/process/test/test_nabu.py +13 -8
- tomwer/core/process/test/test_normalization.py +1 -0
- tomwer/core/process/test/test_timer.py +6 -6
- tomwer/core/process/visualization/dataviewer.py +4 -0
- tomwer/core/process/visualization/diffviewer.py +4 -0
- tomwer/core/process/visualization/imagestackviewer.py +4 -0
- tomwer/core/process/visualization/radiostack.py +4 -0
- tomwer/core/process/visualization/samplemoved.py +4 -0
- tomwer/core/process/visualization/sinogramviewer.py +4 -0
- tomwer/core/process/visualization/slicestack.py +4 -0
- tomwer/core/process/visualization/volumeviewer.py +4 -0
- tomwer/core/scan/hdf5scan.py +4 -4
- tomwer/core/scan/scanbase.py +5 -1
- tomwer/core/scan/test/test_process_registration.py +9 -9
- tomwer/core/settings.py +59 -1
- tomwer/core/test/test_lamino.py +2 -1
- tomwer/core/utils/__init__.py +16 -0
- tomwer/core/utils/locker.py +0 -1
- tomwer/core/utils/resource.py +6 -11
- tomwer/core/utils/scanutils.py +2 -0
- tomwer/gui/cluster/slurm.py +91 -7
- tomwer/gui/cluster/supervisor.py +16 -11
- tomwer/gui/cluster/test/test_cluster.py +16 -1
- tomwer/gui/conditions/filter.py +3 -3
- tomwer/gui/control/datalist.py +24 -11
- tomwer/gui/control/email.py +183 -0
- tomwer/gui/control/reducedarkflatselector.py +545 -0
- tomwer/gui/control/singletomoobj.py +23 -1
- tomwer/gui/control/test/test_email.py +35 -0
- tomwer/gui/control/test/test_reducedarkflat_selector.py +280 -0
- tomwer/gui/reconstruction/axis/CompareImages.py +1 -1
- tomwer/gui/reconstruction/axis/axis.py +10 -6
- tomwer/gui/reconstruction/axis/radioaxis.py +14 -6
- tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +2 -0
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +4 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +3 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +34 -33
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +1 -1
- tomwer/gui/reconstruction/normalization/intensity.py +5 -5
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +1 -0
- tomwer/gui/reconstruction/saaxis/saaxis.py +6 -6
- tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +6 -6
- tomwer/gui/reconstruction/scores/scoreplot.py +6 -4
- tomwer/gui/samplemoved/__init__.py +2 -2
- tomwer/gui/stackplot.py +18 -7
- tomwer/gui/stacks.py +2 -2
- tomwer/gui/stitching/stitchandbackground.py +2 -2
- tomwer/gui/stitching/stitching.py +1 -1
- tomwer/gui/stitching/stitching_raw.py +1 -1
- tomwer/gui/utils/__init__.py +1 -85
- tomwer/gui/utils/illustrations.py +1 -1
- tomwer/gui/utils/inputwidget.py +41 -36
- tomwer/gui/utils/slider.py +2 -2
- tomwer/gui/utils/utils.py +93 -0
- tomwer/gui/visualization/dataviewer.py +8 -5
- tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
- tomwer/gui/visualization/reconstructionparameters.py +26 -6
- tomwer/gui/visualization/sinogramviewer.py +7 -1
- tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -4
- tomwer/gui/visualization/volumeviewer.py +2 -0
- tomwer/resources/__init__.py +55 -43
- tomwer/resources/gui/icons/compose.png +0 -0
- tomwer/resources/gui/icons/compose.svg +75 -0
- tomwer/synctools/datatransfert.py +3 -1
- tomwer/synctools/stacks/edit/darkflatpatch.py +39 -34
- tomwer/synctools/stacks/edit/imagekeyeditor.py +8 -27
- tomwer/synctools/stacks/processingstack.py +45 -9
- tomwer/synctools/stacks/reconstruction/axis.py +6 -5
- tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -0
- tomwer/synctools/stacks/reconstruction/lamino.py +3 -3
- tomwer/synctools/stacks/reconstruction/nabu.py +49 -140
- tomwer/synctools/stacks/reconstruction/normalization.py +1 -0
- tomwer/synctools/stacks/reconstruction/saaxis.py +19 -33
- tomwer/synctools/stacks/reconstruction/sadeltabeta.py +16 -32
- tomwer/synctools/test/test_darkRefs.py +19 -10
- tomwer/synctools/test/test_foldertransfer.py +7 -7
- tomwer/third_party/nabu/preproc/phase.py +6 -8
- tomwer/third_party/nabu/utils.py +2 -3
- tomwer/version.py +1 -1
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/METADATA +15 -54
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/RECORD +219 -192
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/WHEEL +1 -1
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/entry_points.txt +3 -3
- /tomwer-1.2.0a1-py3.9-nspkg.pth → /tomwer-1.2.0a3-py3.11-nspkg.pth +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/LICENSE +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/top_level.txt +0 -0
@@ -33,7 +33,7 @@ import shutil
|
|
33
33
|
import tempfile
|
34
34
|
import unittest
|
35
35
|
|
36
|
-
from tomwer.core.process.control.volumesymlink import
|
36
|
+
from tomwer.core.process.control.volumesymlink import VolumeSymbolicLinkTask
|
37
37
|
from tomwer.core.scan.edfscan import EDFTomoScan
|
38
38
|
from tomwer.core.utils.scanutils import MockEDF
|
39
39
|
|
@@ -57,9 +57,10 @@ class TestVolumeSymbolicLink(unittest.TestCase):
|
|
57
57
|
|
58
58
|
def test(self):
|
59
59
|
"""simple test that the creation of a symbolic link works"""
|
60
|
-
vlink_process =
|
61
|
-
|
62
|
-
|
60
|
+
vlink_process = VolumeSymbolicLinkTask(
|
61
|
+
inputs={
|
62
|
+
"data": self._scan,
|
63
|
+
"serialize_output_data": False,
|
63
64
|
"output_type": "static",
|
64
65
|
"output_folder": self._output_folder,
|
65
66
|
}
|
@@ -35,11 +35,17 @@ from tomwer.core.process.task import Task
|
|
35
35
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
36
36
|
from tomwer.core.scan.scanfactory import ScanFactory
|
37
37
|
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
38
|
+
from silx.utils.deprecation import deprecated_warning, deprecated
|
38
39
|
|
39
40
|
_logger = logging.getLogger(__name__)
|
40
41
|
|
41
42
|
|
42
|
-
class
|
43
|
+
class TimerTask(
|
44
|
+
Task,
|
45
|
+
input_names=("data", "wait"),
|
46
|
+
output_names=("data",),
|
47
|
+
optional_input_names=("serialize_output_data",),
|
48
|
+
):
|
43
49
|
"""
|
44
50
|
Simple timer / time out - function
|
45
51
|
"""
|
@@ -57,15 +63,16 @@ class Timer(Task, input_names=("data",), output_names=("data",)):
|
|
57
63
|
)
|
58
64
|
if inputs is None:
|
59
65
|
inputs = {}
|
60
|
-
self.waiting_time = inputs.get("wait", 1)
|
61
66
|
|
62
67
|
@property
|
68
|
+
@deprecated(replacement="task.wait", since_version="1.2")
|
63
69
|
def waiting_time(self):
|
64
|
-
return self.
|
70
|
+
return self.inputs.wait
|
65
71
|
|
66
72
|
@waiting_time.setter
|
73
|
+
@deprecated(replacement="task.wait", since_version="1.2")
|
67
74
|
def waiting_time(self, wait):
|
68
|
-
self.
|
75
|
+
self.inputs.wait = wait
|
69
76
|
|
70
77
|
def run(self):
|
71
78
|
scan = data_identifier_to_scan(self.inputs.data)
|
@@ -77,8 +84,22 @@ class Timer(Task, input_names=("data",), output_names=("data",)):
|
|
77
84
|
raise TypeError(
|
78
85
|
f"scan is expected to be a dict or an instance of TomwerScanBase. Not {type(scan)}"
|
79
86
|
)
|
80
|
-
time.sleep(self.
|
81
|
-
if self.
|
87
|
+
time.sleep(self.inputs.wait)
|
88
|
+
if self.get_input_value("serialize_output_data", True):
|
82
89
|
self.outputs.data = scan.to_dict()
|
83
90
|
else:
|
84
91
|
self.outputs.data = scan
|
92
|
+
|
93
|
+
|
94
|
+
class Timer(TimerTask):
|
95
|
+
def __init__(
|
96
|
+
self, varinfo=None, inputs=None, node_id=None, node_attrs=None, execinfo=None
|
97
|
+
):
|
98
|
+
deprecated_warning(
|
99
|
+
name="tomwer.core.process.control.timer.Timer",
|
100
|
+
type_="class",
|
101
|
+
reason="improve readibility",
|
102
|
+
since_version="1.2",
|
103
|
+
replacement="TimerTask",
|
104
|
+
)
|
105
|
+
super().__init__(varinfo, inputs, node_id, node_attrs, execinfo)
|
@@ -6,5 +6,9 @@ from tomwer.core.utils.scanutils import data_identifier_to_scan
|
|
6
6
|
class _VolumeSelectorPlaceHolder(
|
7
7
|
EwoksTask, input_names=["volume"], output_names=["volume"]
|
8
8
|
):
|
9
|
+
"""
|
10
|
+
task to select a volume or a set of volumes
|
11
|
+
"""
|
12
|
+
|
9
13
|
def run(self):
|
10
14
|
self.outputs.volume = data_identifier_to_scan(self.inputs.volume)
|
@@ -32,6 +32,7 @@ import logging
|
|
32
32
|
import os
|
33
33
|
|
34
34
|
from silx.utils.enum import Enum as _Enum
|
35
|
+
from silx.utils.deprecation import deprecated_warning, deprecated
|
35
36
|
from tomoscan.factory import Factory
|
36
37
|
from tomoscan.volumebase import VolumeBase
|
37
38
|
|
@@ -84,7 +85,12 @@ def create_volume_symbolic_link(scan: TomwerScanBase, output_folder: str):
|
|
84
85
|
os.symlink(src=src_file_path, dst=dst_file_path)
|
85
86
|
|
86
87
|
|
87
|
-
class
|
88
|
+
class VolumeSymbolicLinkTask(
|
89
|
+
Task,
|
90
|
+
input_names=("data",),
|
91
|
+
output_names=("data",),
|
92
|
+
optional_input_names=("serialize_output_data", "output_type", "output_folder"),
|
93
|
+
):
|
88
94
|
"""
|
89
95
|
Process class for volume symbolic link
|
90
96
|
"""
|
@@ -103,12 +109,25 @@ class VolumeSymbolicLinkProcess(Task, input_names=("data",), output_names=("data
|
|
103
109
|
self._output_folder = None
|
104
110
|
|
105
111
|
@docstring(Task.set_configuration)
|
112
|
+
@deprecated(
|
113
|
+
reason="ewoksification",
|
114
|
+
replacement="task.inputs.output_type and task.inputs.output_folder",
|
115
|
+
since_version="1.2",
|
116
|
+
)
|
106
117
|
def set_configuration(self, properties):
|
107
118
|
if "output_type" in properties:
|
108
119
|
self._output_type = OutputType.from_value(properties["output_type"])
|
109
120
|
if "output_folder" in properties:
|
110
121
|
self._output_folder = properties["output_folder"]
|
111
122
|
|
123
|
+
@deprecated(
|
124
|
+
reason="ewoksification",
|
125
|
+
replacement="task.inputs.output_type and task.inputs.output_folder",
|
126
|
+
since_version="1.2",
|
127
|
+
)
|
128
|
+
def get_configuration(self):
|
129
|
+
return super().get_configuration()
|
130
|
+
|
112
131
|
@docstring(Task.program_name)
|
113
132
|
@staticmethod
|
114
133
|
def program_name():
|
@@ -133,29 +152,49 @@ class VolumeSymbolicLinkProcess(Task, input_names=("data",), output_names=("data
|
|
133
152
|
f"scan is expected to be a dict or an instance of TomwerScanBase. Not {type(scan)}"
|
134
153
|
)
|
135
154
|
|
136
|
-
|
137
|
-
|
155
|
+
output_type = OutputType.from_value(
|
156
|
+
self.get_input_value("output_type", self._output_type)
|
157
|
+
)
|
158
|
+
output_folder = self.get_input_value("output_folder", self._output_folder)
|
159
|
+
if output_type is OutputType.STATIC:
|
160
|
+
if output_folder is None:
|
138
161
|
raise ValueError(
|
139
162
|
"Manual setting of the output folder is "
|
140
163
|
"requested but None is provided."
|
141
164
|
)
|
142
165
|
else:
|
143
|
-
output_folder = self._output_folder
|
144
166
|
if not os.path.isabs(output_folder):
|
145
167
|
os.path.abspath(
|
146
168
|
os.path.join(os.path.realpath(scan.path), output_folder)
|
147
169
|
)
|
148
|
-
elif
|
170
|
+
elif output_type is OutputType.ONE_LEVEL_UPPER:
|
149
171
|
output_folder = os.path.realpath(scan.path)
|
150
172
|
output_folder = os.path.abspath(
|
151
|
-
os.path.join(output_folder,
|
173
|
+
os.path.join(output_folder, output_type.value)
|
152
174
|
)
|
153
175
|
else:
|
154
|
-
raise ValueError(f"output type {
|
176
|
+
raise ValueError(f"output type {output_type.value} is not managed")
|
155
177
|
create_volume_symbolic_link(scan=scan, output_folder=output_folder)
|
156
|
-
self.
|
178
|
+
if self.get_input_value("serialize_output_data", True):
|
179
|
+
self.outputs.data = scan.to_dict()
|
180
|
+
else:
|
181
|
+
self.outputs.data = scan
|
157
182
|
|
158
183
|
@docstring(Task.definition)
|
159
184
|
@staticmethod
|
160
185
|
def definition():
|
161
186
|
return "Create a symbolic link to the volume folder"
|
187
|
+
|
188
|
+
|
189
|
+
class VolumeSymbolicLinkProcess(VolumeSymbolicLinkTask):
|
190
|
+
def __init__(
|
191
|
+
self, varinfo=None, inputs=None, node_id=None, node_attrs=None, execinfo=None
|
192
|
+
):
|
193
|
+
deprecated_warning(
|
194
|
+
name="tomwer.core.process.control.volumesymlink.VolumeSymbolicLinkProcess",
|
195
|
+
type_="class",
|
196
|
+
reason="improve readibility",
|
197
|
+
since_version="1.2",
|
198
|
+
replacement="VolumeSymbolicLinkTask",
|
199
|
+
)
|
200
|
+
super().__init__(varinfo, inputs, node_id, node_attrs, execinfo)
|
@@ -31,11 +31,11 @@ __date__ = "04/11/2020"
|
|
31
31
|
import nxtomomill.version
|
32
32
|
from nxtomomill.utils import add_dark_flat_nx_file
|
33
33
|
from silx.io.url import DataUrl
|
34
|
+
from silx.utils.deprecation import deprecated_warning, deprecated
|
34
35
|
|
35
36
|
from tomwer.core.process.task import Task
|
36
37
|
from tomwer.core.scan.hdf5scan import HDF5TomoScan
|
37
38
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
38
|
-
from tomwer.core.scan.scanfactory import ScanFactory
|
39
39
|
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
40
40
|
|
41
41
|
|
@@ -64,17 +64,18 @@ def apply_dark_flat_patch(scan: HDF5TomoScan, config: dict) -> TomwerScanBase:
|
|
64
64
|
return scan
|
65
65
|
|
66
66
|
|
67
|
-
class
|
67
|
+
class DarkFlatPatchTask(
|
68
|
+
Task,
|
69
|
+
input_names=("data", "configuration"),
|
70
|
+
output_names=("data",),
|
71
|
+
optional_input_names=("serialize_output_data",),
|
72
|
+
):
|
68
73
|
"""
|
69
74
|
Patch an existing NXtomo calling nxtomomill
|
70
75
|
"""
|
71
76
|
|
72
77
|
def run(self):
|
73
78
|
scan = data_identifier_to_scan(self.inputs.data)
|
74
|
-
if type(scan) is dict:
|
75
|
-
scan = ScanFactory.create_scan_object_frm_dict(scan)
|
76
|
-
else:
|
77
|
-
scan = scan
|
78
79
|
if scan is None:
|
79
80
|
return
|
80
81
|
if not isinstance(scan, TomwerScanBase):
|
@@ -84,7 +85,9 @@ class DarkFlatPatch(Task, input_names=("data",), output_names=("data",)):
|
|
84
85
|
if not isinstance(scan, HDF5TomoScan):
|
85
86
|
raise ValueError(f"input type of {scan}: {type(scan)} is not managed")
|
86
87
|
|
87
|
-
config = self.
|
88
|
+
config = self.inputs.configuration
|
89
|
+
if not isinstance(config, dict):
|
90
|
+
raise TypeError(f"config is expected to be a dict. {type(config)} provided")
|
88
91
|
apply_dark_flat_patch(scan=scan, config=config)
|
89
92
|
keys = config.keys()
|
90
93
|
for key in keys:
|
@@ -101,7 +104,10 @@ class DarkFlatPatch(Task, input_names=("data",), output_names=("data",)):
|
|
101
104
|
process_index=scan.pop_process_index(),
|
102
105
|
overwrite=True,
|
103
106
|
)
|
104
|
-
self.
|
107
|
+
if self.get_input_value("serialize_output_data", True):
|
108
|
+
self.outputs.data = scan.to_dict()
|
109
|
+
else:
|
110
|
+
self.outputs.data = scan
|
105
111
|
|
106
112
|
@staticmethod
|
107
113
|
def program_name():
|
@@ -114,3 +120,38 @@ class DarkFlatPatch(Task, input_names=("data",), output_names=("data",)):
|
|
114
120
|
@staticmethod
|
115
121
|
def definition():
|
116
122
|
return "Apply patch for dark and references on a scan (TomwerScanBase)"
|
123
|
+
|
124
|
+
@deprecated(
|
125
|
+
since_version="1.2",
|
126
|
+
replacement="DarkFlatPatchTask.inputs.configuration",
|
127
|
+
reason="ewoksification",
|
128
|
+
)
|
129
|
+
def get_configuration(self):
|
130
|
+
"""
|
131
|
+
|
132
|
+
:return: configuration of the process
|
133
|
+
:rtype: dict
|
134
|
+
"""
|
135
|
+
return self.inputs.configuration
|
136
|
+
|
137
|
+
@deprecated(
|
138
|
+
since_version="1.2",
|
139
|
+
replacement="DarkFlatPatchTask.inputs.configuration",
|
140
|
+
reason="ewoksification",
|
141
|
+
)
|
142
|
+
def set_configuration(self, configuration: dict) -> None:
|
143
|
+
self.inputs.configuration = configuration
|
144
|
+
|
145
|
+
|
146
|
+
class DarkFlatPatch(DarkFlatPatchTask):
|
147
|
+
def __init__(
|
148
|
+
self, varinfo=None, inputs=None, node_id=None, node_attrs=None, execinfo=None
|
149
|
+
):
|
150
|
+
deprecated_warning(
|
151
|
+
name="tomwer.core.process.edit.darkflatpatch.DarkFlatPatch",
|
152
|
+
type_="class",
|
153
|
+
reason="improve readibility",
|
154
|
+
since_version="1.2",
|
155
|
+
replacement="DarkFlatPatchTask",
|
156
|
+
)
|
157
|
+
super().__init__(varinfo, inputs, node_id, node_attrs, execinfo)
|
@@ -34,11 +34,11 @@ import nxtomomill.version
|
|
34
34
|
from nxtomomill.utils import change_image_key_control as _change_image_key_control
|
35
35
|
from tomoscan.esrf.scan.hdf5scan import ImageKey
|
36
36
|
from tomoscan.esrf.scan.hdf5scan import ImageKey as _ImageKey
|
37
|
+
from silx.utils.deprecation import deprecated_warning, deprecated
|
37
38
|
|
38
39
|
from tomwer.core.process.task import Task
|
39
40
|
from tomwer.core.scan.hdf5scan import HDF5TomoScan
|
40
41
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
41
|
-
from tomwer.core.scan.scanfactory import ScanFactory
|
42
42
|
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
43
43
|
|
44
44
|
_logger = logging.getLogger(__name__)
|
@@ -96,7 +96,16 @@ def change_image_key_control(scan: HDF5TomoScan, config: dict) -> TomwerScanBase
|
|
96
96
|
return scan
|
97
97
|
|
98
98
|
|
99
|
-
class
|
99
|
+
class ImageKeyEditorTask(
|
100
|
+
Task,
|
101
|
+
input_names=("data", "configuration"),
|
102
|
+
output_names=("data",),
|
103
|
+
optional_input_names=("serialize_output_data",),
|
104
|
+
):
|
105
|
+
"""
|
106
|
+
task to edit `image_key` field of an NXtomo ('data' input)
|
107
|
+
"""
|
108
|
+
|
100
109
|
def __init__(
|
101
110
|
self, varinfo=None, inputs=None, node_id=None, node_attrs=None, execinfo=None
|
102
111
|
):
|
@@ -107,14 +116,9 @@ class ImageKeyEditor(Task, input_names=("data",), output_names=("data",)):
|
|
107
116
|
node_attrs=node_attrs,
|
108
117
|
execinfo=execinfo,
|
109
118
|
)
|
110
|
-
self.set_configuration(inputs.get("image_key_edition", {}))
|
111
119
|
|
112
120
|
def run(self):
|
113
121
|
scan = data_identifier_to_scan(self.inputs.data)
|
114
|
-
if type(scan) is dict:
|
115
|
-
scan = ScanFactory.create_scan_object_frm_dict(scan)
|
116
|
-
else:
|
117
|
-
scan = scan
|
118
122
|
if scan is None:
|
119
123
|
return
|
120
124
|
if not isinstance(scan, TomwerScanBase):
|
@@ -124,8 +128,10 @@ class ImageKeyEditor(Task, input_names=("data",), output_names=("data",)):
|
|
124
128
|
if not isinstance(scan, HDF5TomoScan):
|
125
129
|
raise ValueError(f"input type of {scan}: {(type(scan))} is not managed")
|
126
130
|
|
127
|
-
|
128
|
-
|
131
|
+
config = self.inputs.configuration
|
132
|
+
if not isinstance(config, dict):
|
133
|
+
raise TypeError
|
134
|
+
change_image_key_control(scan=scan, config=config)
|
129
135
|
modif_keys = list(config.get("modifications", {}).keys())
|
130
136
|
new_modif = {}
|
131
137
|
for key in modif_keys:
|
@@ -141,7 +147,10 @@ class ImageKeyEditor(Task, input_names=("data",), output_names=("data",)):
|
|
141
147
|
process_index=scan.pop_process_index(),
|
142
148
|
overwrite=True,
|
143
149
|
)
|
144
|
-
self.
|
150
|
+
if self.get_input_value("serialize_output_data", True):
|
151
|
+
self.outputs.data = scan.to_dict()
|
152
|
+
else:
|
153
|
+
self.outputs.data = scan
|
145
154
|
|
146
155
|
@staticmethod
|
147
156
|
def program_name():
|
@@ -157,7 +166,10 @@ class ImageKeyEditor(Task, input_names=("data",), output_names=("data",)):
|
|
157
166
|
|
158
167
|
|
159
168
|
class ImageKeyUpgraderTask(
|
160
|
-
Task,
|
169
|
+
Task,
|
170
|
+
input_names=("data", "operations"),
|
171
|
+
output_names=("data",),
|
172
|
+
optional_input_names=("serialize_output_data",),
|
161
173
|
):
|
162
174
|
"""
|
163
175
|
close to ImageKeyEditor but convert a full "family" of frame type to another
|
@@ -165,7 +177,7 @@ class ImageKeyUpgraderTask(
|
|
165
177
|
"""
|
166
178
|
|
167
179
|
def run(self):
|
168
|
-
scan = self.inputs.data
|
180
|
+
scan = data_identifier_to_scan(self.inputs.data)
|
169
181
|
if not isinstance(scan, HDF5TomoScan):
|
170
182
|
raise TypeError(f"scan is expected to be an instance of {HDF5TomoScan}")
|
171
183
|
operations = self.inputs.operations
|
@@ -199,7 +211,10 @@ class ImageKeyUpgraderTask(
|
|
199
211
|
process_index=scan.pop_process_index(),
|
200
212
|
overwrite=True,
|
201
213
|
)
|
202
|
-
self.
|
214
|
+
if self.get_input_value("serialize_output_data", True):
|
215
|
+
self.outputs.data = scan.to_dict()
|
216
|
+
else:
|
217
|
+
self.outputs.data = scan
|
203
218
|
|
204
219
|
@staticmethod
|
205
220
|
def from_operation_to_config(
|
@@ -229,3 +244,38 @@ class ImageKeyUpgraderTask(
|
|
229
244
|
@staticmethod
|
230
245
|
def definition():
|
231
246
|
return "Modify image keys on an NXTomo"
|
247
|
+
|
248
|
+
@deprecated(
|
249
|
+
since_version="1.2",
|
250
|
+
replacement="DarkFlatPatchTask.inputs.configuration",
|
251
|
+
reason="ewoksification",
|
252
|
+
)
|
253
|
+
def get_configuration(self):
|
254
|
+
"""
|
255
|
+
|
256
|
+
:return: configuration of the process
|
257
|
+
:rtype: dict
|
258
|
+
"""
|
259
|
+
return self.inputs.configuration
|
260
|
+
|
261
|
+
@deprecated(
|
262
|
+
since_version="1.2",
|
263
|
+
replacement="DarkFlatPatchTask.inputs.configuration",
|
264
|
+
reason="ewoksification",
|
265
|
+
)
|
266
|
+
def set_configuration(self, configuration: dict) -> None:
|
267
|
+
self.inputs.configuration = configuration
|
268
|
+
|
269
|
+
|
270
|
+
class ImageKeyUpgrader(ImageKeyUpgraderTask):
|
271
|
+
def __init__(
|
272
|
+
self, varinfo=None, inputs=None, node_id=None, node_attrs=None, execinfo=None
|
273
|
+
):
|
274
|
+
deprecated_warning(
|
275
|
+
name="tomwer.core.process.edit.imagekeyeditor.ImageKeyUpgrader",
|
276
|
+
type_="class",
|
277
|
+
reason="improve readibility",
|
278
|
+
since_version="1.2",
|
279
|
+
replacement="ImageKeyUpgraderTask",
|
280
|
+
)
|
281
|
+
super().__init__(varinfo, inputs, node_id, node_attrs, execinfo)
|
@@ -1,2 +1,2 @@
|
|
1
|
-
from .axis import
|
1
|
+
from .axis import AxisTask # noqa F401
|
2
2
|
from .params import AxisRP # noqa F401
|
@@ -32,7 +32,6 @@ __date__ = "19/03/2019"
|
|
32
32
|
import logging
|
33
33
|
from typing import Optional, Union
|
34
34
|
|
35
|
-
import nabu
|
36
35
|
import numpy
|
37
36
|
from nabu.estimation.cor import (
|
38
37
|
CenterOfRotation,
|
@@ -41,8 +40,10 @@ from nabu.estimation.cor import (
|
|
41
40
|
CenterOfRotationSlidingWindow,
|
42
41
|
)
|
43
42
|
from nabu.pipeline.estimators import SinoCORFinder
|
43
|
+
from nabu.resources.nxflatfield import update_dataset_info_flats_darks
|
44
44
|
from processview.core.manager import DatasetState, ProcessManager
|
45
45
|
from processview.core.superviseprocess import SuperviseProcess
|
46
|
+
from silx.utils.deprecation import deprecated_warning
|
46
47
|
|
47
48
|
import tomwer.version
|
48
49
|
from tomwer.core.process.reconstruction.utils.cor import absolute_pos_to_relative
|
@@ -107,32 +108,27 @@ def adapt_tomwer_scan_to_nabu(scan: TomwerScanBase):
|
|
107
108
|
updating infos regarding flat and dark if needed
|
108
109
|
"""
|
109
110
|
dataset_infos = scan.to_nabu_dataset_analyser()
|
110
|
-
if
|
111
|
-
|
112
|
-
# directly in the function but outside. So we need an extra call to
|
113
|
-
# update_dataset_info_flats_darks
|
114
|
-
import inspect
|
115
|
-
|
116
|
-
from nabu.resources.nxflatfield import update_dataset_info_flats_darks
|
117
|
-
|
118
|
-
# processes_file has been removed in a minor release. safer to inspect if is needed or not
|
119
|
-
# should be removed on release 1.1 of tomwer I guess
|
120
|
-
if (
|
121
|
-
"processes_file"
|
122
|
-
in inspect.signature(update_dataset_info_flats_darks).parameters
|
123
|
-
):
|
124
|
-
update_dataset_info_flats_darks( # pylint: disable=E1123
|
125
|
-
dataset_infos,
|
126
|
-
processes_file=scan.get_relative_file(
|
127
|
-
"nabu_processes.h5", with_dataset_prefix=True
|
128
|
-
),
|
129
|
-
flatfield_mode=None,
|
130
|
-
)
|
131
|
-
else:
|
111
|
+
if isinstance(scan, HDF5TomoScan):
|
112
|
+
try:
|
132
113
|
update_dataset_info_flats_darks(
|
133
114
|
dataset_infos,
|
134
115
|
flatfield_mode=None,
|
135
116
|
)
|
117
|
+
except ValueError as exception:
|
118
|
+
# nabu raise an error if no darks / flats set. But this can make sense at this stage if the NXtomo has no
|
119
|
+
# raw dark / flat and is already normalized. In this case only fire a warning
|
120
|
+
if (
|
121
|
+
scan.reduced_darks is not None
|
122
|
+
and len(scan.reduced_darks) > 0
|
123
|
+
and scan.reduced_flats is not None
|
124
|
+
and len(scan.reduced_flats) > 0
|
125
|
+
):
|
126
|
+
raise exception
|
127
|
+
else:
|
128
|
+
_logger.warning(
|
129
|
+
"Fail to update nabu dataset info flats and darks. Expected if the dataset contains already normalized projections"
|
130
|
+
)
|
131
|
+
|
136
132
|
return dataset_infos
|
137
133
|
|
138
134
|
|
@@ -304,7 +300,7 @@ def compute_scan_cor_nabu_growing_window(scan):
|
|
304
300
|
:return: Union[float, None]
|
305
301
|
"""
|
306
302
|
if not scan.axis_params.use_sinogram:
|
307
|
-
radio_1, radio_2 =
|
303
|
+
radio_1, radio_2 = AxisTask.get_inputs(scan=scan)
|
308
304
|
if radio_1 is None or radio_2 is None:
|
309
305
|
raise NoAxisUrl("Unable to find projections for nabu axis calculation")
|
310
306
|
else:
|
@@ -417,7 +413,7 @@ def compute_scan_cor_nabu_sliding_window(scan):
|
|
417
413
|
:return: Union[float, None]
|
418
414
|
"""
|
419
415
|
if not scan.axis_params.use_sinogram:
|
420
|
-
radio_1, radio_2 =
|
416
|
+
radio_1, radio_2 = AxisTask.get_inputs(scan=scan)
|
421
417
|
if radio_1 is None or radio_2 is None:
|
422
418
|
raise NoAxisUrl("Unable to find projections for nabu axis calculation")
|
423
419
|
else:
|
@@ -486,7 +482,7 @@ def compute_scan_cor_nabu_centered(scan):
|
|
486
482
|
|
487
483
|
"""
|
488
484
|
assert scan.axis_params is not None
|
489
|
-
radio_1, radio_2 =
|
485
|
+
radio_1, radio_2 = AxisTask.get_inputs(scan=scan)
|
490
486
|
if radio_1 is None or radio_2 is None:
|
491
487
|
raise NoAxisUrl("Unable to find projections for nabu axis calculation")
|
492
488
|
|
@@ -540,7 +536,7 @@ def compute_scan_cor_nabu_global(scan):
|
|
540
536
|
|
541
537
|
"""
|
542
538
|
assert scan.axis_params is not None
|
543
|
-
radio_1, radio_2 =
|
539
|
+
radio_1, radio_2 = AxisTask.get_inputs(scan=scan)
|
544
540
|
if radio_1 is None or radio_2 is None:
|
545
541
|
raise NoAxisUrl("Unable to find projections for nabu axis calculation")
|
546
542
|
|
@@ -578,8 +574,12 @@ class NoAxisUrl(Exception):
|
|
578
574
|
pass
|
579
575
|
|
580
576
|
|
581
|
-
class
|
582
|
-
Task,
|
577
|
+
class AxisTask(
|
578
|
+
Task,
|
579
|
+
SuperviseProcess,
|
580
|
+
input_names=("data",),
|
581
|
+
output_names=("data",),
|
582
|
+
optional_input_names=("serialize_output_data",),
|
583
583
|
):
|
584
584
|
"""
|
585
585
|
Process used to compute the center of rotation of a scan
|
@@ -677,6 +677,7 @@ class AxisProcess(
|
|
677
677
|
"""
|
678
678
|
scan = data_identifier_to_scan(self.inputs.data)
|
679
679
|
if scan is None:
|
680
|
+
self.outputs.data = None
|
680
681
|
return
|
681
682
|
|
682
683
|
if isinstance(scan, TomwerScanBase):
|
@@ -711,7 +712,11 @@ class AxisProcess(
|
|
711
712
|
finally:
|
712
713
|
if cor != "...":
|
713
714
|
self._process_end(scan, cor=cor, error=error)
|
714
|
-
|
715
|
+
|
716
|
+
if self.get_input_value("serialize_output_data", True):
|
717
|
+
self.outputs.data = scan_res.to_dict()
|
718
|
+
else:
|
719
|
+
self.outputs.data = scan_res
|
715
720
|
|
716
721
|
def _process_end(self, scan, cor, error=None):
|
717
722
|
assert isinstance(scan, TomwerScanBase)
|
@@ -792,7 +797,7 @@ class AxisProcess(
|
|
792
797
|
@staticmethod
|
793
798
|
def get_inputs(scan):
|
794
799
|
assert isinstance(scan, TomwerScanBase)
|
795
|
-
radio_1, radio_2 =
|
800
|
+
radio_1, radio_2 = AxisTask.get_inputs_urls(scan=scan)
|
796
801
|
if radio_1 and radio_2:
|
797
802
|
mess = " ".join(
|
798
803
|
("input radios are", radio_1.url.path(), "and", radio_2.url.path())
|
@@ -856,7 +861,7 @@ class AxisProcess(
|
|
856
861
|
|
857
862
|
:param TomwerScanBase scan: scan for which we want to compute the axis
|
858
863
|
position.
|
859
|
-
:return: scan as a TomoBase or a dict if
|
864
|
+
:return: scan as a TomoBase or a dict if serialize_output_data activated
|
860
865
|
"""
|
861
866
|
_logger.info("compute center of rotation for %s" % scan.path)
|
862
867
|
try:
|
@@ -884,10 +889,7 @@ class AxisProcess(
|
|
884
889
|
f"Compute axis position ({r_cor_value}) with {method} for {scan_name}"
|
885
890
|
)
|
886
891
|
_logger.info(mess)
|
887
|
-
|
888
|
-
return scan.to_dict()
|
889
|
-
else:
|
890
|
-
return scan
|
892
|
+
return scan
|
891
893
|
|
892
894
|
def setMode(self, mode, value):
|
893
895
|
if mode is AxisMode.manual:
|
@@ -952,9 +954,7 @@ class AxisProcess(
|
|
952
954
|
"""
|
953
955
|
if entry is None:
|
954
956
|
with HDF5File(process_file, "r", swmr=True) as h5f:
|
955
|
-
entries =
|
956
|
-
root_node=h5f, process=AxisProcess
|
957
|
-
)
|
957
|
+
entries = AxisTask._get_process_nodes(root_node=h5f, process=AxisTask)
|
958
958
|
if len(entries) == 0:
|
959
959
|
_logger.info("unable to find a Axis process in %s" % process_file)
|
960
960
|
return None
|
@@ -965,8 +965,8 @@ class AxisProcess(
|
|
965
965
|
_logger.info("take %s as default entry" % entry)
|
966
966
|
|
967
967
|
with HDF5File(process_file, "r", swmr=True) as h5f:
|
968
|
-
axis_nodes =
|
969
|
-
root_node=h5f[entry], process=
|
968
|
+
axis_nodes = AxisTask._get_process_nodes(
|
969
|
+
root_node=h5f[entry], process=AxisTask
|
970
970
|
)
|
971
971
|
index_to_path = {}
|
972
972
|
for key, index in axis_nodes.items():
|
@@ -996,3 +996,23 @@ class AxisProcess(
|
|
996
996
|
else:
|
997
997
|
res = h5py_read_dataset(results_node["center_of_rotation"])
|
998
998
|
return res
|
999
|
+
|
1000
|
+
|
1001
|
+
class AxisProcess(AxisTask):
|
1002
|
+
def __init__(
|
1003
|
+
self,
|
1004
|
+
process_id=None,
|
1005
|
+
varinfo=None,
|
1006
|
+
inputs=None,
|
1007
|
+
node_id=None,
|
1008
|
+
node_attrs=None,
|
1009
|
+
execinfo=None,
|
1010
|
+
):
|
1011
|
+
deprecated_warning(
|
1012
|
+
name="tomwer.core.process.reconstruction.axis.axis.AxisProcess",
|
1013
|
+
type_="class",
|
1014
|
+
reason="improve readibility",
|
1015
|
+
since_version="1.2",
|
1016
|
+
replacement="AxisTask",
|
1017
|
+
)
|
1018
|
+
super().__init__(process_id, varinfo, inputs, node_id, node_attrs, execinfo)
|