tomwer 1.4.18__py3-none-any.whl → 1.5.0__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 (127) hide show
  1. orangecontrib/tomwer/tutorials/simple_volume_local_reconstruction.ows +11 -8
  2. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +12 -9
  3. orangecontrib/tomwer/widgets/cluster/SlurmClusterOW.py +11 -0
  4. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -1
  5. orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +21 -10
  6. tomwer/app/axis.py +1 -1
  7. tomwer/app/reducedarkflat.py +2 -2
  8. tomwer/core/process/control/datalistener/rpcserver.py +2 -8
  9. tomwer/core/process/drac/binning.py +2 -2
  10. tomwer/core/process/drac/output.py +1 -1
  11. tomwer/core/process/edit/imagekeyeditor.py +4 -6
  12. tomwer/core/process/edit/nxtomoeditor.py +58 -20
  13. tomwer/core/process/output.py +6 -5
  14. tomwer/core/process/reconstruction/axis/anglemode.py +2 -2
  15. tomwer/core/process/reconstruction/axis/axis.py +1 -0
  16. tomwer/core/process/reconstruction/axis/mode.py +2 -2
  17. tomwer/core/process/reconstruction/axis/params.py +4 -4
  18. tomwer/core/process/reconstruction/axis/projectiontype.py +1 -1
  19. tomwer/core/process/reconstruction/axis/side.py +1 -1
  20. tomwer/core/process/reconstruction/darkref/darkrefs.py +2 -2
  21. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +1 -1
  22. tomwer/core/process/reconstruction/darkref/params.py +2 -3
  23. tomwer/core/process/reconstruction/nabu/castvolume.py +4 -1
  24. tomwer/core/process/reconstruction/nabu/helical.py +3 -1
  25. tomwer/core/process/reconstruction/nabu/nabucommon.py +2 -2
  26. tomwer/core/process/reconstruction/nabu/nabuscores.py +1 -1
  27. tomwer/core/process/reconstruction/nabu/nabuslices.py +4 -4
  28. tomwer/core/process/reconstruction/nabu/plane.py +2 -2
  29. tomwer/core/process/reconstruction/nabu/target.py +1 -1
  30. tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +2 -0
  31. tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +9 -0
  32. tomwer/core/process/reconstruction/nabu/utils.py +18 -14
  33. tomwer/core/process/reconstruction/normalization/normalization.py +1 -1
  34. tomwer/core/process/reconstruction/normalization/params.py +4 -4
  35. tomwer/core/process/reconstruction/output.py +2 -2
  36. tomwer/core/process/reconstruction/saaxis/params.py +3 -3
  37. tomwer/core/process/reconstruction/saaxis/saaxis.py +5 -1
  38. tomwer/core/process/reconstruction/scores/params.py +2 -2
  39. tomwer/core/process/reconstruction/scores/scores.py +3 -3
  40. tomwer/core/process/reconstruction/tests/test_axis.py +1 -1
  41. tomwer/core/process/reconstruction/tests/test_saaxis.py +56 -66
  42. tomwer/core/process/stitching/metadataholder.py +5 -5
  43. tomwer/core/process/stitching/nabustitcher.py +1 -4
  44. tomwer/core/process/tests/test_normalization.py +2 -1
  45. tomwer/core/scan/edfscan.py +3 -3
  46. tomwer/core/scan/nxtomoscan.py +3 -3
  47. tomwer/core/scan/scanbase.py +3 -3
  48. tomwer/core/scan/scantype.py +1 -1
  49. tomwer/core/settings.py +1 -1
  50. tomwer/core/tomwer_object.py +1 -1
  51. tomwer/core/utils/nxtomoutils.py +2 -2
  52. tomwer/core/utils/spec.py +6 -3
  53. tomwer/gui/cluster/slurm.py +12 -3
  54. tomwer/gui/configuration/level.py +1 -1
  55. tomwer/gui/control/actions.py +1 -1
  56. tomwer/gui/control/datadiscovery.py +1 -1
  57. tomwer/gui/control/datalist.py +1 -1
  58. tomwer/gui/control/reducedarkflatselector.py +4 -4
  59. tomwer/gui/control/series/seriescreator.py +5 -5
  60. tomwer/gui/control/tomoobjdisplaymode.py +1 -1
  61. tomwer/gui/dataportal/gallery.py +6 -6
  62. tomwer/gui/edit/imagekeyeditor.py +7 -9
  63. tomwer/gui/edit/nxtomoeditor.py +420 -112
  64. tomwer/gui/edit/tests/test_nx_editor.py +155 -83
  65. tomwer/gui/reconstruction/axis/CalculationWidget.py +1 -1
  66. tomwer/gui/reconstruction/axis/EstimatedCORWidget.py +12 -8
  67. tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +2 -2
  68. tomwer/gui/reconstruction/axis/InputWidget.py +3 -3
  69. tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -2
  70. tomwer/gui/reconstruction/nabu/castvolume.py +16 -1
  71. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
  72. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -6
  73. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +1 -1
  74. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +5 -5
  75. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +2 -4
  76. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +78 -52
  77. tomwer/gui/reconstruction/nabu/nabuflow.py +3 -13
  78. tomwer/gui/reconstruction/nabu/slices.py +11 -11
  79. tomwer/gui/reconstruction/nabu/test/test_cast_volume.py +19 -0
  80. tomwer/gui/reconstruction/nabu/volume.py +1 -1
  81. tomwer/gui/reconstruction/normalization/intensity.py +8 -12
  82. tomwer/gui/reconstruction/saaxis/corrangeselector.py +2 -2
  83. tomwer/gui/reconstruction/saaxis/dimensionwidget.py +71 -67
  84. tomwer/gui/reconstruction/sacommon.py +1 -1
  85. tomwer/gui/reconstruction/scores/scoreplot.py +18 -10
  86. tomwer/gui/reconstruction/tests/test_saaxis.py +18 -16
  87. tomwer/gui/stitching/SingleAxisStitchingWidget.py +8 -8
  88. tomwer/gui/stitching/StitchingOptionsWidget.py +1 -1
  89. tomwer/gui/stitching/alignment.py +8 -8
  90. tomwer/gui/stitching/config/axisparams.py +2 -2
  91. tomwer/gui/stitching/config/output.py +1 -1
  92. tomwer/gui/stitching/config/positionoveraxis.py +1 -1
  93. tomwer/gui/stitching/config/stitchingstrategies.py +4 -6
  94. tomwer/gui/stitching/config/tomoobjdetails.py +21 -13
  95. tomwer/gui/stitching/normalization.py +6 -6
  96. tomwer/gui/stitching/tests/test_ZStitchingWindow.py +8 -1
  97. tomwer/gui/stitching/tests/test_preview.py +10 -7
  98. tomwer/gui/stitching/tests/utils.py +27 -18
  99. tomwer/gui/stitching/z_stitching/fineestimation.py +7 -9
  100. tomwer/gui/stitching/z_stitching/tests/test_raw_estimation.py +18 -7
  101. tomwer/gui/stitching/z_stitching/tests/test_stitching_window.py +7 -2
  102. tomwer/gui/utils/buttons.py +54 -36
  103. tomwer/gui/utils/flow.py +2 -2
  104. tomwer/gui/utils/loadingmode.py +1 -1
  105. tomwer/gui/utils/unitsystem.py +44 -33
  106. tomwer/gui/utils/vignettes.py +1 -1
  107. tomwer/gui/visualization/dataviewer.py +7 -7
  108. tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
  109. tomwer/gui/visualization/diffviewer/shiftwidget.py +4 -6
  110. tomwer/gui/visualization/reconstructionparameters.py +35 -23
  111. tomwer/gui/visualization/scanoverview.py +28 -11
  112. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +25 -13
  113. tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -2
  114. tomwer/model/dataset.py +0 -0
  115. tomwer/resources/gui/icons/borders.png +0 -0
  116. tomwer/synctools/utils/scanstages.py +3 -3
  117. tomwer/tasks/reconstruction/cleardarkflat.py +42 -0
  118. tomwer/tests/app/test_stitching.py +1 -1
  119. tomwer/tests/orangecontrib/tomwer/widgets/edit/tests/test_nxtomo_editor.py +32 -20
  120. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_widget.py +1 -1
  121. tomwer/version.py +2 -2
  122. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/METADATA +8 -8
  123. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/RECORD +127 -124
  124. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/WHEEL +1 -1
  125. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/entry_points.txt +0 -0
  126. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/licenses/LICENSE +0 -0
  127. {tomwer-1.4.18.dist-info → tomwer-1.5.0.dist-info}/top_level.txt +0 -0
