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.
Files changed (59) hide show
  1. orangecontrib/tomwer/widgets/reconstruction/DarkRefAndCopyOW.py +1 -0
  2. orangecontrib/tomwer/widgets/reconstruction/NabuHelicalPrepareWeightsDoubleOW.py +184 -184
  3. tomwer/app/canvas_launcher/mainwindow.py +0 -1
  4. tomwer/app/zstitching.py +0 -1
  5. tomwer/core/cluster/cluster.py +0 -9
  6. tomwer/core/process/control/datalistener/datalistener.py +15 -12
  7. tomwer/core/process/control/datawatcher/edfdwprocess.py +0 -9
  8. tomwer/core/process/reconstruction/axis/axis.py +3 -3
  9. tomwer/core/process/reconstruction/axis/params.py +3 -3
  10. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +37 -8
  11. tomwer/core/process/reconstruction/nabu/nabucommon.py +3 -4
  12. tomwer/core/process/reconstruction/nabu/nabuscores.py +1 -0
  13. tomwer/core/process/reconstruction/nabu/nabuslices.py +6 -52
  14. tomwer/core/process/reconstruction/nabu/nabuvolume.py +2 -5
  15. tomwer/core/process/reconstruction/nabu/utils.py +10 -2
  16. tomwer/core/process/reconstruction/saaxis/saaxis.py +2 -0
  17. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +2 -0
  18. tomwer/core/process/task.py +4 -2
  19. tomwer/core/process/test/test_data_transfer.py +4 -3
  20. tomwer/core/scan/blissscan.py +3 -3
  21. tomwer/core/scan/nxtomoscan.py +2 -2
  22. tomwer/core/scan/scanbase.py +5 -6
  23. tomwer/core/utils/scanutils.py +5 -1
  24. tomwer/gui/cluster/slurm.py +1 -21
  25. tomwer/gui/cluster/test/test_cluster.py +0 -1
  26. tomwer/gui/control/datawatcher/datawatcher.py +1 -24
  27. tomwer/gui/control/reducedarkflatselector.py +2 -2
  28. tomwer/gui/control/selectorwidgetbase.py +3 -1
  29. tomwer/gui/edit/dkrfpatch.py +4 -4
  30. tomwer/gui/edit/nxtomoeditor.py +28 -20
  31. tomwer/gui/edit/nxtomowarmer.py +3 -2
  32. tomwer/gui/edit/test/test_nx_editor.py +58 -1
  33. tomwer/gui/imagefromfile.py +2 -2
  34. tomwer/gui/qfolderdialog.py +4 -0
  35. tomwer/gui/reconstruction/axis/axis.py +16 -13
  36. tomwer/gui/reconstruction/axis/radioaxis.py +3 -1
  37. tomwer/gui/reconstruction/darkref/darkrefcopywidget.py +11 -0
  38. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +16 -14
  39. tomwer/gui/reconstruction/saaxis/saaxis.py +2 -2
  40. tomwer/gui/stitching/stitching.py +8 -3
  41. tomwer/gui/visualization/dataviewer.py +27 -15
  42. tomwer/gui/visualization/diffviewer/diffviewer.py +9 -8
  43. tomwer/gui/visualization/volumeviewer.py +10 -4
  44. tomwer/io/utils/h5pyutils.py +3 -7
  45. tomwer/io/utils/utils.py +3 -3
  46. tomwer/synctools/stacks/reconstruction/castvolume.py +20 -5
  47. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +10 -0
  48. tomwer/tests/datasets.py +5 -1
  49. tomwer/utils.py +1 -4
  50. tomwer/version.py +1 -1
  51. tomwer-1.3.26-py3.11-nspkg.pth +1 -0
  52. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/METADATA +34 -48
  53. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/RECORD +58 -58
  54. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/WHEEL +1 -1
  55. tomwer-1.3.4-py3.11-nspkg.pth +0 -1
  56. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/LICENSE +0 -0
  57. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/entry_points.txt +0 -0
  58. {tomwer-1.3.4.dist-info → tomwer-1.3.26.dist-info}/namespace_packages.txt +0 -0
  59. {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
- if scan.reduced_flats in (None, {}):
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 scan.reduced_darks in (None, {}):
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 HDF5File(self._save_file, mode="r") as h5f:
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 HDF5File(self._save_file, mode="r") as h5f:
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, get_swmr_mode
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 HDF5File(
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:
@@ -211,6 +211,7 @@ def run_nabu_multicor(
211
211
  recons_urls = {}
212
212
  std_outs = []
213
213
  std_errs = []
214
+ future_tomo_obj = None
214
215
 
215
216
  success = result.success
216
217
  if isinstance(result, ResultsWithStd):
@@ -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 HDF5File(process_file, "r", swmr=get_swmr_mode()) as h5f:
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 HDF5File(process_file, "r", swmr=get_swmr_mode()) as h5f:
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 HDF5File(scan.master_file, mode="r", swmr=get_swmr_mode()) as h5f:
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 HDF5File(
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:
@@ -536,6 +536,8 @@ class SAAxisTask(
536
536
  mess = "sa-axis computation succeeded"
537
537
  else:
538
538
  cors_res = {}
539
+ state = DatasetState.FAILED
540
+ mess = "couldn't find 'compute_scores'"
539
541
 
540
542
  if self._cancelled:
541
543
  state = DatasetState.CANCELLED
@@ -341,6 +341,8 @@ class SADeltaBetaTask(
341
341
  mess = "sa-delta-beta computation succeeded"
342
342
  else:
343
343
  dbs_res = {}
344
+ state = DatasetState.FAILED
345
+ mess = "couldn't find 'compute_scores'"
344
346
 
345
347
  if self._cancelled:
346
348
  state = DatasetState.CANCELLED
@@ -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 tomoscan.io import HDF5File, get_swmr_mode
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 HDF5File(process_file, mode="r", swmr=get_swmr_mode()) as h5f:
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 tomoscan.io import HDF5File, get_swmr_mode
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 HDF5File(src_scan.master_file, mode="r", swmr=get_swmr_mode()) as h5s_src:
339
+ with open_hdf5(src_scan.master_file) as h5s_src:
339
340
  src_dataset = h5s_src["entry0000/detector/data"][...]
340
- with HDF5File(dst_scan.master_file, mode="r", swmr=get_swmr_mode()) as h5s_dst:
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
 
@@ -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 tomoscan.io import HDF5File, get_swmr_mode
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 HDF5File(file_path, mode="r", swmr=get_swmr_mode()) as h5s:
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 HDF5File(file_path, mode="r", swmr=get_swmr_mode()) as h5s:
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)
@@ -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 HDF5File(file_path, mode="r", swmr=get_swmr_mode()) as h5s:
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):
@@ -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 HDF5File(self.process_file, mode="r", swmr=get_swmr_mode()) as h5s:
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 HDF5File(self.process_file, mode="r", swmr=get_swmr_mode()) as h5s:
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 HDF5File(
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
@@ -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
- from tomoscan.test.utils import MockContext
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
@@ -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():
@@ -63,7 +63,6 @@ class TestSlurmWidget(TestCaseQt):
63
63
  "job_name": "tomwer_{scan}_-_{process}_-_{info}",
64
64
  "n_jobs": 1,
65
65
  "modules": ("tomotools/stable",),
66
- "walltime": "01:00:00",
67
66
  "sbatch_extra_params": {
68
67
  "export": "NONE",
69
68
  "gpu_card": None,
@@ -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
- if not self.__threadAnimation.isRunning():
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: