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.
Files changed (219) hide show
  1. orangecontrib/tomwer/tutorials/append_raw_darks_and_flats_frames_to_NXtomos.ows +44 -0
  2. orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth1.ows +55 -0
  3. orangecontrib/tomwer/tutorials/copy_reduced_darks_and_flats_meth2.ows +48 -0
  4. orangecontrib/tomwer/tutorials/default_cor_search.ows +40 -0
  5. orangecontrib/tomwer/tutorials/hello_world_python_script.ows +50 -0
  6. orangecontrib/tomwer/tutorials/simple_slice_reconstruction_on_slurm.ows +50 -0
  7. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +8 -8
  8. orangecontrib/tomwer/widgets/__init__.py +1 -1
  9. orangecontrib/tomwer/widgets/cluster/FutureSupervisorOW.py +0 -1
  10. orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +8 -6
  11. orangecontrib/tomwer/widgets/control/AdvancementOW.py +0 -1
  12. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -6
  13. orangecontrib/tomwer/widgets/control/DataListOW.py +0 -1
  14. orangecontrib/tomwer/widgets/control/DataListenerOW.py +4 -4
  15. orangecontrib/tomwer/widgets/control/DataSelectorOW.py +0 -1
  16. orangecontrib/tomwer/widgets/control/DataTransfertOW.py +7 -7
  17. orangecontrib/tomwer/widgets/control/DataValidatorOW.py +0 -1
  18. orangecontrib/tomwer/widgets/control/DataWatcherOW.py +0 -3
  19. orangecontrib/tomwer/widgets/control/EDF2NXTomomillOW.py +3 -2
  20. orangecontrib/tomwer/widgets/control/EmailOW.py +82 -0
  21. orangecontrib/tomwer/widgets/control/FilterOW.py +3 -3
  22. orangecontrib/tomwer/widgets/control/NXTomomillOW.py +1 -1
  23. orangecontrib/tomwer/widgets/control/NotifierOW.py +0 -1
  24. orangecontrib/tomwer/widgets/control/ReduceDarkFlatSelectorOW.py +93 -0
  25. orangecontrib/tomwer/widgets/control/SingleTomoObjOW.py +29 -5
  26. orangecontrib/tomwer/widgets/control/TimerOW.py +1 -2
  27. orangecontrib/tomwer/widgets/control/TomoObjSerieOW.py +0 -1
  28. orangecontrib/tomwer/widgets/control/VolumeSelector.py +0 -1
  29. orangecontrib/tomwer/widgets/control/VolumeSymLinkOW.py +4 -10
  30. orangecontrib/tomwer/widgets/control/icons/email.png +0 -0
  31. orangecontrib/tomwer/widgets/control/icons/email.svg +58 -0
  32. orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.png +0 -0
  33. orangecontrib/tomwer/widgets/control/icons/reduced_darkflat_selector.svg +199 -0
  34. orangecontrib/tomwer/widgets/debugtools/DatasetGeneratorOW.py +0 -1
  35. orangecontrib/tomwer/widgets/debugtools/ObjectInspectorOW.py +0 -1
  36. orangecontrib/tomwer/widgets/edit/DarkFlatPatchOW.py +1 -2
  37. orangecontrib/tomwer/widgets/edit/ImageKeyEditorOW.py +1 -2
  38. orangecontrib/tomwer/widgets/edit/ImageKeyUpgraderOW.py +0 -1
  39. orangecontrib/tomwer/widgets/edit/NXtomoEditorOW.py +0 -1
  40. orangecontrib/tomwer/widgets/other/PythonScriptOW.py +29 -1
  41. orangecontrib/tomwer/widgets/other/TomoObjsHub.py +28 -0
  42. orangecontrib/tomwer/widgets/other/icons/hub.png +0 -0
  43. orangecontrib/tomwer/widgets/other/icons/hub.svg +113 -0
  44. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +18 -12
  45. orangecontrib/tomwer/widgets/reconstruction/CastNabuVolumeOW.py +0 -2
  46. orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +21 -6
  47. orangecontrib/tomwer/widgets/reconstruction/NabuOW.py +29 -7
  48. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +18 -5
  49. orangecontrib/tomwer/widgets/reconstruction/SAAxisOW.py +40 -13
  50. orangecontrib/tomwer/widgets/reconstruction/SADeltaBetaOW.py +37 -10
  51. orangecontrib/tomwer/widgets/reconstruction/SinoNormOW.py +2 -3
  52. orangecontrib/tomwer/widgets/reconstruction/TofuOW.py +5 -4
  53. orangecontrib/tomwer/widgets/stitching/StitcherOW.py +0 -1
  54. orangecontrib/tomwer/widgets/stitching/ZStitchingConfigOW.py +0 -1
  55. orangecontrib/tomwer/widgets/visualization/DataViewerOW.py +10 -4
  56. orangecontrib/tomwer/widgets/visualization/DiffViewerOW.py +1 -1
  57. orangecontrib/tomwer/widgets/visualization/LivesliceOW.py +0 -1
  58. orangecontrib/tomwer/widgets/visualization/NXtomoMetadataViewerOW.py +0 -1
  59. orangecontrib/tomwer/widgets/visualization/RadioStackOW.py +7 -5
  60. orangecontrib/tomwer/widgets/visualization/SampleMovedOW.py +1 -1
  61. orangecontrib/tomwer/widgets/visualization/SinogramViewerOW.py +0 -3
  62. orangecontrib/tomwer/widgets/visualization/SliceStackOW.py +7 -5
  63. orangecontrib/tomwer/widgets/visualization/VolumeViewerOW.py +4 -4
  64. tomwer/__main__.py +139 -5
  65. tomwer/app/axis.py +16 -5
  66. tomwer/app/canvas_launcher/config.py +1 -1
  67. tomwer/app/canvas_launcher/mainwindow.py +164 -6
  68. tomwer/app/darkref.py +10 -181
  69. tomwer/app/darkrefpatch.py +10 -131
  70. tomwer/app/diffframe.py +11 -0
  71. tomwer/app/imagekeyeditor.py +12 -19
  72. tomwer/app/intensitynormalization.py +1 -0
  73. tomwer/app/lamino.py +7 -2
  74. tomwer/app/patchrawdarkflat.py +131 -0
  75. tomwer/app/radiostack.py +10 -0
  76. tomwer/app/reducedarkflat.py +205 -0
  77. tomwer/app/saaxis.py +27 -8
  78. tomwer/app/sadeltabeta.py +29 -8
  79. tomwer/app/samplemoved.py +11 -0
  80. tomwer/app/scanviewer.py +12 -0
  81. tomwer/app/sinogramviewer.py +11 -0
  82. tomwer/app/slicestack.py +11 -0
  83. tomwer/app/zstitching.py +12 -0
  84. tomwer/core/futureobject.py +4 -2
  85. tomwer/core/process/conditions/filters.py +26 -4
  86. tomwer/core/process/control/datadiscovery.py +4 -0
  87. tomwer/core/process/control/datawatcher/datawatcher.py +5 -1
  88. tomwer/core/process/control/email.py +148 -0
  89. tomwer/core/process/control/nxtomoconcatenate.py +9 -2
  90. tomwer/core/process/control/nxtomomill.py +58 -16
  91. tomwer/core/process/control/scanselector.py +4 -0
  92. tomwer/core/process/control/scantransfer.py +52 -23
  93. tomwer/core/process/control/test/test_concatenate_nxtomos.py +1 -0
  94. tomwer/core/process/control/test/test_email.py +52 -0
  95. tomwer/core/process/control/test/test_h52nx_process.py +106 -0
  96. tomwer/core/process/control/test/test_volume_link.py +5 -4
  97. tomwer/core/process/control/timer.py +27 -6
  98. tomwer/core/process/control/tomoobjserie.py +4 -0
  99. tomwer/core/process/control/volumeselector.py +4 -0
  100. tomwer/core/process/control/volumesymlink.py +47 -8
  101. tomwer/core/process/edit/darkflatpatch.py +49 -8
  102. tomwer/core/process/edit/imagekeyeditor.py +63 -13
  103. tomwer/core/process/reconstruction/axis/__init__.py +1 -1
  104. tomwer/core/process/reconstruction/axis/axis.py +61 -41
  105. tomwer/core/process/reconstruction/axis/params.py +4 -6
  106. tomwer/core/process/reconstruction/darkref/darkrefs.py +53 -16
  107. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +12 -2
  108. tomwer/core/process/reconstruction/lamino/__init__.py +1 -1
  109. tomwer/core/process/reconstruction/lamino/tofu.py +22 -2
  110. tomwer/core/process/reconstruction/nabu/nabucommon.py +93 -14
  111. tomwer/core/process/reconstruction/nabu/nabuscores.py +70 -33
  112. tomwer/core/process/reconstruction/nabu/nabuslices.py +219 -41
  113. tomwer/core/process/reconstruction/nabu/nabuvolume.py +240 -108
  114. tomwer/core/process/reconstruction/nabu/utils.py +10 -36
  115. tomwer/core/process/reconstruction/normalization/normalization.py +10 -3
  116. tomwer/core/process/reconstruction/saaxis/__init__.py +1 -0
  117. tomwer/core/process/reconstruction/saaxis/saaxis.py +564 -376
  118. tomwer/core/process/reconstruction/sadeltabeta/__init__.py +1 -0
  119. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +481 -268
  120. tomwer/core/process/reconstruction/scores/params.py +21 -8
  121. tomwer/core/process/reconstruction/test/test_darkref_copy.py +2 -0
  122. tomwer/core/process/reconstruction/test/test_saaxis.py +21 -8
  123. tomwer/core/process/reconstruction/test/test_sadeltabeta.py +8 -5
  124. tomwer/core/process/script/python.py +7 -2
  125. tomwer/core/process/stitching/nabustitcher.py +10 -3
  126. tomwer/core/process/task.py +2 -9
  127. tomwer/core/process/test/test_axis.py +25 -15
  128. tomwer/core/process/test/test_conditions.py +6 -6
  129. tomwer/core/process/test/test_dark_and_flat.py +20 -15
  130. tomwer/core/process/test/test_data_transfer.py +8 -8
  131. tomwer/core/process/test/test_data_watcher.py +1 -1
  132. tomwer/core/process/test/test_lamino.py +6 -6
  133. tomwer/core/process/test/test_nabu.py +13 -8
  134. tomwer/core/process/test/test_normalization.py +1 -0
  135. tomwer/core/process/test/test_timer.py +6 -6
  136. tomwer/core/process/visualization/dataviewer.py +4 -0
  137. tomwer/core/process/visualization/diffviewer.py +4 -0
  138. tomwer/core/process/visualization/imagestackviewer.py +4 -0
  139. tomwer/core/process/visualization/radiostack.py +4 -0
  140. tomwer/core/process/visualization/samplemoved.py +4 -0
  141. tomwer/core/process/visualization/sinogramviewer.py +4 -0
  142. tomwer/core/process/visualization/slicestack.py +4 -0
  143. tomwer/core/process/visualization/volumeviewer.py +4 -0
  144. tomwer/core/scan/hdf5scan.py +4 -4
  145. tomwer/core/scan/scanbase.py +5 -1
  146. tomwer/core/scan/test/test_process_registration.py +9 -9
  147. tomwer/core/settings.py +59 -1
  148. tomwer/core/test/test_lamino.py +2 -1
  149. tomwer/core/utils/__init__.py +16 -0
  150. tomwer/core/utils/locker.py +0 -1
  151. tomwer/core/utils/resource.py +6 -11
  152. tomwer/core/utils/scanutils.py +2 -0
  153. tomwer/gui/cluster/slurm.py +91 -7
  154. tomwer/gui/cluster/supervisor.py +16 -11
  155. tomwer/gui/cluster/test/test_cluster.py +16 -1
  156. tomwer/gui/conditions/filter.py +3 -3
  157. tomwer/gui/control/datalist.py +24 -11
  158. tomwer/gui/control/email.py +183 -0
  159. tomwer/gui/control/reducedarkflatselector.py +545 -0
  160. tomwer/gui/control/singletomoobj.py +23 -1
  161. tomwer/gui/control/test/test_email.py +35 -0
  162. tomwer/gui/control/test/test_reducedarkflat_selector.py +280 -0
  163. tomwer/gui/reconstruction/axis/CompareImages.py +1 -1
  164. tomwer/gui/reconstruction/axis/axis.py +10 -6
  165. tomwer/gui/reconstruction/axis/radioaxis.py +14 -6
  166. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +2 -0
  167. tomwer/gui/reconstruction/darkref/darkrefwidget.py +4 -4
  168. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +3 -1
  169. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +34 -33
  170. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +1 -1
  171. tomwer/gui/reconstruction/normalization/intensity.py +5 -5
  172. tomwer/gui/reconstruction/saaxis/corrangeselector.py +1 -0
  173. tomwer/gui/reconstruction/saaxis/saaxis.py +6 -6
  174. tomwer/gui/reconstruction/sadeltabeta/saadeltabeta.py +6 -6
  175. tomwer/gui/reconstruction/scores/scoreplot.py +6 -4
  176. tomwer/gui/samplemoved/__init__.py +2 -2
  177. tomwer/gui/stackplot.py +18 -7
  178. tomwer/gui/stacks.py +2 -2
  179. tomwer/gui/stitching/stitchandbackground.py +2 -2
  180. tomwer/gui/stitching/stitching.py +1 -1
  181. tomwer/gui/stitching/stitching_raw.py +1 -1
  182. tomwer/gui/utils/__init__.py +1 -85
  183. tomwer/gui/utils/illustrations.py +1 -1
  184. tomwer/gui/utils/inputwidget.py +41 -36
  185. tomwer/gui/utils/slider.py +2 -2
  186. tomwer/gui/utils/utils.py +93 -0
  187. tomwer/gui/visualization/dataviewer.py +8 -5
  188. tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
  189. tomwer/gui/visualization/reconstructionparameters.py +26 -6
  190. tomwer/gui/visualization/sinogramviewer.py +7 -1
  191. tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -4
  192. tomwer/gui/visualization/volumeviewer.py +2 -0
  193. tomwer/resources/__init__.py +55 -43
  194. tomwer/resources/gui/icons/compose.png +0 -0
  195. tomwer/resources/gui/icons/compose.svg +75 -0
  196. tomwer/synctools/datatransfert.py +3 -1
  197. tomwer/synctools/stacks/edit/darkflatpatch.py +39 -34
  198. tomwer/synctools/stacks/edit/imagekeyeditor.py +8 -27
  199. tomwer/synctools/stacks/processingstack.py +45 -9
  200. tomwer/synctools/stacks/reconstruction/axis.py +6 -5
  201. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -0
  202. tomwer/synctools/stacks/reconstruction/lamino.py +3 -3
  203. tomwer/synctools/stacks/reconstruction/nabu.py +49 -140
  204. tomwer/synctools/stacks/reconstruction/normalization.py +1 -0
  205. tomwer/synctools/stacks/reconstruction/saaxis.py +19 -33
  206. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +16 -32
  207. tomwer/synctools/test/test_darkRefs.py +19 -10
  208. tomwer/synctools/test/test_foldertransfer.py +7 -7
  209. tomwer/third_party/nabu/preproc/phase.py +6 -8
  210. tomwer/third_party/nabu/utils.py +2 -3
  211. tomwer/version.py +1 -1
  212. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/METADATA +15 -54
  213. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/RECORD +219 -192
  214. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/WHEEL +1 -1
  215. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/entry_points.txt +3 -3
  216. /tomwer-1.2.0a1-py3.9-nspkg.pth → /tomwer-1.2.0a3-py3.11-nspkg.pth +0 -0
  217. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/LICENSE +0 -0
  218. {tomwer-1.2.0a1.dist-info → tomwer-1.2.0a3.dist-info}/namespace_packages.txt +0 -0
  219. {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 VolumeSymbolicLinkProcess
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 = VolumeSymbolicLinkProcess(inputs={"data": self._scan})
61
- vlink_process.set_configuration(
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 Timer(Task, input_names=("data",), output_names=("data",)):
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._waiting_time
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._waiting_time = wait
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.waiting_time)
81
- if self._return_dict:
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)
@@ -4,5 +4,9 @@ from ewokscore.task import Task as EwoksTask
4
4
  class _TomoobjseriePlaceHolder(
5
5
  EwoksTask, input_names=["serie"], output_names=["serie"]
6
6
  ):