@@ -129,6 +129,7 @@ class CastVolumeTask(
129
129
 
130
130
  # build output volume object
131
131
  overwrite = configuration.get("overwrite", False)
132
+ remove_input_volume = configuration.get("remove_input_volume", False)
132
133
  output_volume.overwrite = overwrite
133
134
  cratios = configuration.get("compression_ratios", None)
134
135
  if cratios is not None:
@@ -161,6 +162,7 @@ class CastVolumeTask(
161
162
  rescale_max_percentile=rescale_max_percentile,
162
163
  save=True,
163
164
  store=False,
165
+ remove_input_volume=remove_input_volume,
164
166
  )
165
167
  except Exception as e:
166
168
  mess = f"volume cast of {str(input_volume)} failed. Reason is {str(e)}"
@@ -203,7 +205,8 @@ class CastVolumeTask(
203
205
  command += f" --rescale_min_percentile={rescale_min_percentile}"
204
206
  if rescale_max_percentile is not None:
205
207
  command += f" --rescale_max_percentile={rescale_max_percentile}"
206
-
208
+ if remove_input_volume:
209
+ command += " --remove-input-volume"
207
210
  return command
208
211
 
209
212
  script_name = get_slurm_script_name(prefix="nabu_cast")
@@ -34,7 +34,9 @@ class NabuHelicalPrepareWeightsDouble(
34
34
  scan.master_file,
35
35
  extra_options={"h5_entry": scan.entry},
36
36
  )
37
- update_dataset_info_flats_darks(dataset_info, flatfield_mode=1)
37
+ update_dataset_info_flats_darks(
38
+ dataset_info, flatfield_mode=1, loading_mode="load_if_present"
39
+ )
38
40
 
39
41
  mappe = 0
40
42
  my_flats = load_images_from_dataurl_dict(dataset_info.flats)
@@ -205,7 +205,7 @@ class _NabuBaseReconstructor:
205
205
  axis: NabuPlane = NabuPlane.XY,
206
206
  ) -> None:
207
207
  self._scan = scan
208
- self._target = Target.from_value(target)
208
+ self._target = Target(target)
209
209
  self._dry_run = dry_run
210
210
  self._process_name = process_name
211
211
  self._process = None
@@ -564,7 +564,7 @@ class _NabuBaseReconstructor:
564
564
  )
