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
@@ -39,8 +39,13 @@ from nabu.pipeline.config import generate_nabu_configfile
|
|
39
39
|
from nabu.pipeline.fullfield.nabu_config import (
|
40
40
|
nabu_config as nabu_fullfield_default_config,
|
41
41
|
)
|
42
|
-
from processview.core.manager.manager import ProcessManager
|
42
|
+
from processview.core.manager.manager import ProcessManager, DatasetState
|
43
|
+
from processview.core.superviseprocess import SuperviseProcess
|
44
|
+
|
43
45
|
from silx.io.utils import h5py_read_dataset
|
46
|
+
from silx.utils.deprecation import deprecated_warning
|
47
|
+
|
48
|
+
from tomoscan.io import HDF5File
|
44
49
|
|
45
50
|
from tomwer.core.cluster.cluster import SlurmClusterConfiguration
|
46
51
|
from tomwer.core.futureobject import FutureTomwerObject
|
@@ -52,6 +57,8 @@ from tomwer.core.scan.scanfactory import ScanFactory
|
|
52
57
|
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
53
58
|
from tomwer.io.utils.h5pyutils import EntryReader
|
54
59
|
from tomwer.utils import docstring
|
60
|
+
from tomwer.core.utils import concatenate_dict
|
61
|
+
from tomwer.io.utils import format_stderr_stdout
|
55
62
|
|
56
63
|
from . import settings, utils
|
57
64
|
from .nabucommon import ResultsLocalRun, ResultSlurmRun, _NabuBaseReconstructor
|
@@ -93,23 +100,23 @@ def run_volume_reconstruction(
|
|
93
100
|
else:
|
94
101
|
target = Target.SLURM
|
95
102
|
|
96
|
-
# beam shape is not directly used by nabu (uses ctf_geometry directly)
|
97
|
-
config.get("phase", {}).pop("beam_shape", None)
|
98
|
-
|
99
|
-
config_volume = copy.copy(config)
|
100
|
-
config_nabu_slices = copy.deepcopy(scan.nabu_recons_params)
|
101
|
-
if "tomwer_slices" in config_nabu_slices:
|
102
|
-
|
103
|
-
|
104
|
-
if "phase" in config_nabu_slices and "delta_beta" in config_nabu_slices["phase"]:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
scan.clear_latest_vol_reconstructions()
|
103
|
+
# # beam shape is not directly used by nabu (uses ctf_geometry directly)
|
104
|
+
# config.get("phase", {}).pop("beam_shape", None)
|
105
|
+
|
106
|
+
# config_volume = copy.copy(config)
|
107
|
+
# config_nabu_slices = copy.deepcopy(scan.nabu_recons_params)
|
108
|
+
# if "tomwer_slices" in config_nabu_slices:
|
109
|
+
# del config_nabu_slices["tomwer_slices"]
|
110
|
+
|
111
|
+
# if "phase" in config_nabu_slices and "delta_beta" in config_nabu_slices["phase"]:
|
112
|
+
# pag_dbs = config_nabu_slices["phase"]["delta_beta"]
|
113
|
+
# if isinstance(pag_dbs, str):
|
114
|
+
# pag_dbs = utils.retrieve_lst_of_value_from_str(pag_dbs, type_=float)
|
115
|
+
# if len(pag_dbs) > 1:
|
116
|
+
# raise ValueError(
|
117
|
+
# "Several value of delta / beta found for volume reconstruction"
|
118
|
+
# )
|
119
|
+
# scan.clear_latest_vol_reconstructions()
|
113
120
|
|
114
121
|
if process_id is not None:
|
115
122
|
try:
|
@@ -121,8 +128,7 @@ def run_volume_reconstruction(
|
|
121
128
|
|
122
129
|
volume_reconstructor = VolumeRunner(
|
123
130
|
scan=scan,
|
124
|
-
|
125
|
-
config_slices=config_nabu_slices,
|
131
|
+
config_nabu=config,
|
126
132
|
cluster_config=cluster_config,
|
127
133
|
dry_run=dry_run,
|
128
134
|
target=target,
|
@@ -171,6 +177,7 @@ def run_volume_reconstruction(
|
|
171
177
|
if res is not None
|
172
178
|
else []
|
173
179
|
)
|
180
|
+
|
174
181
|
return succeed, stdouts, stderrs, configs, future_tomo_obj
|
175
182
|
|
176
183
|
|
@@ -185,8 +192,7 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
185
192
|
def __init__(
|
186
193
|
self,
|
187
194
|
scan: TomwerScanBase,
|
188
|
-
|
189
|
-
config_slices: dict,
|
195
|
+
config_nabu,
|
190
196
|
cluster_config: Optional[dict],
|
191
197
|
dry_run: bool,
|
192
198
|
target: Target,
|
@@ -199,58 +205,44 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
199
205
|
cluster_config=cluster_config,
|
200
206
|
process_name=process_name,
|
201
207
|
)
|
202
|
-
self.
|
203
|
-
self._config_slices = config_slices
|
208
|
+
self._config = config_nabu
|
204
209
|
|
205
210
|
@property
|
206
|
-
def
|
207
|
-
return self.
|
208
|
-
|
209
|
-
@property
|
210
|
-
def config_slices(self):
|
211
|
-
return self._config_slices
|
211
|
+
def configuration(self):
|
212
|
+
return self._config
|
212
213
|
|
213
214
|
@docstring(_NabuBaseReconstructor)
|
214
215
|
def run(self) -> Iterable:
|
215
216
|
dataset_params = self.scan.get_nabu_dataset_info()
|
216
|
-
if "dataset" in self.
|
217
|
-
dataset_params.update(self.
|
218
|
-
self.
|
219
|
-
self.
|
217
|
+
if "dataset" in self.configuration:
|
218
|
+
dataset_params.update(self.configuration["dataset"])
|
219
|
+
self.configuration["dataset"] = dataset_params
|
220
|
+
self.configuration["resources"] = utils.get_nabu_resources_desc(
|
220
221
|
scan=self.scan, workers=1, method="local"
|
221
222
|
)
|
222
223
|
|
223
224
|
# force overwrite results
|
224
|
-
if "output" not in self.
|
225
|
-
self.
|
226
|
-
config_slices,
|
227
|
-
|
228
|
-
|
225
|
+
if "output" not in self.configuration:
|
226
|
+
self.configuration["output"] = {}
|
227
|
+
config_slices, cfg_folder = self._treateOutputConfig(self.configuration)
|
228
|
+
|
229
|
+
# force overwriting results
|
229
230
|
config_slices["output"].update({"overwrite_results": 1})
|
230
231
|
|
231
232
|
# check and clamp `start_z` and `end_z`
|
232
|
-
if "reconstruction" in self.
|
233
|
+
if "reconstruction" in self.configuration:
|
233
234
|
for key in ("start_z", "end_z"):
|
234
|
-
value =
|
235
|
+
value = config_slices["reconstruction"].get(key)
|
235
236
|
if value is None:
|
236
237
|
continue
|
237
238
|
|
238
239
|
value = int(value)
|
239
|
-
if value < 0:
|
240
|
-
_logger.warning(f"{key} < 0 found. Set it to 0 (vs value)")
|
241
|
-
value = 0
|
242
240
|
if self.scan.dim_2 is not None and value >= self.scan.dim_2:
|
243
241
|
_logger.warning(
|
244
242
|
f"{key} > max_size (radio height: {self.scan.dim_2}). Set it to -1 (maximum)"
|
245
243
|
)
|
246
244
|
value = -1
|
247
|
-
|
248
|
-
|
249
|
-
cfg_folder = os.path.join(
|
250
|
-
config_slices["output"]["location"], settings.NABU_CFG_FILE_FOLDER
|
251
|
-
)
|
252
|
-
if not os.path.exists(cfg_folder):
|
253
|
-
os.makedirs(cfg_folder)
|
245
|
+
config_slices["reconstruction"][key] = value
|
254
246
|
|
255
247
|
name = (
|
256
248
|
config_slices["output"]["file_prefix"] + settings.NABU_CONFIG_FILE_EXTENSION
|
@@ -260,6 +252,9 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
260
252
|
conf_file = os.path.join(cfg_folder, name)
|
261
253
|
_logger.info(f"{self.scan}: create {conf_file}")
|
262
254
|
|
255
|
+
# make sure output location exists
|
256
|
+
os.makedirs(config_slices["output"]["location"], exist_ok=True)
|
257
|
+
|
263
258
|
# add some tomwer metadata and save the configuration
|
264
259
|
# note: for now the section is ignored by nabu but shouldn't stay that way
|
265
260
|
with utils.TomwerInfo(config_slices) as config_to_dump:
|
@@ -269,20 +264,19 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
269
264
|
config=config_to_dump,
|
270
265
|
options_level="advanced",
|
271
266
|
)
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
)
|
267
|
+
return tuple(
|
268
|
+
[
|
269
|
+
self._process_config(
|
270
|
+
config_to_dump=config_to_dump,
|
271
|
+
config_file=conf_file,
|
272
|
+
start_z=config_to_dump["reconstruction"]["start_z"],
|
273
|
+
end_z=config_to_dump["reconstruction"]["end_z"],
|
274
|
+
info="nabu volume reconstruction",
|
275
|
+
file_format=config_slices["output"]["file_format"],
|
276
|
+
process_name=self.process_name,
|
277
|
+
)
|
278
|
+
]
|
279
|
+
)
|
286
280
|
|
287
281
|
@docstring(_NabuBaseReconstructor)
|
288
282
|
def _get_futures_slurm_callback(self, config_to_dump) -> tuple:
|
@@ -316,26 +310,27 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
316
310
|
|
317
311
|
return (CallBack(callback, self.scan),)
|
318
312
|
|
319
|
-
def _treateOutputConfig(self,
|
313
|
+
def _treateOutputConfig(self, config) -> tuple:
|
320
314
|
"""
|
321
315
|
|
322
316
|
:return: (nabu config dict, nabu extra options)
|
323
317
|
"""
|
324
|
-
|
325
|
-
|
318
|
+
config = copy.deepcopy(config)
|
319
|
+
config, nabu_cfg_folder = super()._treateOutputSliceConfig(config)
|
320
|
+
os.makedirs(config["output"]["location"], exist_ok=True)
|
321
|
+
|
326
322
|
# adapt config_s to specific volume treatment
|
327
|
-
if "postproc" in
|
328
|
-
|
323
|
+
if "postproc" in config:
|
324
|
+
config["postproc"] = config["postproc"]
|
329
325
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
del extra_opts["end_z"]
|
326
|
+
if "start_z" in config:
|
327
|
+
config["reconstruction"]["start_z"] = config["start_z"]
|
328
|
+
del config["start_z"]
|
329
|
+
if "end_z" in config:
|
330
|
+
config["reconstruction"]["end_z"] = config["end_z"]
|
331
|
+
del config["end_z"]
|
337
332
|
|
338
|
-
return
|
333
|
+
return config, nabu_cfg_folder
|
339
334
|
|
340
335
|
@docstring(_NabuBaseReconstructor)
|
341
336
|
def _get_file_basename_reconstruction(self, pag, db, ctf):
|
@@ -354,8 +349,16 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
354
349
|
if isinstance(self.scan, HDF5TomoScan):
|
355
350
|
basename, _ = os.path.splitext(self.scan.master_file)
|
356
351
|
basename = os.path.basename(basename)
|
352
|
+
try:
|
353
|
+
# if there is more than one entry in the file append the entry name to the file basename
|
354
|
+
with HDF5File(self.scan.master_file, mode="r") as h5f:
|
355
|
+
if len(h5f.keys()) > 1:
|
356
|
+
basename = "_".join((basename, self.scan.entry.strip("/")))
|
357
|
+
except Exception:
|
358
|
+
pass
|
357
359
|
else:
|
358
360
|
basename = os.path.basename(self.scan.path)
|
361
|
+
|
359
362
|
if pag:
|
360
363
|
return "_".join((basename + "pag", "db" + str(db).zfill(4), "vol"))
|
361
364
|
elif ctf:
|
@@ -364,15 +367,27 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
364
367
|
return "_".join((basename, "vol"))
|
365
368
|
|
366
369
|
|
367
|
-
class
|
370
|
+
class NabuVolumeTask(
|
368
371
|
Task,
|
369
|
-
|
370
|
-
|
371
|
-
output_names=("data", "volumes"),
|
372
|
+
SuperviseProcess,
|
373
|
+
input_names=("data", "nabu_params"),
|
374
|
+
output_names=("data", "volumes", "future_tomo_obj"),
|
375
|
+
optional_input_names=(
|
376
|
+
"dry_run",
|
377
|
+
"nabu_extra_params", # some parameter that must update 'nabu_params' before launching the reconstruction. Such as z range...
|
378
|
+
"serialize_output_data",
|
379
|
+
),
|
372
380
|
):
|
373
381
|
def __init__(
|
374
|
-
self,
|
382
|
+
self,
|
383
|
+
process_id=None,
|
384
|
+
varinfo=None,
|
385
|
+
inputs=None,
|
386
|
+
node_id=None,
|
387
|
+
node_attrs=None,
|
388
|
+
execinfo=None,
|
375
389
|
):
|
390
|
+
SuperviseProcess.__init__(self, process_id=process_id)
|
376
391
|
Task.__init__(
|
377
392
|
self,
|
378
393
|
varinfo=varinfo,
|
@@ -382,15 +397,40 @@ class NabuVolume(
|
|
382
397
|
execinfo=execinfo,
|
383
398
|
)
|
384
399
|
self._dry_run = inputs.get("dry_run", False)
|
400
|
+
self._current_processing = None
|
385
401
|
|
386
402
|
def run(self):
|
387
403
|
scan = data_identifier_to_scan(self.inputs.data)
|
388
404
|
if scan is None:
|
389
405
|
self.outputs.data = None
|
390
406
|
return
|
391
|
-
|
392
|
-
|
393
|
-
|
407
|
+
|
408
|
+
# update scan reconstruction parameters used
|
409
|
+
nabu_params = concatenate_dict(
|
410
|
+
copy.deepcopy(self.inputs.nabu_params),
|
411
|
+
self.get_input_value("nabu_extra_params", dict()),
|
412
|
+
)
|
413
|
+
scan.nabu_recons_params = nabu_params
|
414
|
+
scan.clear_latest_vol_reconstructions()
|
415
|
+
|
416
|
+
cluster_config = nabu_params.pop("cluster_config", None)
|
417
|
+
if cluster_config == {}:
|
418
|
+
cluster_config = None
|
419
|
+
elif isinstance(cluster_config, SlurmClusterConfiguration):
|
420
|
+
cluster_config = cluster_config.to_dict()
|
421
|
+
|
422
|
+
if "tomwer_slices" in nabu_params:
|
423
|
+
del nabu_params["tomwer_slices"]
|
424
|
+
|
425
|
+
if "phase" in nabu_params and "delta_beta" in nabu_params["phase"]:
|
426
|
+
pag_dbs = nabu_params["phase"]["delta_beta"]
|
427
|
+
if isinstance(pag_dbs, str):
|
428
|
+
pag_dbs = utils.retrieve_lst_of_value_from_str(pag_dbs, type_=float)
|
429
|
+
if len(pag_dbs) > 1:
|
430
|
+
raise ValueError(
|
431
|
+
"Several value of delta / beta found for volume reconstruction"
|
432
|
+
)
|
433
|
+
|
394
434
|
if isinstance(scan, TomwerScanBase):
|
395
435
|
scan = scan
|
396
436
|
elif isinstance(scan, dict):
|
@@ -398,30 +438,94 @@ class NabuVolume(
|
|
398
438
|
else:
|
399
439
|
raise ValueError(f"input type {scan} is not managed")
|
400
440
|
|
401
|
-
if
|
402
|
-
|
403
|
-
|
441
|
+
if cluster_config is None:
|
442
|
+
target = Target.LOCAL
|
443
|
+
else:
|
444
|
+
target = Target.SLURM
|
404
445
|
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
self.register_process(
|
416
|
-
process_file=scan.process_file,
|
417
|
-
entry=entry,
|
418
|
-
configuration=self.get_configuration(),
|
419
|
-
results={},
|
420
|
-
process_index=scan.pop_process_index(),
|
421
|
-
overwrite=True,
|
446
|
+
state = None
|
447
|
+
details = None
|
448
|
+
try:
|
449
|
+
self._current_processing = VolumeRunner(
|
450
|
+
scan=scan,
|
451
|
+
config_nabu=nabu_params,
|
452
|
+
cluster_config=cluster_config,
|
453
|
+
dry_run=self._dry_run,
|
454
|
+
target=target,
|
455
|
+
process_name=self.program_name,
|
422
456
|
)
|
423
|
-
|
457
|
+
res = self._current_processing.run()[0]
|
458
|
+
except Exception as e:
|
459
|
+
_logger.error(f"Failed to process {scan}. Error is {e}")
|
460
|
+
state = DatasetState.FAILED
|
461
|
+
details = None
|
462
|
+
future_tomo_obj = None
|
463
|
+
else:
|
464
|
+
# tag latest reconstructions
|
465
|
+
if isinstance(res, ResultsLocalRun) and res.results_urls is not None:
|
466
|
+
scan.set_latest_vol_reconstructions(res.results_urls)
|
467
|
+
# create future if needed
|
468
|
+
if isinstance(res, ResultSlurmRun):
|
469
|
+
future_tomo_obj = FutureTomwerObject(
|
470
|
+
tomo_obj=scan,
|
471
|
+
futures=tuple(res.future_slurm_jobs),
|
472
|
+
process_requester_id=self.process_id,
|
473
|
+
)
|
474
|
+
|
475
|
+
else:
|
476
|
+
future_tomo_obj = None
|
477
|
+
|
478
|
+
if self._cancelled:
|
479
|
+
state = DatasetState.CANCELLED
|
480
|
+
details = "cancelled by user"
|
481
|
+
_logger.info(f"Slices computation for {scan} cancelled")
|
482
|
+
else:
|
483
|
+
succeed = res.success
|
484
|
+
stdouts = (
|
485
|
+
[
|
486
|
+
res.std_out,
|
487
|
+
]
|
488
|
+
if hasattr(res, "std_out")
|
489
|
+
else []
|
490
|
+
)
|
491
|
+
stderrs = (
|
492
|
+
[
|
493
|
+
res.std_err,
|
494
|
+
]
|
495
|
+
if hasattr(res, "std_err")
|
496
|
+
else []
|
497
|
+
)
|
498
|
+
|
499
|
+
if not succeed:
|
500
|
+
mess = f"Volume computed for {scan} failed."
|
501
|
+
_logger.processFailed(mess)
|
502
|
+
state = DatasetState.FAILED
|
503
|
+
else:
|
504
|
+
mess = f"Volume computed for {scan}."
|
505
|
+
_logger.processSucceed(mess)
|
506
|
+
state = DatasetState.SUCCEED
|
507
|
+
|
508
|
+
# format stderr and stdout
|
509
|
+
elmts = [
|
510
|
+
format_stderr_stdout(stderr=stderr, stdout=stdout)
|
511
|
+
for stderr, stdout in zip(stderrs, stdouts)
|
512
|
+
]
|
513
|
+
elmts.insert(0, mess)
|
514
|
+
details = "\n".join(elmts)
|
515
|
+
finally:
|
516
|
+
ProcessManager().notify_dataset_state(
|
517
|
+
dataset=scan,
|
518
|
+
process=self,
|
519
|
+
state=state,
|
520
|
+
details=details,
|
521
|
+
)
|
522
|
+
|
523
|
+
if self.get_input_value("serialize_output_data", True):
|
524
|
+
self.outputs.data = scan.to_dict()
|
525
|
+
else:
|
526
|
+
self.outputs.data = scan
|
424
527
|
self.outputs.volumes = scan.latest_vol_reconstructions
|
528
|
+
self.outputs.future_tomo_obj = future_tomo_obj
|
425
529
|
|
426
530
|
def set_configuration(self, configuration: dict) -> None:
|
427
531
|
Task.set_configuration(self, configuration=configuration)
|
@@ -446,7 +550,35 @@ class NabuVolume(
|
|
446
550
|
@staticmethod
|
447
551
|
def retrieve_last_relative_cor(scan):
|
448
552
|
with EntryReader(scan.process_file_url) as h5f:
|
449
|
-
latest_nabu_node = Task.get_most_recent_process(h5f,
|
553
|
+
latest_nabu_node = Task.get_most_recent_process(h5f, NabuVolumeTask)
|
450
554
|
path = "configuration/reconstruction/rotation_axis_position"
|
451
555
|
if path in latest_nabu_node:
|
452
556
|
return h5py_read_dataset(latest_nabu_node[path])
|
557
|
+
|
558
|
+
def cancel(self):
|
559
|
+
"""
|
560
|
+
stop current processing
|
561
|
+
"""
|
562
|
+
self._cancelled = True
|
563
|
+
if self._current_processing is not None:
|
564
|
+
self._current_processing.cancel()
|
565
|
+
|
566
|
+
|
567
|
+
class NabuVolume(NabuVolumeTask):
|
568
|
+
def __init__(
|
569
|
+
self,
|
570
|
+
process_id=None,
|
571
|
+
varinfo=None,
|
572
|
+
inputs=None,
|
573
|
+
node_id=None,
|
574
|
+
node_attrs=None,
|
575
|
+
execinfo=None,
|
576
|
+
):
|
577
|
+
deprecated_warning(
|
578
|
+
name="tomwer.core.process.reconstruction.nabu.nabuvolume.NabuVolume",
|
579
|
+
type_="class",
|
580
|
+
reason="improve readibility",
|
581
|
+
since_version="1.2",
|
582
|
+
replacement="NabuVolumeTask",
|
583
|
+
)
|
584
|
+
super().__init__(process_id, varinfo, inputs, node_id, node_attrs, execinfo)
|
@@ -159,7 +159,7 @@ def get_recons_volume_identifier(
|
|
159
159
|
if file_format in ("hdf5", "h5", "hdf"):
|
160
160
|
if slice_index is not None:
|
161
161
|
# case of a single hdf5 file
|
162
|
-
file_name = "_".join((file_prefix, str(slice_index).zfill(
|
162
|
+
file_name = "_".join((file_prefix, str(slice_index).zfill(6)))
|
163
163
|
else:
|
164
164
|
file_name = file_prefix
|
165
165
|
file_name = ".".join((file_name, file_format))
|
@@ -179,23 +179,13 @@ def get_recons_volume_identifier(
|
|
179
179
|
elif file_format in ("vol", "raw"):
|
180
180
|
if slice_index is not None:
|
181
181
|
# case of a single hdf5 file
|
182
|
-
file_name = "_".join((file_prefix, str(slice_index).zfill(
|
182
|
+
file_name = "_".join((file_prefix, str(slice_index).zfill(6)))
|
183
183
|
else:
|
184
184
|
file_name = file_prefix
|
185
|
-
# on 2022.3.x the location seems invalid for nabu. Add this second location to
|
186
|
-
# handle most of the case.
|
187
|
-
fix_nabu = os.path.join(file_prefix, file_name)
|
188
|
-
|
189
185
|
file_name = ".".join((file_name, file_format))
|
190
186
|
file_path = os.path.join(location, file_name)
|
191
187
|
|
192
|
-
|
193
|
-
file_path_fix_nabu = os.path.join(location, file_name_fix_nabu)
|
194
|
-
|
195
|
-
volumes = (
|
196
|
-
RawVolume(file_path=file_path_fix_nabu),
|
197
|
-
RawVolume(file_path=file_path),
|
198
|
-
)
|
188
|
+
volumes = (RawVolume(file_path=file_path),)
|
199
189
|
elif file_format in ("jp2", "jp2k", "edf", "tiff"):
|
200
190
|
if file_format in ("jp2k", "jp2"):
|
201
191
|
constructor = JP2KVolume
|
@@ -205,31 +195,15 @@ def get_recons_volume_identifier(
|
|
205
195
|
constructor = TIFFVolume
|
206
196
|
else:
|
207
197
|
raise NotImplementedError
|
208
|
-
output_extension = file_format
|
209
198
|
basename = file_prefix
|
199
|
+
file_path = location
|
200
|
+
volumes = (
|
201
|
+
constructor(
|
202
|
+
folder=location,
|
203
|
+
volume_basename=basename,
|
204
|
+
),
|
205
|
+
)
|
210
206
|
|
211
|
-
if slice_index is None and start_z is None and end_z is None:
|
212
|
-
# if this is a single slice
|
213
|
-
file_path = ".".join(
|
214
|
-
(
|
215
|
-
os.path.join(location, file_prefix, file_prefix),
|
216
|
-
output_extension,
|
217
|
-
)
|
218
|
-
)
|
219
|
-
# TODO: in the future we might want to provide data_slice according to z values
|
220
|
-
volumes = (
|
221
|
-
constructor(
|
222
|
-
folder=os.path.join(location, file_prefix),
|
223
|
-
volume_basename=basename,
|
224
|
-
),
|
225
|
-
)
|
226
|
-
else:
|
227
|
-
volumes = (
|
228
|
-
constructor(
|
229
|
-
folder=os.path.join(location, file_prefix),
|
230
|
-
volume_basename=basename,
|
231
|
-
),
|
232
|
-
)
|
233
207
|
# case of the multitiff. Not handled by tomwer
|
234
208
|
# elif file_format == "tiff":
|
235
209
|
# # for single frame tiff nabu uses another convention by saving it 'directly'.
|
@@ -55,10 +55,14 @@ _logger = logging.getLogger(__name__)
|
|
55
55
|
|
56
56
|
|
57
57
|
class SinoNormalizationTask(
|
58
|
-
Task,
|
58
|
+
Task,
|
59
|
+
SuperviseProcess,
|
60
|
+
input_names=("data",),
|
61
|
+
output_names=("data",),
|
62
|
+
optional_input_names=("serialize_output_data",),
|
59
63
|
):
|
60
64
|
"""
|
61
|
-
Task to define the normalization to apply to a sinogram
|
65
|
+
Task to define the normalization to apply to a sinogram before reconstructing it with nabu
|
62
66
|
"""
|
63
67
|
|
64
68
|
def __init__(
|
@@ -148,7 +152,10 @@ class SinoNormalizationTask(
|
|
148
152
|
else:
|
149
153
|
final_norm_info.update({"tomwer_processing_res_code": True})
|
150
154
|
scan.intensity_normalization.set_extra_infos(final_norm_info)
|
151
|
-
self.
|
155
|
+
if self.get_input_value("serialize_output_data", True):
|
156
|
+
self.outputs.data = scan.to_dict()
|
157
|
+
else:
|
158
|
+
self.outputs.data = scan
|
152
159
|
|
153
160
|
def _compute_from_manual_roi(self, scan):
|
154
161
|
params = SinoNormalizationParams.from_dict(self.get_configuration())
|