7
+ """
8
+ task to define a tomography 'serie'
9
+ """
10
+
7
11
  def run(self):
8
12
  self.outputs.serie = self.inputs.serie
@@ -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 VolumeSymbolicLinkProcess(Task, input_names=("data",), output_names=("data",)):
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
- if self._output_type is OutputType.STATIC:
137
- if self._output_folder is None:
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 self._output_type is OutputType.ONE_LEVEL_UPPER:
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, self._output_type.value)
173
+ os.path.join(output_folder, output_type.value)
152
174
  )
153
175
  else:
154
- raise ValueError(f"output type {self._output_type.value} is not managed")
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.outputs.data = scan
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 DarkFlatPatch(Task, input_names=("data",), output_names=("data",)):
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.get_configuration()
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.outputs.data = scan
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 ImageKeyEditor(Task, input_names=("data",), output_names=("data",)):
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
- change_image_key_control(scan=scan, config=self.get_configuration())
128
- config = self.get_configuration()
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.outputs.data = scan
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, input_names=("data", "operations"), output_names=("data",)
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.outputs.data = scan
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 AxisProcess # noqa F401
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 nabu.version > "2021.1.0" and isinstance(scan, HDF5TomoScan):
111
- # since this version nabu does not the load of dark / flat mean/median
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 = AxisProcess.get_inputs(scan=scan)
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 = AxisProcess.get_inputs(scan=scan)
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 = AxisProcess.get_inputs(scan=scan)
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 = AxisProcess.get_inputs(scan=scan)
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 AxisProcess(
582
- Task, SuperviseProcess, input_names=("data",), output_names=("data",)
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
- self.outputs.data = scan_res
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 = AxisProcess.get_inputs_urls(scan=scan)
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 _return_dict activated
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
- if self._return_dict:
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 = AxisProcess._get_process_nodes(
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 = AxisProcess._get_process_nodes(
969
- root_node=h5f[entry], process=AxisProcess
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)