565
565
 
566
566
  source = extra_infos.get("source", INormSource.NONE)
567
- source = INormSource.from_value(source)
567
+ source = INormSource(source)
568
568
 
569
569
  if source is INormSource.NONE:
570
570
  pass
@@ -390,7 +390,7 @@ class _Reconstructor(_NabuBaseReconstructor):
390
390
  _config["reconstruction"]["end_z"] = self.slice_index
391
391
  else:
392
392
  raise ValueError(
393
- f"self.axis has an invalid value: {self.axis} when expected to be in {NabuPlane.values()}"
393
+ f"self.axis has an invalid value: {self.axis} when expected to be in {[item.value for item in NabuPlane]}"
394
394
  )
395
395
  return _config, file_prefix
396
396
 
@@ -54,7 +54,7 @@ from nabu.pipeline.fullfield.nabu_config import (
54
54
  nabu_config as nabu_fullfield_default_config,
55
55
  )
56
56
  from processview.core.superviseprocess import SuperviseProcess
57
- from silx.utils.enum import Enum as _Enum
57
+ from enum import Enum as _Enum
58
58
 
59
59
  from tomwer.core.process.task import Task
60
60
  from tomwer.core.scan.edfscan import EDFTomoScan
@@ -612,7 +612,7 @@ class SingleSliceRunner(_NabuBaseReconstructor):
612
612
  config["reconstruction"]["end_z"] = self.slice_index
613
613
  else:
614
614
  raise ValueError(
615
- f"self.axis has an invalid value: {self.axis} when expected to be in {NabuPlane.values()}"
615
+ f"self.axis has an invalid value: {self.axis} when expected to be in {[item.value for item in NabuPlane]}"
616
616
  )
617
617
 
618
618
  if self.slice_index is not None:
@@ -842,7 +842,7 @@ class NabuSliceMode(_Enum):
842
842
  def getSlices(slices, scan, axis=NabuPlane.XY) -> tuple:
843
843
  res = []
844
844
  try:
845
- mode = NabuSliceMode.from_value(slices)
845
+ mode = NabuSliceMode(slices)
846
846
  except ValueError:
847
847
  try:
848
848
  res = utils.retrieve_lst_of_value_from_str(slices, type_=int)
@@ -850,7 +850,7 @@ class NabuSliceMode(_Enum):
850
850
  pass
851
851
  else:
852
852
  if mode == mode.MIDDLE:
853
- axis = NabuPlane.from_value(axis)
853
+ axis = NabuPlane(axis)
854
854
  if axis is NabuPlane.XY:
855
855
  n_slice = scan.dim_2 or 2048
856
856
  elif axis in (NabuPlane.YZ, NabuPlane.XZ):
@@ -1,6 +1,6 @@
1
1
  """Define nabu Axis"""
2
2
 
3
- from silx.utils.enum import Enum as _Enum
3
+ from enum import Enum as _Enum
4
4
 
5
5
 
6
6
  class NabuPlane(_Enum):
@@ -16,4 +16,4 @@ class NabuPlane(_Enum):
16
16
  return NabuPlane.XZ
