tomwer 1.3.4__py3-none-any.whl → 1.3.26__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/widgets/reconstruction/DarkRefAndCopyOW.py +1 -0
- orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +184 -184
- tomwer/app/canvas_launcher/mainwindow.py +0 -1
- tomwer/app/zstitching.py +0 -1
- tomwer/core/cluster/cluster.py +0 -9
- tomwer/core/process/control/datalistener/datalistener.py +15 -12
- tomwer/core/process/control/datawatcher/edfdwprocess.py +0 -9
- tomwer/core/process/reconstruction/axis/axis.py +3 -3
- tomwer/core/process/reconstruction/axis/params.py +3 -3
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +37 -8
- tomwer/core/process/reconstruction/nabu/nabucommon.py +3 -4
- tomwer/core/process/reconstruction/nabu/nabuscores.py +1 -0
- tomwer/core/process/reconstruction/nabu/nabuslices.py +6 -52
- tomwer/core/process/reconstruction/nabu/nabuvolume.py +2 -5
- tomwer/core/process/reconstruction/nabu/utils.py +10 -2
- tomwer/core/process/reconstruction/saaxis/saaxis.py +2 -0
- tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +2 -0
- tomwer/core/process/task.py +4 -2
- tomwer/core/process/test/test_data_transfer.py +4 -3
- tomwer/core/scan/blissscan.py +3 -3
- tomwer/core/scan/nxtomoscan.py +2 -2
- tomwer/core/scan/scanbase.py +5 -6
- tomwer/core/utils/scanutils.py +5 -1
- tomwer/gui/cluster/slurm.py +1 -21
- tomwer/gui/cluster/test/test_cluster.py +0 -1
- tomwer/gui/control/datawatcher/datawatcher.py +1 -24
- tomwer/gui/control/reducedarkflatselector.py +2 -2
- tomwer/gui/control/selectorwidgetbase.py +3 -1
- tomwer/gui/edit/dkrfpatch.py +4 -4
- tomwer/gui/edit/nxtomoeditor.py +28 -20
- tomwer/gui/edit/nxtomowarmer.py +3 -2
- tomwer/gui/edit/test/test_nx_editor.py +58 -1
- tomwer/gui/imagefromfile.py +2 -2
- tomwer/gui/qfolderdialog.py +4 -0
- tomwer/gui/reconstruction/axis/axis.py +16 -13
- tomwer/gui/reconstruction/axis/radioaxis.py +3 -1
- tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +11 -0
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +16 -14
- tomwer/gui/reconstruction/saaxis/saaxis.py +2 -2
- tomwer/gui/stitching/stitching.py +8 -3
- tomwer/gui/visualization/dataviewer.py +27 -15
- tomwer/gui/visualization/diffviewer/diffviewer.py +9 -8
- tomwer/gui/visualization/volumeviewer.py +10 -4
- tomwer/io/utils/h5pyutils.py +3 -7
- tomwer/io/utils/utils.py +3 -3
- tomwer/synctools/stacks/reconstruction/castvolume.py +20 -5
- tomwer/synctools/stacks/reconstruction/dkrefcopy.py +10 -0
- tomwer/tests/datasets.py +5 -1
- tomwer/utils.py +1 -4
- tomwer/version.py +1 -1
- tomwer-1.3.26-py3.11-nspkg.pth +1 -0
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/METADATA +34 -48
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/RECORD +58 -58
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/WHEEL +1 -1
- tomwer-1.3.4-py3.11-nspkg.pth +0 -1
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/LICENSE +0 -0
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/entry_points.txt +0 -0
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/namespace_packages.txt +0 -0
- {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/top_level.txt +0 -0
@@ -34,11 +34,13 @@ __date__ = "17/08/2021"
|
|
34
34
|
|
35
35
|
import logging
|
36
36
|
import os
|
37
|
+
import h5py
|
37
38
|
import tempfile
|
38
39
|
from typing import Union
|
39
40
|
|
40
41
|
from silx.io.dictdump import dicttoh5, h5todict
|
41
42
|
from silx.io.url import DataUrl
|
43
|
+
from silx.io.utils import open as open_hdf5
|
42
44
|
from tomoscan.esrf.scan.utils import (
|
43
45
|
copy_h5_dict_darks_to,
|
44
46
|
copy_h5_dict_flats_to,
|
@@ -197,10 +199,37 @@ class DarkRefsCopy(DarkRefsTask):
|
|
197
199
|
update_mode="replace",
|
198
200
|
)
|
199
201
|
|
202
|
+
def clear_cache(self):
|
203
|
+
"""
|
204
|
+
remove the file used to cache the reduced darks / flats.
|
205
|
+
This can be used in the case it contain unrelevant data. Like frame with another shape...
|
206
|
+
"""
|
207
|
+
cache_file = DarkRefsCopy.get_save_file(self._savedir)
|
208
|
+
if os.path.exists(cache_file):
|
209
|
+
os.remove(cache_file)
|
210
|
+
|
211
|
+
def _clear_cache_data_path(self, file_path: str, data_path: str):
|
212
|
+
if not os.path.exists(file_path):
|
213
|
+
return
|
214
|
+
with h5py.File(file_path, mode="a") as h5f:
|
215
|
+
if data_path in h5f:
|
216
|
+
del h5f[data_path]
|
217
|
+
|
200
218
|
def set_darks_and_flats_from_scan(self, scan: TomwerScanBase) -> bool:
|
201
|
-
|
219
|
+
has_flats = scan.reduced_flats not in (None, {})
|
220
|
+
has_darks = scan.reduced_darks not in (None, {})
|
221
|
+
if has_flats and has_darks:
|
222
|
+
# if the scan has darks and flats remove directly the cache file
|
223
|
+
# else in append mode HDF5 is not removing the dataset and
|
224
|
+
# the cache size will continue to increase
|
225
|
+
self.clear_cache()
|
226
|
+
if not has_flats:
|
202
227
|
logger.warning(f"No flat found for {scan}. Unable to copy them")
|
203
228
|
else:
|
229
|
+
self._clear_cache_data_path(
|
230
|
+
file_path=self._flats_url.file_path(),
|
231
|
+
data_path=self._flats_url.data_path(),
|
232
|
+
)
|
204
233
|
dicttoh5(
|
205
234
|
scan.reduced_flats,
|
206
235
|
h5file=self._flats_url.file_path(),
|
@@ -208,9 +237,13 @@ class DarkRefsCopy(DarkRefsTask):
|
|
208
237
|
mode="a",
|
209
238
|
update_mode="replace",
|
210
239
|
)
|
211
|
-
if
|
240
|
+
if not has_darks:
|
212
241
|
logger.warning(f"No dark found for {scan}. Unable to copy them")
|
213
242
|
else:
|
243
|
+
self._clear_cache_data_path(
|
244
|
+
file_path=self._darks_url.file_path(),
|
245
|
+
data_path=self._darks_url.data_path(),
|
246
|
+
)
|
214
247
|
dicttoh5(
|
215
248
|
scan.reduced_darks,
|
216
249
|
h5file=self._darks_url.file_path(),
|
@@ -246,10 +279,6 @@ class DarkRefsCopy(DarkRefsTask):
|
|
246
279
|
overwrite=True,
|
247
280
|
)
|
248
281
|
|
249
|
-
def clean_save_files(self):
|
250
|
-
if os.path.exists(self._save_file):
|
251
|
-
os.remove(self._save_file)
|
252
|
-
|
253
282
|
def run(self):
|
254
283
|
"""
|
255
284
|
This is function triggered when a new scan / data is received.
|
@@ -297,7 +326,7 @@ class DarkRefsCopy(DarkRefsTask):
|
|
297
326
|
if not os.path.exists(self._save_file):
|
298
327
|
return False
|
299
328
|
else:
|
300
|
-
with
|
329
|
+
with open_hdf5(self._save_file) as h5f:
|
301
330
|
return self._flats_url.data_path() in h5f
|
302
331
|
|
303
332
|
def has_dark_stored(self) -> bool:
|
@@ -309,7 +338,7 @@ class DarkRefsCopy(DarkRefsTask):
|
|
309
338
|
if not os.path.exists(self._save_file):
|
310
339
|
return False
|
311
340
|
else:
|
312
|
-
with
|
341
|
+
with open_hdf5(self._save_file) as h5f:
|
313
342
|
return self._darks_url.data_path() in h5f
|
314
343
|
|
315
344
|
def contains_dark(self, scan: TomwerScanBase) -> bool:
|
@@ -43,9 +43,10 @@ import sys
|
|
43
43
|
|
44
44
|
import numpy
|
45
45
|
from silx.io.url import DataUrl
|
46
|
+
from silx.io.utils import open as open_hdf5
|
46
47
|
from sluurp.executor import submit as submit_to_slurm_cluster
|
47
48
|
from sluurp.job import SBatchScriptJob
|
48
|
-
from tomoscan.io import HDF5File
|
49
|
+
from tomoscan.io import HDF5File
|
49
50
|
from tomoscan.normalization import Method as INormMethod
|
50
51
|
from tomoscan.identifier import VolumeIdentifier
|
51
52
|
|
@@ -581,9 +582,7 @@ class _NabuBaseReconstructor:
|
|
581
582
|
# if an url exists insure we can access it
|
582
583
|
dataset_url = DataUrl(path=dataset_url)
|
583
584
|
if os.path.exists(dataset_url.file_path()):
|
584
|
-
with
|
585
|
-
dataset_url.file_path(), mode="r", swmr=get_swmr_mode()
|
586
|
-
) as h5f:
|
585
|
+
with open_hdf5(dataset_url.file_path()) as h5f:
|
587
586
|
if dataset_url.data_path() not in h5f:
|
588
587
|
dataset_url = None
|
589
588
|
else:
|
@@ -35,6 +35,7 @@ import os
|
|
35
35
|
import gc
|
36
36
|
from tomwer.io.utils import format_stderr_stdout
|
37
37
|
from silx.utils.deprecation import deprecated, deprecated_warning
|
38
|
+
from silx.io.utils import open as open_hdf5
|
38
39
|
|
39
40
|
from processview.core.manager.manager import ProcessManager, DatasetState
|
40
41
|
|
@@ -84,7 +85,6 @@ from processview.core.superviseprocess import SuperviseProcess
|
|
84
85
|
from silx.io.dictdump import h5todict
|
85
86
|
from silx.io.utils import h5py_read_dataset
|
86
87
|
from silx.utils.enum import Enum as _Enum
|
87
|
-
from tomoscan.io import HDF5File, get_swmr_mode
|
88
88
|
|
89
89
|
from tomwer.core.process.task import Task
|
90
90
|
from tomwer.core.scan.edfscan import EDFTomoScan
|
@@ -173,14 +173,6 @@ def run_slices_reconstruction(
|
|
173
173
|
|
174
174
|
# handle special cases like several db...
|
175
175
|
nabu_configurations = interpret_tomwer_configuration(config, scan=scan)
|
176
|
-
if "phase" in config and "delta_beta" in config["phase"]:
|
177
|
-
db_list = utils.retrieve_lst_of_value_from_str(
|
178
|
-
config["phase"]["delta_beta"], type_=float
|
179
|
-
)
|
180
|
-
else:
|
181
|
-
db_list = ()
|
182
|
-
ask_sinogram_registration = len(db_list) > 0
|
183
|
-
ask_sinogram_load = False
|
184
176
|
output_urls = []
|
185
177
|
stderrs = []
|
186
178
|
stdouts = []
|
@@ -199,8 +191,6 @@ def run_slices_reconstruction(
|
|
199
191
|
scan=scan,
|
200
192
|
slice_index=slice_index,
|
201
193
|
dry_run=dry_run,
|
202
|
-
ask_sinogram_registration=ask_sinogram_registration,
|
203
|
-
ask_sinogram_load=ask_sinogram_load,
|
204
194
|
instanciate_class_only=instanciate_classes_only,
|
205
195
|
axis=config.get("reconstruction", {}).get("slice_plane", "XY"),
|
206
196
|
)
|
@@ -238,9 +228,6 @@ def run_slices_reconstruction(
|
|
238
228
|
final_configs.append(result.config)
|
239
229
|
all_succeed = all_succeed and result.success
|
240
230
|
|
241
|
-
if ask_sinogram_registration:
|
242
|
-
ask_sinogram_load = True
|
243
|
-
ask_sinogram_registration = False
|
244
231
|
if advancement is not None:
|
245
232
|
advancement.increaseAdvancement(1)
|
246
233
|
|
@@ -494,7 +481,7 @@ class NabuSlicesTask(
|
|
494
481
|
:rtype:dict
|
495
482
|
"""
|
496
483
|
if entry is None:
|
497
|
-
with
|
484
|
+
with open_hdf5(process_file) as h5f:
|
498
485
|
entries = NabuSlicesTask._get_process_nodes(
|
499
486
|
root_node=h5f, process=NabuSlicesTask
|
500
487
|
)
|
@@ -510,7 +497,7 @@ class NabuSlicesTask(
|
|
510
497
|
configuration_path = None
|
511
498
|
res = {}
|
512
499
|
|
513
|
-
with
|
500
|
+
with open_hdf5(process_file) as h5f:
|
514
501
|
nabu_nodes = NabuSlicesTask._get_process_nodes(
|
515
502
|
root_node=h5f[entry], process=NabuSlicesTask
|
516
503
|
)
|
@@ -640,8 +627,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
640
627
|
slice_index: Union[int, str, None],
|
641
628
|
axis: NabuPlane,
|
642
629
|
target: Target,
|
643
|
-
ask_sinogram_registration: bool,
|
644
|
-
ask_sinogram_load: bool,
|
645
630
|
cluster_config: Optional[dict],
|
646
631
|
process_name: str,
|
647
632
|
add_to_latest_reconstructions: bool = True,
|
@@ -658,8 +643,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
658
643
|
if not isinstance(config, dict):
|
659
644
|
raise TypeError(f"config is expected to be a dictionary not {type(dict)}")
|
660
645
|
self._config = config
|
661
|
-
self._ask_sinogram_registration = ask_sinogram_registration
|
662
|
-
self._ask_sinogram_load = ask_sinogram_load
|
663
646
|
self._add_to_latest_reconstructions = add_to_latest_reconstructions
|
664
647
|
|
665
648
|
@property
|
@@ -670,14 +653,6 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
670
653
|
def config(self):
|
671
654
|
return self._config
|
672
655
|
|
673
|
-
@property
|
674
|
-
def ask_sinogram_load(self):
|
675
|
-
return self._ask_sinogram_load
|
676
|
-
|
677
|
-
@property
|
678
|
-
def ask_sinogram_registration(self):
|
679
|
-
return self._ask_sinogram_registration
|
680
|
-
|
681
656
|
@property
|
682
657
|
def add_to_latest_reconstructions(self):
|
683
658
|
return self._add_to_latest_reconstructions
|
@@ -721,25 +696,8 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
721
696
|
# force overwrite results
|
722
697
|
if "output" not in config:
|
723
698
|
config["output"] = {}
|
724
|
-
# handle nabu sinogram step
|
725
|
-
if self.scan.process_file is not None:
|
726
|
-
steps_file_basename, _ = os.path.splitext(self.scan.process_file)
|
727
|
-
steps_file_basename = "_".join(
|
728
|
-
("steps_file_basename", "nabu", "sinogram", "save", "step")
|
729
|
-
)
|
730
|
-
steps_file_basename = steps_file_basename + ".hdf5"
|
731
|
-
steps_file = os.path.join(
|
732
|
-
os.path.dirname(self.scan.process_file), steps_file_basename
|
733
|
-
)
|
734
|
-
else:
|
735
|
-
steps_file = ""
|
736
699
|
|
737
700
|
config["output"].update({"overwrite_results": 1})
|
738
|
-
config["pipeline"] = {
|
739
|
-
"save_steps": "sinogram" if self.ask_sinogram_registration else "",
|
740
|
-
"resume_from_step": "sinogram" if self.ask_sinogram_load else "",
|
741
|
-
"steps_file": steps_file,
|
742
|
-
}
|
743
701
|
|
744
702
|
config, cfg_folder = self._treateOutputSliceConfig(config)
|
745
703
|
# the policy is to save nabu .cfg file at the same location as the
|
@@ -845,7 +803,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
|
|
845
803
|
basename, _ = os.path.splitext(scan.master_file)
|
846
804
|
basename = os.path.basename(basename)
|
847
805
|
try:
|
848
|
-
with
|
806
|
+
with open_hdf5(scan.master_file) as h5f:
|
849
807
|
if len(h5f.keys()) > 1:
|
850
808
|
# if there is more than one entry in the file append the entry name to the file basename
|
851
809
|
basename = "_".join((basename, scan.entry.lstrip("/")))
|
@@ -918,8 +876,6 @@ def run_single_slice_reconstruction(
|
|
918
876
|
nabu_config,
|
919
877
|
dry_run,
|
920
878
|
slice_index: Union[int, str, None],
|
921
|
-
ask_sinogram_registration: bool,
|
922
|
-
ask_sinogram_load: bool,
|
923
879
|
process_id: Optional[int] = None,
|
924
880
|
cluster_config: Optional[dict] = None,
|
925
881
|
add_to_latest_reconstructions=True,
|
@@ -938,8 +894,6 @@ def run_single_slice_reconstruction(
|
|
938
894
|
:param local:
|
939
895
|
:param stdout: file to redirect stdout
|
940
896
|
:param stderr: file to redirect stderr
|
941
|
-
:param bool ask_sinogram_registration: should we ask nabu to register sinogram
|
942
|
-
:param bool ask_sinogram_load: should we ask nabu to load sinogram
|
943
897
|
:param bool add_to_latest_reconstructions: if true add reconstructed slice to the latest reconstruction.
|
944
898
|
We wan't to avoid this treatment for saaxis and sadeltebeta for example
|
945
899
|
:param bool instanciate_class_only: if we don't want to run the SingleSliceRunner but only return them. Use case: we want to keep a hand on processing and it can be cancelled
|
@@ -970,8 +924,6 @@ def run_single_slice_reconstruction(
|
|
970
924
|
slice_index=slice_index,
|
971
925
|
axis=axis,
|
972
926
|
target=target,
|
973
|
-
ask_sinogram_registration=ask_sinogram_registration,
|
974
|
-
ask_sinogram_load=ask_sinogram_load,
|
975
927
|
cluster_config=cluster_config,
|
976
928
|
add_to_latest_reconstructions=add_to_latest_reconstructions,
|
977
929
|
process_name=process_name,
|
@@ -1010,6 +962,8 @@ class NabuSliceMode(_Enum):
|
|
1010
962
|
n_slice = scan.dim_2 or 2048
|
1011
963
|
elif axis in (NabuPlane.YZ, NabuPlane.XZ):
|
1012
964
|
n_slice = scan.dim_1 or 2048
|
965
|
+
else:
|
966
|
+
raise NotImplementedError(f"unknow axis {axis}")
|
1013
967
|
res.append(n_slice // 2)
|
1014
968
|
else:
|
1015
969
|
raise ValueError(
|
@@ -43,10 +43,9 @@ from processview.core.manager.manager import ProcessManager, DatasetState
|
|
43
43
|
from processview.core.superviseprocess import SuperviseProcess
|
44
44
|
|
45
45
|
from silx.io.utils import h5py_read_dataset
|
46
|
+
from silx.io.utils import open as open_hdf5
|
46
47
|
from tomwer.core.utils.deprecation import deprecated_warning
|
47
48
|
|
48
|
-
from tomoscan.io import HDF5File, get_swmr_mode
|
49
|
-
|
50
49
|
from tomwer.core.cluster.cluster import SlurmClusterConfiguration
|
51
50
|
from tomwer.core.futureobject import FutureTomwerObject
|
52
51
|
from tomwer.core.process.reconstruction.nabu.plane import NabuPlane
|
@@ -354,9 +353,7 @@ class VolumeRunner(_NabuBaseReconstructor):
|
|
354
353
|
basename = os.path.basename(basename)
|
355
354
|
try:
|
356
355
|
# if there is more than one entry in the file append the entry name to the file basename
|
357
|
-
with
|
358
|
-
self.scan.master_file, mode="r", swmr=get_swmr_mode()
|
359
|
-
) as h5f:
|
356
|
+
with open_hdf5(self.scan.master_file) as h5f:
|
360
357
|
if len(h5f.keys()) > 1:
|
361
358
|
basename = "_".join((basename, self.scan.entry.strip("/")))
|
362
359
|
except Exception:
|
@@ -128,7 +128,6 @@ def get_nabu_resources_desc(scan: TomwerScanBase, method, workers=1) -> dict:
|
|
128
128
|
"partition": "gpu",
|
129
129
|
"memory_per_node": "90%",
|
130
130
|
"threads_per_node": "100%",
|
131
|
-
"walltime": "01:00:00",
|
132
131
|
}
|
133
132
|
return res
|
134
133
|
|
@@ -171,6 +170,8 @@ def get_recons_volume_identifier(
|
|
171
170
|
entry = scan.entry
|
172
171
|
elif isinstance(scan, EDFTomoScan):
|
173
172
|
entry = "entry"
|
173
|
+
else:
|
174
|
+
raise NotImplementedError(f"unrecognized scan type ({type(scan)})")
|
174
175
|
|
175
176
|
volumes = (
|
176
177
|
HDF5Volume(
|
@@ -303,7 +304,7 @@ def get_multi_cor_recons_volume_identifiers(
|
|
303
304
|
class _NabuMode(_Enum):
|
304
305
|
FULL_FIELD = "standard acquisition"
|
305
306
|
HALF_ACQ = "half acquisition"
|
306
|
-
HELICAL = "helical acquisition"
|
307
|
+
# HELICAL = "helical acquisition"
|
307
308
|
|
308
309
|
|
309
310
|
class _NabuStages(_Enum):
|
@@ -461,6 +462,13 @@ def nabu_std_err_has_error(errs: typing.Optional[bytes]):
|
|
461
462
|
in line
|
462
463
|
or "return SourceModule(" in line
|
463
464
|
or "CUBLAS" in line
|
465
|
+
or "Not supported for EDF"
|
466
|
+
in line # debatable but very disturbing from the gui side... anyway EDF days are coming to an end
|
467
|
+
or "PerformanceWarning" in line
|
468
|
+
or "jitify._init_module()" in line
|
469
|
+
or " unable to import 'siphash24.siphash13" in line
|
470
|
+
or "_create_built_program_from_source_cached" in line
|
471
|
+
or "prg.build(options_bytes," in line
|
464
472
|
)
|
465
473
|
|
466
474
|
if errs is None:
|
tomwer/core/process/task.py
CHANGED
@@ -46,7 +46,8 @@ from ewokscore.task import Task as _EwoksTask
|
|
46
46
|
from ewokscore.taskwithprogress import TaskWithProgress as _EwoksTaskWithProgress
|
47
47
|
from silx.io.dictdump import dicttoh5, h5todict
|
48
48
|
from silx.io.utils import h5py_read_dataset
|
49
|
-
from
|
49
|
+
from silx.io.utils import open as open_hdf5
|
50
|
+
from tomoscan.io import HDF5File
|
50
51
|
from tomwer.core.utils.locker import FileLockerManager
|
51
52
|
|
52
53
|
|
@@ -376,12 +377,13 @@ class BaseProcessInfo:
|
|
376
377
|
:rtype: list
|
377
378
|
"""
|
378
379
|
# retrieve process to load
|
379
|
-
with
|
380
|
+
with open_hdf5(process_file) as h5f:
|
380
381
|
if entry is None:
|
381
382
|
if len(h5f.keys()) > 0:
|
382
383
|
root = h5f[list(h5f.keys())[0]]
|
383
384
|
else:
|
384
385
|
_logger.warning("no process find")
|
386
|
+
return []
|
385
387
|
else:
|
386
388
|
root = h5f[entry]
|
387
389
|
|
@@ -42,7 +42,8 @@ from nxtomomill.converter import from_h5_to_nx
|
|
42
42
|
from nxtomomill.io.config.hdf5config import TomoHDF5Config
|
43
43
|
from nxtomo.nxobject.nxdetector import ImageKey
|
44
44
|
|
45
|
-
from
|
45
|
+
from silx.io.utils import open as open_hdf5
|
46
|
+
from tomoscan.io import HDF5File
|
46
47
|
from tomoscan.validator import is_valid_for_reconstruction
|
47
48
|
|
48
49
|
from tomwer.core.process.control.datalistener import DataListener
|
@@ -335,9 +336,9 @@ class NXTomoDataTransferBase(unittest.TestCase):
|
|
335
336
|
dst_scan = process.outputs.data
|
336
337
|
assert dst_scan.master_file != self.nexus_file_path
|
337
338
|
assert is_valid_for_reconstruction(dst_scan, check_values=True)
|
338
|
-
with
|
339
|
+
with open_hdf5(src_scan.master_file) as h5s_src:
|
339
340
|
src_dataset = h5s_src["entry0000/detector/data"][...]
|
340
|
-
with
|
341
|
+
with open_hdf5(dst_scan.master_file) as h5s_dst:
|
341
342
|
dst_dataset = h5s_dst["entry0000/detector/data"][...]
|
342
343
|
assert numpy.array_equal(src_dataset, dst_dataset)
|
343
344
|
|
tomwer/core/scan/blissscan.py
CHANGED
@@ -54,7 +54,7 @@ import logging
|
|
54
54
|
from typing import Optional
|
55
55
|
|
56
56
|
from silx.io.utils import h5py_read_dataset
|
57
|
-
from
|
57
|
+
from silx.io.utils import open as open_hdf5
|
58
58
|
|
59
59
|
_logger = logging.getLogger(__name__)
|
60
60
|
|
@@ -203,7 +203,7 @@ class BlissScan:
|
|
203
203
|
return True
|
204
204
|
return False
|
205
205
|
|
206
|
-
with
|
206
|
+
with open_hdf5(file_path) as h5s:
|
207
207
|
if not isinstance(h5s, h5py.Group) or not isinstance(
|
208
208
|
h5s[entry], h5py.Group
|
209
209
|
):
|
@@ -227,7 +227,7 @@ class BlissScan:
|
|
227
227
|
return tuple()
|
228
228
|
else:
|
229
229
|
res = []
|
230
|
-
with
|
230
|
+
with open_hdf5(file_path) as h5s:
|
231
231
|
for entry in h5s:
|
232
232
|
if BlissScan.is_bliss_valid_entry(file_path=file_path, entry=entry):
|
233
233
|
res.append(entry)
|
tomwer/core/scan/nxtomoscan.py
CHANGED
@@ -40,12 +40,12 @@ from urllib.parse import urlparse
|
|
40
40
|
|
41
41
|
import h5py
|
42
42
|
from processview.core.dataset import DatasetIdentifier
|
43
|
+
from silx.io.utils import open as open_hdf5
|
43
44
|
from tomoscan.esrf.identifier.hdf5Identifier import (
|
44
45
|
NXtomoScanIdentifier as _NXtomoScanIdentifier,
|
45
46
|
)
|
46
47
|
from tomoscan.esrf.identifier.url_utils import UrlSettings, split_path, split_query
|
47
48
|
from tomoscan.esrf.scan.nxtomoscan import NXtomoScan as _tsNXtomoScan
|
48
|
-
from tomoscan.io import HDF5File, get_swmr_mode
|
49
49
|
from nxtomo.nxobject.nxdetector import ImageKey
|
50
50
|
|
51
51
|
from tomwer.utils import docstring
|
@@ -424,7 +424,7 @@ class NXtomoScan(_tsNXtomoScan, TomwerScanBase):
|
|
424
424
|
return tuple()
|
425
425
|
else:
|
426
426
|
res = []
|
427
|
-
with
|
427
|
+
with open_hdf5(file_path) as h5s:
|
428
428
|
for entry_name, node in h5s.items():
|
429
429
|
if isinstance(node, h5py.Group):
|
430
430
|
if NXtomoScan.entry_is_nx_tomo(node):
|
tomwer/core/scan/scanbase.py
CHANGED
@@ -40,8 +40,9 @@ import functools
|
|
40
40
|
import numpy
|
41
41
|
from silx.io.url import DataUrl
|
42
42
|
from silx.utils.enum import Enum as _Enum
|
43
|
+
from silx.io.utils import open as open_hdf5
|
44
|
+
|
43
45
|
from tomoscan.identifier import VolumeIdentifier
|
44
|
-
from tomoscan.io import HDF5File, get_swmr_mode
|
45
46
|
from tomoscan.normalization import IntensityNormalization
|
46
47
|
from tomoscan.volumebase import VolumeBase
|
47
48
|
from tomoscan.identifier import BaseIdentifier
|
@@ -131,7 +132,7 @@ class TomwerScanBase(TomwerObject):
|
|
131
132
|
and self.process_file is not None
|
132
133
|
and os.path.exists(self.process_file)
|
133
134
|
):
|
134
|
-
with
|
135
|
+
with open_hdf5(self.process_file) as h5s:
|
135
136
|
self._process_index = len(h5s.items())
|
136
137
|
else:
|
137
138
|
self._process_index = 0
|
@@ -756,7 +757,7 @@ class TomwerScanBase(TomwerObject):
|
|
756
757
|
from tomwer.core.process.task import Task
|
757
758
|
|
758
759
|
if os.path.exists(self.process_file):
|
759
|
-
with
|
760
|
+
with open_hdf5(self.process_file) as h5s:
|
760
761
|
if not hasattr(self, "entry"):
|
761
762
|
entry = "entry"
|
762
763
|
else:
|
@@ -864,9 +865,7 @@ def _get_reconstructed_single_file_volume(
|
|
864
865
|
|
865
866
|
if check_url is True:
|
866
867
|
try:
|
867
|
-
with
|
868
|
-
os.path.abspath(file_), "r", swmr=get_swmr_mode()
|
869
|
-
) as h5f:
|
868
|
+
with open_hdf5(os.path.abspath(file_)) as h5f:
|
870
869
|
if entry not in h5f:
|
871
870
|
logger.info("{volume} does not exists")
|
872
871
|
return None
|
tomwer/core/utils/scanutils.py
CHANGED
@@ -40,7 +40,11 @@ from silx.io.utils import h5py_read_dataset
|
|
40
40
|
from tomoscan.esrf.scan.mock import MockEDF as _MockEDF
|
41
41
|
from tomoscan.esrf.scan.mock import MockNXtomo as _MockNXtomo
|
42
42
|
from tomoscan.io import HDF5File
|
43
|
-
|
43
|
+
|
44
|
+
try:
|
45
|
+
from tomoscan.test.utils import MockContext
|
46
|
+
except ImportError:
|
47
|
+
from tomoscan.tests.utils import MockContext
|
44
48
|
|
45
49
|
from tomwer.core.scan.blissscan import BlissScan
|
46
50
|
from tomwer.core.scan.nxtomoscan import NXtomoScan
|
tomwer/gui/cluster/slurm.py
CHANGED
@@ -166,7 +166,6 @@ class SlurmSettingsWindow(qt.QMainWindow):
|
|
166
166
|
"partition": settingsClass.PARTITION,
|
167
167
|
"n_gpus": settingsClass.N_GPUS_PER_WORKER,
|
168
168
|
"job_name": settingsClass.PROJECT_NAME,
|
169
|
-
"walltime": settingsClass.DEFAULT_WALLTIME,
|
170
169
|
"python_venv": settingsClass.PYTHON_VENV,
|
171
170
|
"modules": settingsClass.MODULES_TO_LOAD,
|
172
171
|
}
|
@@ -261,11 +260,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
261
260
|
self._nJobsLabel.setVisible(jobLimitation is None)
|
262
261
|
self._nJobs.setVisible(jobLimitation is None)
|
263
262
|
|
264
|
-
# wall time
|
265
|
-
self._wallTimeQLE = qt.QLineEdit("", self)
|
266
|
-
self._wallTimeLabel = qt.QLabel("wall time", self)
|
267
|
-
self.layout().addRow(self._wallTimeLabel, self._wallTimeQLE)
|
268
|
-
|
269
263
|
# python exe / modules
|
270
264
|
self._preProcessingGroup = qt.QGroupBox("pre-processing", self)
|
271
265
|
self._preProcessingGroup.setLayout(qt.QFormLayout())
|
@@ -356,8 +350,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
356
350
|
self._sbatchAdvancedParameters.layout().addRow("-C (gpu card)", self._gpuCardCB)
|
357
351
|
|
358
352
|
# simplify gui
|
359
|
-
self._wallTimeLabel.hide()
|
360
|
-
self._wallTimeQLE.hide()
|
361
353
|
self._dashboardPort.hide()
|
362
354
|
self._dashboardPortLabel.hide()
|
363
355
|
self._jobName.hide()
|
@@ -376,7 +368,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
376
368
|
self._queue.setCurrentText(SlurmSettings.PARTITION)
|
377
369
|
self._nGpu.setValue(n_gpu)
|
378
370
|
self._jobName.setText(SlurmSettings.PROJECT_NAME)
|
379
|
-
self._wallTimeQLE.setText(SlurmSettings.DEFAULT_WALLTIME)
|
380
371
|
self._modulesCB.setChecked(True) # by default we go for modules
|
381
372
|
self._preProcessingModeChanged()
|
382
373
|
self._partitionChanged()
|
@@ -389,7 +380,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
389
380
|
self._queue.currentTextChanged.connect(self._configurationChanged)
|
390
381
|
self._nGpu.valueChanged.connect(self._configurationChanged)
|
391
382
|
self._jobName.editingFinished.connect(self._configurationChanged)
|
392
|
-
self._wallTimeQLE.editingFinished.connect(self._configurationChanged)
|
393
383
|
self._pythonVenv.editingFinished.connect(self._configurationChanged)
|
394
384
|
self._modulesQLE.editingFinished.connect(self._configurationChanged)
|
395
385
|
self._preProcessingButtonGroup.buttonClicked.connect(self._configurationChanged)
|
@@ -401,6 +391,7 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
401
391
|
self._queue.currentTextChanged.connect(self._partitionChanged)
|
402
392
|
self._nGpu.valueChanged.connect(self._nGpuChanged)
|
403
393
|
self._gpuCardCB.currentTextChanged.connect(self._configurationChanged)
|
394
|
+
self._exportValueCM.currentIndexChanged.connect(self._configurationChanged)
|
404
395
|
|
405
396
|
def _nGpuChanged(self, *args, **kwargs):
|
406
397
|
nGpu = self.getNGPU()
|
@@ -451,12 +442,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
451
442
|
def setProjectName(self, name):
|
452
443
|
self._jobName.setText(name)
|
453
444
|
|
454
|
-
def getWallTime(self):
|
455
|
-
return self._wallTimeQLE.text()
|
456
|
-
|
457
|
-
def setWallTime(self, walltime):
|
458
|
-
self._wallTimeQLE.setText(walltime)
|
459
|
-
|
460
445
|
def getPythonExe(self):
|
461
446
|
if self._sourceScriptCB.isChecked():
|
462
447
|
return self._pythonVenv.text()
|
@@ -547,10 +532,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
547
532
|
if project_name is not None:
|
548
533
|
self.setProjectName(project_name)
|
549
534
|
|
550
|
-
wall_time = config.get("walltime", None)
|
551
|
-
if wall_time is not None:
|
552
|
-
self.setWallTime(wall_time)
|
553
|
-
|
554
535
|
python_venv = config.get("python_venv", None)
|
555
536
|
if python_venv is not None:
|
556
537
|
python_venv = python_venv.rstrip("'").rstrip('"')
|
@@ -581,7 +562,6 @@ class SlurmSettingsWidget(qt.QWidget):
|
|
581
562
|
"partition": self.getQueue(),
|
582
563
|
"n_gpus": self.getNGPU(),
|
583
564
|
"job_name": self.getProjectName(),
|
584
|
-
"walltime": self.getWallTime(),
|
585
565
|
"sbatch_extra_params": self.getSBatchExtraParams(),
|
586
566
|
}
|
587
567
|
if self._modulesCB.isChecked():
|
@@ -148,7 +148,6 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
|
|
148
148
|
|
149
149
|
# set initial path to observe
|
150
150
|
self.setFolderObserved(self._getInitPath())
|
151
|
-
self._initStatusView()
|
152
151
|
|
153
152
|
# hide all windows by default
|
154
153
|
for widget in (
|
@@ -475,20 +474,10 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
|
|
475
474
|
self.observationThread.sigScanReady.disconnect(self._signalScanReady)
|
476
475
|
self.obsThIsConnected = False
|
477
476
|
|
478
|
-
def _initStatusView(self):
|
479
|
-
"""
|
480
|
-
The status view need a thread to update the animated icon when scanning
|
481
|
-
"""
|
482
|
-
self.__threadAnimation = QWaiterThread(0.1)
|
483
|
-
self.__threadAnimation.finished.connect(self._updateAnimatedIcon)
|
484
|
-
|
485
477
|
def _updateStatusView(self):
|
486
478
|
"""Update the processing state"""
|
487
479
|
if self.currentStatus in self._animatedStates:
|
488
|
-
|
489
|
-
self.__threadAnimation.start()
|
490
|
-
elif self.__threadAnimation is not None:
|
491
|
-
self.__threadAnimation.wait(4000)
|
480
|
+
pass
|
492
481
|
elif self.currentStatus == "acquisition ended":
|
493
482
|
self._setStateIcon(silxicons.getQIcon("selected"))
|
494
483
|
elif self.currentStatus == "failure":
|
@@ -506,18 +495,6 @@ class DataWatcherWidget(_DataWatcher, qt.QMainWindow):
|
|
506
495
|
else:
|
507
496
|
self._stateLabel.setPixmap(icon.pixmap(30, state=qt.QIcon.On))
|
508
497
|
|
509
|
-
def _updateAnimatedIcon(self):
|
510
|
-
"""Simple function which manage the waiting icon"""
|
511
|
-
if self.currentStatus in self._animatedStates:
|
512
|
-
icon = self.animated_icon.currentIcon()
|
513
|
-
if icon is None:
|
514
|
-
icon = qt.QIcon()
|
515
|
-
self.animated_icon._updateState()
|
516
|
-
self._setStateIcon(icon)
|
517
|
-
|
518
|
-
# get ready for the next animation
|
519
|
-
self.__threadAnimation.start()
|
520
|
-
|
521
498
|
def _signalScanReady(self, scan):
|
522
499
|
if type(scan) is str:
|
523
500
|
try:
|