17
17
  elif value == 2:
18
18
  return NabuPlane.YZ
19
- return super().from_value(value=value)
19
+ return NabuPlane(value=value)
@@ -1,6 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
- from silx.utils.enum import Enum as _Enum
3
+ from enum import Enum as _Enum
4
4
 
5
5
 
6
6
  class Target(_Enum):
@@ -107,6 +107,7 @@ def test_cast_volume_32bitstiff_to_16bits_tiff(tmp_path):
107
107
  "output_dir": str(save_dir),
108
108
  "output_file_format": NabuOutputFileFormat.HDF5,
109
109
  "output_data_type": numpy.int16,
110
+ "remove_input_volume": True,
110
111
  },
111
112
  "output_volume": output_volume.get_identifier().to_str(),
112
113
  },
@@ -114,3 +115,4 @@ def test_cast_volume_32bitstiff_to_16bits_tiff(tmp_path):
114
115
  task.run()
115
116
  assert task.outputs.volume.load_data().shape == (20, 100, 100)
116
117
  assert task.outputs.volume.load_data().dtype == numpy.int16
118
+ assert not os.path.exists(volume.data_url.file_path())
@@ -275,3 +275,12 @@ def test_nabu_std_err_has_error():
275
275
  )
276
276
  is False
277
277
  )
278
+
279
+ assert (
280
+ nabu_std_err_has_error(
281
+ b"""Performing MLEM-WL2 iterations: 0%| | 0/200[00:00<?, ?its/s]
282
+ Performing MLEM-WL2 iterations: 82%| | 163/200[00:00<?, 828.12its/s]
283
+ """
284
+ )
285
+ is False
286
+ )
@@ -10,7 +10,7 @@ from nabu.pipeline.config import generate_nabu_configfile, parse_nabu_config_fil
10
10
  from nabu.pipeline.fullfield.nabu_config import (
11
11
  nabu_config as nabu_fullfield_default_config,
12
12
  )
13
- from silx.utils.enum import Enum as _Enum
13
+ from enum import Enum
14
14
 
15
15
  from tomoscan.identifier import VolumeIdentifier
16
16
  import tomwer.version
@@ -240,13 +240,13 @@ def get_multi_cor_recons_volume_identifiers(
240
240
  return res
241
241
 
242
242
 
243
- class _NabuMode(_Enum):
243
+ class _NabuMode(Enum):
244
244
  FULL_FIELD = "standard acquisition"
245
245
  HALF_ACQ = "half acquisition"
246
246
  # HELICAL = "helical acquisition"
247
247
 
248
248
 
249
- class _NabuStages(_Enum):
249
+ class _NabuStages(Enum):
250
250
  INI = "initialization"
251
251
  PRE = "pre-processing"
252
252
  PHASE = "phase"
@@ -267,7 +267,7 @@ class _NabuStages(_Enum):
267
267
  @staticmethod
268
268
  def getProcessEnum(stage):
269
269
  """Return the process Enum associated to the stage"""
270
- stage = _NabuStages.from_value(stage)
270
+ stage = _NabuStages(stage)
271
271
  if stage is _NabuStages.INI:
272
272
  raise NotImplementedError()
273
273
  elif stage is _NabuStages.PRE:
@@ -281,7 +281,7 @@ class _NabuStages(_Enum):
281
281
  raise NotImplementedError()
282
282
 
283
283
 
284
- class _NabuPreprocessing(_Enum):
284
+ class _NabuPreprocessing(Enum):
285
285
  """Define all the preprocessing action possible and the order they
286
286
  are applied on"""
287
287
 
@@ -296,7 +296,7 @@ class _NabuPreprocessing(_Enum):
296
296
  )
297
297
 
298
298
 
299
- class _NabuPhase(_Enum):
299
+ class _NabuPhase(Enum):
300
300
  """Define all the phase action possible and the order they
301
301
  are applied on"""
302
302
 
@@ -309,7 +309,7 @@ class _NabuPhase(_Enum):
309
309
  return (_NabuPhase.PHASE, _NabuPhase.UNSHARP_MASK, _NabuPhase.LOGARITHM)
310
310
 
311
311
 
312
- class _NabuProcessing(_Enum):
312
+ class _NabuProcessing(Enum):
313
313
  """Define all the processing action possible"""
314
314
 
315
315
  RECONSTRUCTION = "reconstruction"
@@ -319,7 +319,7 @@ class _NabuProcessing(_Enum):
319
319
  return (_NabuProcessing.RECONSTRUCTION,)
320
320
 
321
321
 
322
- class _NabuPostProcessing(_Enum):
322
+ class _NabuPostProcessing(Enum):
323
323
  """Define all the post processing action available"""
324
324
 
325
325
  SAVE_DATA = "save"
@@ -329,11 +329,12 @@ class _NabuPostProcessing(_Enum):
329
329
  return (_NabuPostProcessing.SAVE_DATA,)
330
330
 
331
331
 
332
- class _NabuReconstructionMethods(_Enum):
332
+ class _NabuReconstructionMethods(Enum):
333
333
  FBP = "FBP"
334
+ MLEM = "MLEM"
334
335
 
335
336
 
336
- class _NabuPhaseMethod(_Enum):
337
+ class _NabuPhaseMethod(Enum):
337
338
  """
338
339
  Nabu phase method
339
340
  """
@@ -354,10 +355,10 @@ class _NabuPhaseMethod(_Enum):
354
355
  elif value.lower() == "ctf":
355
356
  return _NabuPhaseMethod.CTF
356
357
  else:
357
- return super().from_value(value=value)
358
+ return _NabuPhaseMethod(value=value)
358
359
 
359
360
 
360
- class _NabuFBPFilterType(_Enum):
361
+ class _NabuFBPFilterType(Enum):
361
362
  RAMLAK = "ramlak"
362
363
  SHEPP_LOGAN = "shepp-logan"
363
364
  COSINE = "cosine"
@@ -368,12 +369,12 @@ class _NabuFBPFilterType(_Enum):
368
369
  HILBERT = "hilbert"
369
370
 
370
371
 
371
- class _NabuPaddingType(_Enum):
372
+ class _NabuPaddingType(Enum):
372
373
  ZEROS = "zeros"
373
374
  EDGES = "edges"
374
375
 
375
376
 
376
- class RingCorrectionMethod(_Enum):
377
+ class RingCorrectionMethod(Enum):
377
378
  NONE = "None"
378
379
  MUNCH = "munch"
379
380
  VO = "vo"
@@ -408,6 +409,9 @@ def nabu_std_err_has_error(errs: bytes | None):
408
409
  or " unable to import 'siphash24.siphash13" in line
409
410
  or "_create_built_program_from_source_cached" in line
410
411
  or "prg.build(options_bytes," in line
412
+ or (
413
+ "Performing MLEM" in line and "iterations" in line
414
+ ) # corrct usage of tqdm (goes to stderr)
411
415
  )
412
416
 
413
417
  if errs is None:
@@ -140,7 +140,7 @@ class SinoNormalizationTask(
140
140
  if calc_fct is None:
141
141
  raise ValueError("calc_fct should be provided")
142
142
  else:
143
- calc_fct = _ValueCalculationFct.from_value(calc_fct)
143
+ calc_fct = _ValueCalculationFct(calc_fct)
144
144
 
145
145
  try:
146
146
  value = self._cache_compute_from_manual_roi(
@@ -4,7 +4,7 @@ material for radio and sinogram normalization
4
4
  """
5
5
  from __future__ import annotations
6
6
 
7
- from silx.utils.enum import Enum as _Enum
7
+ from enum import Enum as _Enum
8
8
  from tomoscan.normalization import Method
9
9
 
10
10
 
@@ -39,7 +39,7 @@ class _DatasetInfos:
39
39
 
40
40
  @scope.setter
41
41
  def scope(self, scope: str | _DatasetScope):
42
- self._scope = _DatasetScope.from_value(scope)
42
+ self._scope = _DatasetScope(scope)
43
43
 
44
44
  @property
45
45
  def file_path(self):
@@ -86,7 +86,7 @@ class SinoNormalizationParams:
86
86
  def method(self, method: str | Method | None):
87
87
  if method is None:
88
88
  method = Method.NONE
89
- self._method = Method.from_value(method)
89
+ self._method = Method(method)
90
90
 
91
91
  @property
92
92
  def source(self):
@@ -96,7 +96,7 @@ class SinoNormalizationParams:
96
96
  def source(self, source):
97
97
  if source is None:
98
98
  source = _ValueSource.NONE
99
- self._source = _ValueSource.from_value(source)
99
+ self._source = _ValueSource(source)
100
100
 
101
101
  @property
102
102
  def extra_infos(self):
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
  import os
3
3
  import logging
4
- from silx.utils.enum import Enum as _Enum
4
+ from enum import Enum as _Enum
5
5
  from tomwer.io.utils.raw_and_processed_data import (
6
6
  to_processed_data_path,
7
7
  )
@@ -30,7 +30,7 @@ class NabuOutputFileFormat(_Enum):
30
30
  def from_value(cls, value):
31
31
  if isinstance(value, str):
32
32
  value = value.lstrip(".")
33
- return super().from_value(value)
33
+ return NabuOutputFileFormat(value)
34
34
 
35
35
 
36
36
  def get_file_format(file_str):
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  from typing import Iterable
5
5
 
6
6
  import numpy
7
- from silx.utils.enum import Enum as _Enum
7
+ from enum import Enum as _Enum
8
8
 
9
9
  from tomwer.core.process.reconstruction.scores.params import SABaseParams
10
10
 
@@ -56,7 +56,7 @@ class SAAxisParams(SABaseParams):
56
56
 
57
57
  @mode.setter
58
58
  def mode(self, mode):
59
- mode = ReconstructionMode.from_value(mode)
59
+ mode = ReconstructionMode(mode)
60
60
  self._mode = mode
61
61
 
62
62
  @property
@@ -91,7 +91,7 @@ class SAAxisParams(SABaseParams):
91
91
  if "n_reconstruction" in dict_:
92
92
  self.n_reconstruction = dict_["n_reconstruction"]
93
93
  if "mode" in dict_:
94
- self.mode = ReconstructionMode.from_value(dict_["mode"])
94
+ self.mode = ReconstructionMode(dict_["mode"])
95
95
 
96
96
  @staticmethod
97
97
  def from_dict(dict_):
@@ -430,7 +430,7 @@ class SAAxisTask(
430
430
  params.image_width = scan.dim_1
431
431
  scan.saaxis_params = params
432
432
 
433
- mode = ReconstructionMode.from_value(params.mode)
433
+ mode = ReconstructionMode(params.mode)
434
434
  if mode is not ReconstructionMode.VERTICAL:
435
435
  raise ValueError(f"{mode} is not handled for now")
436
436
 
@@ -628,6 +628,10 @@ class SAAxisTask(
628
628
 
629
629
  saaxis_results_url = SAAxisTask.get_results_url(scan=scan)
630
630
 
631
+ if not os.path.exists(saaxis_results_url.file_path()):
632
+ _logger.error("no result saved")
633
+ return
634
+
631
635
  # save it to the file
632
636
  with HDF5File(saaxis_results_url.file_path(), mode="a") as h5f:
633
637
  nx_process = h5f.require_group(saaxis_results_url.data_path())
@@ -102,7 +102,7 @@ class SABaseParams:
102
102
 
103
103
  @score_method.setter
104
104
  def score_method(self, method):
105
- self._score_method = ScoreMethod.from_value(method)
105
+ self._score_method = ScoreMethod(method)
106
106
 
107
107
  @property
108
108
  def scores(self) -> dict | None:
@@ -170,7 +170,7 @@ class SABaseParams:
170
170
  output_dir = None
171
171
  self.output_dir = output_dir
172
172
  if "score_method" in dict_:
173
- self.score_method = ScoreMethod.from_value(dict_["score_method"])
173
+ self.score_method = ScoreMethod(dict_["score_method"])
174
174
  if "cluster_config" in dict_:
175
175
  if dict_["cluster_config"] in (None, ""):
176
176
  self.cluster_config = None
@@ -4,7 +4,7 @@ import logging
4
4
  import sys
5
5
 
6
6
  import numpy
7
- from silx.utils.enum import Enum as _Enum
7
+ from enum import Enum as _Enum
8
8
 
9
9
  _logger = logging.getLogger(__name__)
10
10
 
@@ -36,7 +36,7 @@ class ComputedScore:
36
36
  return self._tomo_consistency
37
37
 
38
38
  def get(self, method: ScoreMethod):
39
- method = ScoreMethod.from_value(method)
39
+ method = ScoreMethod(method)
40
40
  if method is ScoreMethod.TV:
41
41
  return self.total_variation / float(10e5)
42
42
  elif method is ScoreMethod.TV_INVERSE:
@@ -135,7 +135,7 @@ def compute_score(
135
135
  :param method:
136
136
  :return: score of the frame
137
137
  """
138
- method = ScoreMethod.from_value(method)
138
+ method = ScoreMethod(method)
139
139
  if data.ndim == 3:
140
140
  if data.shape[0] == 1:
141
141
  data = data.reshape(data.shape[1], data.shape[2])
@@ -40,7 +40,7 @@ def test_read_x_rotation_axis_pixel_position(nxtomo_scan_360): # noqa F811
40
40
  with h5py.File(nxtomo_scan_360.master_file, mode="a") as h5f:
41
41
  h5f[x_rotation_axis_pixel_position_path] = 12.5
42
42
 
43
- nxtomo_scan_360.clear_caches()
43
+ nxtomo_scan_360.clear_cache()
44
44
  task.run()
45
45
  assert nxtomo_scan_360.axis_params.absolute_cor_value == 22.5
46
46
  assert nxtomo_scan_360.axis_params.relative_cor_value == 12.5
@@ -3,9 +3,7 @@ from __future__ import annotations
3
3
 
4
4
 
5
5
  import os
6
- import shutil
7
- import tempfile
8
- import unittest
6
+ import pytest
9
7
 
10
8
  import numpy
11
9
 
@@ -18,74 +16,66 @@ from tomwer.core.process.reconstruction.scores.scores import (
18
16
  from tomwer.core.utils.scanutils import MockNXtomo
19
17
 
20
18
 
21
- class TestScoreFunctions(unittest.TestCase):
22
- """Test all the score functions"""
19
+ def test_img_contrast_std_score():
20
+ """simple test of the API to call compute_score_contrast_std"""
21
+ data = numpy.random.random(100 * 100).reshape(100, 100)
22
+ compute_score_contrast_std(data)
23
23
 
24
- def test_img_contrast_std_score(self):
25
- """simple test of the API to call compute_score_contrast_std"""
26
- data = numpy.random.random(100 * 100).reshape(100, 100)
27
- compute_score_contrast_std(data)
28
24
 
29
- def test_method_to_function(self):
30
- """Test the dictionary used to for linking the score method to the
31
- callback function"""
32
- data = numpy.random.random(100 * 100).reshape(100, 100)
33
- for method_name, fct in _METHOD_TO_FCT.items():
34
- with self.subTest(method_name=method_name, fct=fct):
35
- res = fct(data)
36
- self.assertFalse(res is None)
37
- self.assertTrue(isinstance(res, float))
25
+ @pytest.mark.parametrize("fct", _METHOD_TO_FCT.values())
26
+ def test_method_to_function(fct):
27
+ """Test the dictionary used to for linking the score method to the
28
+ callback function"""
29
+ data = numpy.random.random(100 * 100).reshape(100, 100)
30
+ res = fct(data)
31
+ assert res is not None
32
+ assert isinstance(res, float)
38
33
 
39
34
 
40
- class TestSAAxisProcess(unittest.TestCase):
35
+ def testSAAxisProcess(tmp_path):
41
36
  """Test the SAAxisProcess class"""
37
+ scan_path = tmp_path / "mock_nxtomo"
38
+ scan_path.mkdir()
39
+ # set up
40
+ dim = 10
41
+ mock = MockNXtomo(
42
+ scan_path=scan_path, n_proj=10, n_ini_proj=10, scan_range=180, dim=dim
43
+ )
44
+ mock.add_alignment_radio(index=10, angle=90)
45
+ mock.add_alignment_radio(index=10, angle=0)
46
+ scan = mock.scan
42
47
 
43
- def setUp(self) -> None:
44
- self.tempdir = tempfile.mkdtemp()
45
- dim = 10
46
- mock = MockNXtomo(
47
- scan_path=self.tempdir, n_proj=10, n_ini_proj=10, scan_range=180, dim=dim
48
- )
49
- mock.add_alignment_radio(index=10, angle=90)
50
- mock.add_alignment_radio(index=10, angle=0)
51
- self.scan = mock.scan
48
+ default_saaxis_params = SAAxisParams()
49
+ default_saaxis_params.output_dir = os.path.join(scan_path, "output_dir")
50
+ default_saaxis_params.slice_indexes = {"slice": 4}
51
+ default_saaxis_params.nabu_config = {}
52
+ default_saaxis_params.dry_run = True
53
+ default_saaxis_params.file_format = "hdf5"
52
54
 
53
- self._default_saaxis_params = SAAxisParams()
54
- self._default_saaxis_params.output_dir = os.path.join(
55
- self.tempdir, "output_dir"
56
- )
57
- self._default_saaxis_params.slice_indexes = {"slice": 4}
58
- self._default_saaxis_params.nabu_config = {}
59
- self._default_saaxis_params.dry_run = True
60
- self._default_saaxis_params.file_format = "hdf5"
55
+ # test processing
56
+ process = SAAxisTask(
57
+ inputs={
58
+ "data": scan,
59
+ "sa_axis_params": default_saaxis_params.to_dict(),
60
+ "serialize_output_data": False,
61
+ }
62
+ )
61
63
 
62
- def tearDown(self) -> None:
63
- shutil.rmtree(self.tempdir)
64
-
65
- def test(self):
66
- process = SAAxisTask(
67
- inputs={
68
- "data": self.scan,
69
- "sa_axis_params": self._default_saaxis_params.to_dict(),
70
- "serialize_output_data": False,
71
- }
72
- )
73
-
74
- self._default_saaxis_params.estimated_cor = 11
75
- self._default_saaxis_params.research_width = 2
76
- process = SAAxisTask(
77
- inputs={
78
- "data": self.scan,
79
- "sa_axis_params": self._default_saaxis_params.to_dict(),
80
- "serialize_output_data": False,
81
- },
82
- )
83
- process.run()
84
- process = SAAxisTask(
85
- inputs={
86
- "data": self.scan,
87
- "sa_axis_params": self._default_saaxis_params.to_dict(),
88
- "serialize_output_data": False,
89
- },
90
- )
91
- process.run()
64
+ default_saaxis_params.estimated_cor = 11
65
+ default_saaxis_params.research_width = 2
66
+ process = SAAxisTask(
67
+ inputs={
68
+ "data": scan,
69
+ "sa_axis_params": default_saaxis_params.to_dict(),
70
+ "serialize_output_data": False,
71
+ },
72
+ )
73
+ process.run()
74
+ process = SAAxisTask(
75
+ inputs={
76
+ "data": scan,
77
+ "sa_axis_params": default_saaxis_params.to_dict(),
78
+ "serialize_output_data": False,
79
+ },
80
+ )
81
+ process.run()
@@ -41,19 +41,19 @@ class StitchingMetadata:
41
41
  if value is not None and not isinstance(
42
42
  value, (float, numpy.float32, numpy.float64)
43
43
  ):
44
- raise TypeError
44
+ raise TypeError(f"Invalid type for value. Got {type(value)}")
45
45
  self._pixel_or_voxel_size[axis] = value
46
46
 
47
47
  def setPxPos(self, value, axis):
48
48
  if value is not None and not isinstance(value, (int, numpy.int32)):
49
- raise TypeError
49
+ raise TypeError(f"Invalid type for value. Got {type(value)}")
50
50
  self._pos_as_px[axis] = value
51
51
 
52
52
  def setMetricPos(self, value, axis):
53
53
  if value is not None and not isinstance(
54
54
  value, (int, numpy.float32, numpy.float64, float)
55
55
  ):
56
- raise TypeError
56
+ raise TypeError(f"Invalid type for value. Got {type(value)}")
57
57
  self._pos_as_m[axis] = value
58
58
 
59
59
  def get_raw_position_m(self, axis):
@@ -111,9 +111,9 @@ class StitchingMetadata:
111
111
  return self._pixel_or_voxel_size[axis]
112
112
  elif isinstance(self.tomo_obj, TomoScanBase):
113
113
  if axis == 0:
114
- return self.tomo_obj.y_pixel_size
114
+ return self.tomo_obj.sample_y_pixel_size
115
115
  elif axis in (1, 2):
116
- return self.tomo_obj.x_pixel_size
116
+ return self.tomo_obj.sample_x_pixel_size
117
117
  else:
118
118
  raise TypeError(f"axis is expected to be in (0, 1, 2). {axis} provided")
119
119
  elif isinstance(self.tomo_obj, VolumeBase):
@@ -162,12 +162,9 @@ class StitchingPostProcAggregation(_StitchingPostProcAggregation):
162
162
 
163
163
  def __init__(self, *args, **kwargs) -> None:
164
164
  super().__init__(*args, **kwargs)
165
- print("creates StitchingPostProcAggregation")
166
165
 
167
166
  if isinstance(self.stitching_config, dict):
168
- stitching_type = StitchingType.from_value(
169
- self.stitching_config["stitching"]["type"]
170
- )
167
+ stitching_type = StitchingType(self.stitching_config["stitching"]["type"])
171
168
  if stitching_type is StitchingType.Z_PREPROC:
172
169
  self._stitching_config = PreProcessedZStitchingConfiguration.from_dict(
173
170
  self.stitching_config
@@ -54,7 +54,8 @@ class TestNormalization(unittest.TestCase):
54
54
  "median": numpy.array([800.5, 10800.5]),
55
55
  }
56
56
 
57
- for calc_fct in params._ValueCalculationFct.values():
57
+ for item in params._ValueCalculationFct:
58
+ calc_fct = item.value
58
59
  with self.subTest(calc_fct=calc_fct):
59
60
  process_params.extra_infos = {
60
61
  "start_x": 0,
@@ -127,9 +127,9 @@ class EDFTomoScan(_tsEDFTomoScan, TomwerScanBase):
127
127
  )
128
128
  return EDFTomoScan(scan=identifier.folder)
129
129
 
130
- def clear_caches(self):
131
- _tsEDFTomoScan.clear_caches(self)
132
- TomwerScanBase.clear_caches(self)
130
+ def clear_cache(self):
131
+ _tsEDFTomoScan.clear_cache(self)
132
+ TomwerScanBase.clear_cache(self)
133
133
 
134
134
  @staticmethod
135
135
  def directory_contains_scan(directory, src_pattern, dest_pattern):