tomwer 1.5.0rc0__py3-none-any.whl → 1.5.1__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 (69) hide show
  1. orangecontrib/tomwer/tutorials/id16b/ID16b_insitu.ows +1 -1
  2. orangecontrib/tomwer/tutorials/id16b/ID16b_normalization.ows +1 -1
  3. tomwer/app/axis.py +1 -1
  4. tomwer/core/process/control/datalistener/rpcserver.py +2 -8
  5. tomwer/core/process/drac/binning.py +2 -2
  6. tomwer/core/process/drac/output.py +1 -1
  7. tomwer/core/process/reconstruction/axis/mode.py +2 -2
  8. tomwer/core/process/reconstruction/axis/params.py +4 -4
  9. tomwer/core/process/reconstruction/axis/projectiontype.py +1 -1
  10. tomwer/core/process/reconstruction/axis/side.py +1 -1
  11. tomwer/core/process/reconstruction/darkref/params.py +1 -2
  12. tomwer/core/process/reconstruction/nabu/nabucommon.py +2 -2
  13. tomwer/core/process/reconstruction/nabu/nabuslices.py +18 -5
  14. tomwer/core/process/reconstruction/nabu/target.py +1 -1
  15. tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +9 -0
  16. tomwer/core/process/reconstruction/nabu/utils.py +3 -0
  17. tomwer/core/process/reconstruction/normalization/normalization.py +1 -1
  18. tomwer/core/process/reconstruction/normalization/params.py +3 -3
  19. tomwer/core/process/reconstruction/saaxis/params.py +3 -3
  20. tomwer/core/process/reconstruction/saaxis/saaxis.py +5 -1
  21. tomwer/core/process/reconstruction/scores/params.py +2 -2
  22. tomwer/core/process/reconstruction/scores/scores.py +3 -3
  23. tomwer/core/process/reconstruction/tests/test_saaxis.py +56 -66
  24. tomwer/core/process/tests/test_normalization.py +2 -1
  25. tomwer/core/scan/scanbase.py +1 -1
  26. tomwer/core/scan/scantype.py +1 -1
  27. tomwer/core/settings.py +1 -1
  28. tomwer/gui/cluster/slurm.py +3 -3
  29. tomwer/gui/configuration/level.py +1 -1
  30. tomwer/gui/control/actions.py +1 -1
  31. tomwer/gui/control/datalist.py +1 -1
  32. tomwer/gui/control/series/seriescreator.py +5 -5
  33. tomwer/gui/control/tomoobjdisplaymode.py +1 -1
  34. tomwer/gui/dataportal/gallery.py +6 -6
  35. tomwer/gui/edit/tests/test_nx_editor.py +1 -1
  36. tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +2 -2
  37. tomwer/gui/reconstruction/axis/InputWidget.py +3 -3
  38. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +1 -3
  39. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -6
  40. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +3 -3
  41. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +3 -3
  42. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +7 -3
  43. tomwer/gui/reconstruction/nabu/slices.py +6 -6
  44. tomwer/gui/reconstruction/nabu/volume.py +1 -1
  45. tomwer/gui/reconstruction/normalization/intensity.py +6 -10
  46. tomwer/gui/reconstruction/saaxis/corrangeselector.py +2 -2
  47. tomwer/gui/reconstruction/sacommon.py +2 -2
  48. tomwer/gui/reconstruction/scores/scoreplot.py +3 -3
  49. tomwer/gui/reconstruction/tests/test_nabu.py +2 -2
  50. tomwer/gui/stitching/config/positionoveraxis.py +1 -1
  51. tomwer/gui/utils/buttons.py +1 -1
  52. tomwer/gui/utils/flow.py +1 -1
  53. tomwer/gui/utils/loadingmode.py +1 -1
  54. tomwer/gui/utils/vignettes.py +1 -1
  55. tomwer/gui/visualization/dataviewer.py +7 -7
  56. tomwer/gui/visualization/reconstructionparameters.py +35 -23
  57. tomwer/gui/visualization/scanoverview.py +28 -11
  58. tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -2
  59. tomwer/resources/gui/icons/borders.png +0 -0
  60. tomwer/synctools/stacks/processingstack.py +19 -3
  61. tomwer/synctools/stacks/reconstruction/nabu.py +5 -0
  62. tomwer/synctools/utils/scanstages.py +3 -3
  63. tomwer/version.py +2 -2
  64. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/METADATA +1 -1
  65. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/RECORD +69 -68
  66. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/WHEEL +0 -0
  67. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/entry_points.txt +0 -0
  68. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/licenses/LICENSE +0 -0
  69. {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/top_level.txt +0 -0
@@ -31,7 +31,7 @@
31
31
  <thumbnail />
32
32
  <node_properties>
33
33
  <properties node_id="0" format="literal">{'_muted': False, 'controlAreaVisible': False, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x04n\x00\x00\x01\xfe\x00\x00\x05\xc1\x00\x00\x03-\x00\x00\x04n\x00\x00\x02#\x00\x00\x05\xc1\x00\x00\x03-\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x04n\x00\x00\x02#\x00\x00\x05\xc1\x00\x00\x03-', '__version__': 1}</properties>
34
- <properties node_id="1" format="literal">{'_ewoks_default_inputs': {'data': None, 'nabu_params': {'preproc': {'flatfield': 1, 'double_flatfield_enabled': 0, 'dff_sigma': 0.0, 'ccd_filter_enabled': 0, 'ccd_filter_threshold': 0.04, 'take_logarithm': True, 'log_min_clip': 1e-06, 'log_max_clip': 10.0, 'sino_rings_correction': 'None', 'sino_rings_options': 'sigma=1.0 ; levels=10 ; padding=False', 'tilt_correction': '', 'autotilt_options': '', 'normalize_srcurrent': 1}, 'reconstruction': {'method': 'FBP', 'slice_plane': 'XY', 'angles_file': '', 'axis_correction_file': '', 'angle_offset': 0.0, 'fbp_filter_type': 'ramlak', 'padding_type': 'edges', 'iterations': 200, 'optim_algorithm': 'chambolle-pock', 'weight_tv': 0.01, 'preconditioning_filter': 1, 'positivity_constraint': 1, 'rotation_axis_position': '', 'translation_movements_file': '', 'clip_outer_circle': 1, 'centered_axis': 1, 'start_x': 0, 'end_x': -1, 'start_y': 0, 'end_y': -1, 'start_z': 0, 'end_z': -1, 'enable_halftomo': 0}, 'dataset': {'binning': 1, 'binning_z': 1, 'projections_subsampling': 1}, 'tomwer_slices': 'middle', 'output': {'file_format': 'vol', 'location': '', 'output_dir_mode': 'same folder as scan'}, 'phase': {'method': 'Paganin', 'delta_beta': '180', 'padding_type': 'edge', 'unsharp_coeff': 3.0, 'unsharp_sigma': 0.8, 'ctf_geometry': ' z1_v=None; z1_h=None; detec_pixel_size=None; magnification=True', 'beam_shape': 'parallel', 'ctf_advanced_params': ' length_scale=1e-05; lim1=1e-05; lim2=0.2; normalize_by_mean=True', 'ctf_translations_file': ''}, 'configuration_level': 'optional', 'mode_locked': True, 'cluster_config': None}}, 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12', '__version__': 1}</properties>
34
+ <properties node_id="1" format="literal">{'_ewoks_default_inputs': {'data': None, 'nabu_params': {'preproc': {'flatfield': 1, 'double_flatfield': 0, 'dff_sigma': 0.0, 'ccd_filter_enabled': 0, 'ccd_filter_threshold': 0.04, 'take_logarithm': True, 'log_min_clip': 1e-06, 'log_max_clip': 10.0, 'sino_rings_correction': 'None', 'sino_rings_options': 'sigma=1.0 ; levels=10 ; padding=False', 'tilt_correction': '', 'autotilt_options': '', 'normalize_srcurrent': 1}, 'reconstruction': {'method': 'FBP', 'slice_plane': 'XY', 'angles_file': '', 'axis_correction_file': '', 'angle_offset': 0.0, 'fbp_filter_type': 'ramlak', 'padding_type': 'edges', 'iterations': 200, 'optim_algorithm': 'chambolle-pock', 'weight_tv': 0.01, 'preconditioning_filter': 1, 'positivity_constraint': 1, 'rotation_axis_position': '', 'translation_movements_file': '', 'clip_outer_circle': 1, 'centered_axis': 1, 'start_x': 0, 'end_x': -1, 'start_y': 0, 'end_y': -1, 'start_z': 0, 'end_z': -1, 'enable_halftomo': 0}, 'dataset': {'binning': 1, 'binning_z': 1, 'projections_subsampling': 1}, 'tomwer_slices': 'middle', 'output': {'file_format': 'vol', 'location': '', 'output_dir_mode': 'same folder as scan'}, 'phase': {'method': 'Paganin', 'delta_beta': '180', 'padding_type': 'edge', 'unsharp_coeff': 3.0, 'unsharp_sigma': 0.8, 'ctf_geometry': ' z1_v=None; z1_h=None; detec_pixel_size=None; magnification=True', 'beam_shape': 'parallel', 'ctf_advanced_params': ' length_scale=1e-05; lim1=1e-05; lim2=0.2; normalize_by_mean=True', 'ctf_translations_file': ''}, 'configuration_level': 'optional', 'mode_locked': True, 'cluster_config': None}}, 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x02\xaa\x00\x00\x00\xb4\x00\x00\x083\x00\x00\x04\x12', '__version__': 1}</properties>
35
35
  <properties node_id="2" format="pickle">gASVPgEAAAAAAAB9lCiMDl92aWV3ZXJfY29uZmlnlH2UKIwEbW9kZZSMI3RvbXdlci5ndWkudmlz
36
36
  dWFsaXphdGlvbi5kYXRhdmlld2VylIwMX0Rpc3BsYXlNb2RllJOUjAZzbGljZXOUhZRSlIwJc2xp
37
37
  Y2Vfb3B0lGgEjApfU2xpY2VNb2RllJOUjAZsYXRlc3SUhZRSlIwJcmFkaW9fb3B0lGgEjApfUmFk
@@ -33,7 +33,7 @@
33
33
  <properties node_id="1" format="literal">{'_ewoks_default_inputs': {'data': None, 'dark_ref_params': {'DOWHEN': 'before', 'DARKCAL': 'Average', 'DARKOVE': 1, 'DARKRMV': 0, 'DKFILE': 'darkend[0-9]{3,4}', 'REFSCAL': 'Median', 'REFSOVE': 1, 'REFSRMV': 0, 'RFFILE': 'ref*.*[0-9]{3,4}_[0-9]{3,4}'}}, 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x00H\x00\x00\x00\x1b\x00\x00\x03\xef\x00\x00\x02\x1f\x00\x00\x00H\x00\x00\x00@\x00\x00\x03\xef\x00\x00\x02\x1f\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00H\x00\x00\x00@\x00\x00\x03\xef\x00\x00\x02\x1f', '__version__': 1}</properties>
34
34
  <properties node_id="2" format="literal">{'_scanIDs': [], 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x02\x80\x00\x00\x01C\x00\x00\x04\xff\x00\x00\x03G\x00\x00\x02\x80\x00\x00\x01h\x00\x00\x04\xff\x00\x00\x03G\x00\x00\x00\x00\x00\x00\x00\x00\x07\x80\x00\x00\x02\x80\x00\x00\x01h\x00\x00\x04\xff\x00\x00\x03G', '__version__': 1}</properties>
35
35
  <properties node_id="3" format="literal">{'_muted': False, 'controlAreaVisible': True, 'savedWidgetGeometry': None, '__version__': 1}</properties>
36
- <properties node_id="4" format="literal">{'_ewoks_default_inputs': {'data': None, 'nabu_params': {'preproc': {'flatfield': 1, 'double_flatfield_enabled': 0, 'dff_sigma': 0.0, 'ccd_filter_enabled': 0, 'ccd_filter_threshold': 0.04, 'take_logarithm': True, 'log_min_clip': 1e-06, 'log_max_clip': 10.0, 'sino_rings_correction': 'None', 'sino_rings_options': 'sigma=1.0 ; levels=10', 'tilt_correction': '', 'autotilt_options': ''}, 'reconstruction': {'method': 'FBP', 'angles_file': '', 'axis_correction_file': '', 'angle_offset': 0.0, 'fbp_filter_type': 'ramlak', 'padding_type': 'edges', 'iterations': 200, 'optim_algorithm': 'chambolle-pock', 'weight_tv': 0.01, 'preconditioning_filter': 1, 'positivity_constraint': 1, 'rotation_axis_position': '', 'translation_movements_file': '', 'clip_outer_circle': 1, 'start_x': 0, 'end_x': -1, 'start_y': 0, 'end_y': -1, 'start_z': 0, 'end_z': -1, 'enable_halftomo': 0}, 'dataset': {'binning': 1, 'binning_z': 1, 'projections_subsampling': 1}, 'tomwer_slices': 'middle', 'output': {'file_format': 'vol', 'location': ''}, 'phase': {'method': 'Paganin', 'delta_beta': '500', 'padding_type': 'edge', 'unsharp_coeff': 3.0, 'unsharp_sigma': 0.65}, 'configuration_level': 'optional', 'mode_locked': False, 'cluster_config': None}}, 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e', '__version__': 1}</properties>
36
+ <properties node_id="4" format="literal">{'_ewoks_default_inputs': {'data': None, 'nabu_params': {'preproc': {'flatfield': 1, 'double_flatfield': 0, 'dff_sigma': 0.0, 'ccd_filter_enabled': 0, 'ccd_filter_threshold': 0.04, 'take_logarithm': True, 'log_min_clip': 1e-06, 'log_max_clip': 10.0, 'sino_rings_correction': 'None', 'sino_rings_options': 'sigma=1.0 ; levels=10', 'tilt_correction': '', 'autotilt_options': ''}, 'reconstruction': {'method': 'FBP', 'angles_file': '', 'axis_correction_file': '', 'angle_offset': 0.0, 'fbp_filter_type': 'ramlak', 'padding_type': 'edges', 'iterations': 200, 'optim_algorithm': 'chambolle-pock', 'weight_tv': 0.01, 'preconditioning_filter': 1, 'positivity_constraint': 1, 'rotation_axis_position': '', 'translation_movements_file': '', 'clip_outer_circle': 1, 'start_x': 0, 'end_x': -1, 'start_y': 0, 'end_y': -1, 'start_z': 0, 'end_z': -1, 'enable_halftomo': 0}, 'dataset': {'binning': 1, 'binning_z': 1, 'projections_subsampling': 1}, 'tomwer_slices': 'middle', 'output': {'file_format': 'vol', 'location': ''}, 'phase': {'method': 'Paganin', 'delta_beta': '500', 'padding_type': 'edge', 'unsharp_coeff': 3.0, 'unsharp_sigma': 0.65}, 'configuration_level': 'optional', 'mode_locked': False, 'cluster_config': None}}, 'controlAreaVisible': True, 'savedWidgetGeometry': b'\x01\xd9\xd0\xcb\x00\x03\x00\x00\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00H\x00\x00\x00@\x00\x00\x05\xd1\x00\x00\x03\x9e', '__version__': 1}</properties>
37
37
  <properties node_id="5" format="pickle">gASVWQEAAAAAAAB9lCiMDl92aWV3ZXJfY29uZmlnlH2UKIwEbW9kZZSMCGJ1aWx0aW5zlIwHZ2V0
38
38
  YXR0cpSTlIwjdG9td2VyLmd1aS52aXN1YWxpemF0aW9uLmRhdGF2aWV3ZXKUjAxfRGlzcGxheU1v
39
39
  ZGWUk5SMBlNMSUNFU5SGlFKUjAlzbGljZV9vcHSUaAZoB4wKX1NsaWNlTW9kZZSTlIwGTEFURVNU
tomwer/app/axis.py CHANGED
@@ -104,7 +104,7 @@ def main(argv):
104
104
  parser.add_argument(
105
105
  "--mode",
106
106
  default=None,
107
- help=f"Use a specific mode. Available modes are {AxisMode.values()}",
107
+ help=f"Use a specific mode. Available modes are {[item.value for item in AxisMode]}",
108
108
  )
109
109
  parser.add_argument(
110
110
  "--full-image",
@@ -1,6 +1,7 @@
1
1
  # coding: utf-8
2
2
  from __future__ import annotations
3
3
 
4
+ from enum import Enum as _Enum
4
5
  import getpass
5
6
  import logging
6
7
  import socket
@@ -10,7 +11,6 @@ from multiprocessing import Process
10
11
 
11
12
  from jsonrpc import JSONRPCResponseManager, dispatcher
12
13
  from psutil import process_iter
13
- from silx.utils.enum import Enum as _Enum
14
14
  from werkzeug.serving import run_simple
15
15
  from werkzeug.wrappers import Request, Response
16
16
 
@@ -26,12 +26,6 @@ class TangoAcquisitionStatus(_Enum):
26
26
  ENDED = "ended"
27
27
 
28
28
 
29
- class _TangoState:
30
- MOVING = "moving"
31
- ON = "on"
32
- FAULT = "fault"
33
-
34
-
35
29
  class BlissAcquisition:
36
30
  """Define an acquisition made with bliss / tango"""
37
31
 
@@ -59,7 +53,7 @@ class BlissAcquisition:
59
53
  self.scan_numbers.append(scan_number)
60
54
 
61
55
  def set_status(self, status):
62
- self.status = TangoAcquisitionStatus.from_value(status)
56
+ self.status = TangoAcquisitionStatus(status)
63
57
 
64
58
  def end(self, end_time, succeed: bool, error: str | None):
65
59
  if succeed is True:
@@ -1,5 +1,5 @@
1
1
  import numpy
2
- from silx.utils.enum import Enum as _Enum
2
+ from enum import Enum as _Enum
3
3
 
4
4
 
5
5
  class Binning(_Enum):
@@ -18,7 +18,7 @@ class Binning(_Enum):
18
18
  raise TypeError("data should be a numpy array")
19
19
  if not data.ndim == 2:
20
20
  raise ValueError("data is expected to be 2d")
21
- binning = Binning.from_value(binning)
21
+ binning = Binning(binning)
22
22
  if binning is Binning.ONE_BY_ONE:
23
23
  return data
24
24
  elif binning is Binning.TWO_BY_TWO:
@@ -1,4 +1,4 @@
1
- from silx.utils.enum import Enum as _Enum
1
+ from enum import Enum as _Enum
2
2
 
3
3
 
4
4
  PROPOSAL_GALLERY_DIR_NAME = "GALLERY"
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
 
3
- from silx.utils.enum import Enum as _Enum
3
+ from enum import Enum as _Enum
4
4
  from tomwer.core.process.reconstruction.axis.side import Side
5
5
 
6
6
  _logger = logging.getLogger(__name__)
@@ -120,7 +120,7 @@ class AxisMode(_Enum):
120
120
  elif value in ("read", "read from estimated cor"):
121
121
  value = AxisMode.read
122
122
 
123
- return super().from_value(value=value)
123
+ return AxisMode(value)
124
124
 
125
125
  def requires_radio_indices(self) -> bool:
126
126
  return self in (
@@ -5,7 +5,7 @@ from collections import namedtuple
5
5
 
6
6
  import numpy
7
7
  from silx.io.url import DataUrl
8
- from silx.utils.enum import Enum as _Enum
8
+ from enum import Enum as _Enum
9
9
  from tomoscan.esrf.scan.utils import get_data
10
10
 
11
11
  from tomwer.core.process.reconstruction.utils.cor import relative_pos_to_absolute
@@ -60,8 +60,8 @@ class AxisCalculationInput(_Enum):
60
60
  if type(value) is str and len(value.split("_")) == 2:
61
61
  proj_type, pag = value.split("_")
62
62
  value_pag = True if pag == _WITH_PAG else False
63
- value_proj = ProjectionType.from_value(proj_type)
64
- return cls.from_value(_calculation_conf(value_proj, value_pag))
63
+ value_proj = ProjectionType(proj_type)
64
+ return cls(_calculation_conf(value_proj, value_pag))
65
65
  elif isinstance(value, cls):
66
66
  return value
67
67
  else:
@@ -348,7 +348,7 @@ class AxisRP:
348
348
  @estimated_cor.setter
349
349
  def estimated_cor(self, value: Side | float | None):
350
350
  try:
351
- value = Side.from_value(value)
351
+ value = Side(value)
352
352
  except ValueError:
353
353
  pass
354
354
  if self.__estimated_cor != 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 ProjectionType(_Enum):
@@ -1,4 +1,4 @@
1
- from silx.utils.enum import Enum as _Enum
1
+ from enum import Enum as _Enum
2
2
 
3
3
 
4
4
  class Side(_Enum):
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
 
4
4
  import enum
5
5
 
6
- from silx.utils.enum import Enum as _Enum
7
6
  from tomoscan.framereducer.method import ReduceMethod
8
7
 
9
8
  from tomwer.core.process.reconstruction.darkref.settings import (
@@ -17,7 +16,7 @@ from tomwer.core.utils.deprecation import deprecated
17
16
  # TODO: those classes (when, method) should be linked / embedded in the DarkRef
18
17
  # method
19
18
  @enum.unique
20
- class When(_Enum):
19
+ class When(enum.Enum):
21
20
  never = (0,)
22
21
  before = (1,)
23
22
  after = (2,)
@@ -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
@@ -5,6 +5,7 @@ import functools
5
5
  import logging
6
6
  import os
7
7
  import gc
8
+ from collections.abc import Callable
8
9
  from tomwer.io.utils import format_stderr_stdout
9
10
  from silx.utils.deprecation import deprecated, deprecated_warning
10
11
  from silx.io.utils import open as open_hdf5
@@ -85,6 +86,7 @@ def run_slices_reconstruction(
85
86
  advancement=None,
86
87
  process_id: int | None = None,
87
88
  instantiate_classes_only: bool = False,
89
+ invalid_slice_callback: Callable[[str], None] | None = None,
88
90
  ) -> tuple:
89
91
  """
90
92
  call nabu for a reconstruction on scan with the given configuration
@@ -142,7 +144,9 @@ def run_slices_reconstruction(
142
144
  scan.nabu_recons_params = sc_config
143
145
 
144
146
  # handle special cases like several db...
145
- nabu_configurations = interpret_tomwer_configuration(config, scan=scan)
147
+ nabu_configurations = interpret_tomwer_configuration(
148
+ config, scan=scan, invalid_slice_callback=invalid_slice_callback
149
+ )
146
150
  output_urls = []
147
151
  stderrs = []
148
152
  stdouts = []
@@ -227,6 +231,7 @@ class NabuSlicesTask(
227
231
  optional_input_names=(
228
232
  "dry_run",
229
233
  "serialize_output_data",
234
+ "invalid_slice_callback",
230
235
  ),
231
236
  output_names=("data", "nabu_params", "future_tomo_obj"),
232
237
  ):
@@ -288,6 +293,9 @@ class NabuSlicesTask(
288
293
  dry_run=self._dry_run,
289
294
  process_id=self.process_id,
290
295
  instantiate_classes_only=True,
296
+ invalid_slice_callback=self.get_input_value(
297
+ "invalid_slice_callback", None
298
+ ),
291
299
  )
292
300
  except Exception as e:
293
301
  mess = f"Fail to instantiate slice reconstructor for {str(scan)}. Reason is {e}."
@@ -425,7 +433,11 @@ class NabuSlicesTask(
425
433
  self._current_processing.cancel()
426
434
 
427
435
 
428
- def interpret_tomwer_configuration(config: dict, scan: TomwerScanBase | None) -> tuple:
436
+ def interpret_tomwer_configuration(
437
+ config: dict,
438
+ scan: TomwerScanBase | None,
439
+ invalid_slice_callback: Callable[[str], None] | None = None,
440
+ ) -> tuple:
429
441
  """
430
442
  tomwer can 'mock' the nabu reconstruction to request more feature.
431
443
  Typical use case is that we can ask for reconstruction of several
@@ -471,9 +483,10 @@ def interpret_tomwer_configuration(config: dict, scan: TomwerScanBase | None) ->
471
483
  index_max = index_max - 1
472
484
 
473
485
  if slice_index > index_max:
474
- _logger.error(
475
- f"slice index {slice_index} requested. But slice index must be in 0-{index_max} - ignore this request"
476
- )
486
+ error_message = f"{scan.get_identifier().short_description()}\n\nCannot reconstruct slice {slice_index} along plane {axis.value}. Must be in [0-{index_max}]"
487
+ _logger.error(error_message)
488
+ if invalid_slice_callback is not None:
489
+ invalid_slice_callback(error_message)
477
490
  return False
478
491
  return True
479
492
 
@@ -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):
@@ -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
+ )
@@ -409,6 +409,9 @@ def nabu_std_err_has_error(errs: bytes | None):
409
409
  or " unable to import 'siphash24.siphash13" in line
410
410
  or "_create_built_program_from_source_cached" in line
411
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)
412
415
  )
413
416
 
414
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):
@@ -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):
@@ -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])
@@ -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()
@@ -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,
@@ -10,7 +10,7 @@ from typing import Iterable
10
10
 
11
11
  import numpy
12
12
  from silx.io.url import DataUrl
13
- from silx.utils.enum import Enum as _Enum
13
+ from enum import Enum as _Enum
14
14
 
15
15
  from tomoscan.identifier import VolumeIdentifier
16
16
  from tomoscan.normalization import IntensityNormalization
@@ -1,4 +1,4 @@
1
- from silx.utils.enum import Enum as _Enum
1
+ from enum import Enum as _Enum
2
2
 
3
3
 
4
4
  class ScanType(_Enum):
tomwer/core/settings.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import os
2
- from silx.utils.enum import Enum as _Enum
2
+ from enum import Enum as _Enum
3
3
 
4
4
 
5
5
  __LBSRAM_PATH = "/lbsram"
@@ -94,7 +94,7 @@ class SlurmSettingsWindow(qt.QMainWindow):
94
94
 
95
95
  self._modeCombox = qt.QComboBox(self)
96
96
  self._mainWidget.layout().addRow("configuration: ", self._modeCombox)
97
- self._modeCombox.addItems(SlurmSettingsMode.values())
97
+ self._modeCombox.addItems([item.value for item in SlurmSettingsMode])
98
98
  self._modeCombox.setCurrentText(SlurmSettingsMode.GENERIC.value)
99
99
 
100
100
  self._settingsWidget = SlurmSettingsWidget(self, jobLimitation=None)
@@ -155,10 +155,10 @@ class SlurmSettingsWindow(qt.QMainWindow):
155
155
  self._modeCombox.setCurrentText(SlurmSettingsMode.MANUAL.value)
156
156
 
157
157
  def getCurrentSettingsMode(self) -> SlurmSettingsMode:
158
- return SlurmSettingsMode.from_value(self._modeCombox.currentText())
158
+ return SlurmSettingsMode(self._modeCombox.currentText())
159
159
 
160
160
  def setCurrentSettingsMode(self, mode: SlurmSettingsMode) -> SlurmSettingsMode:
161
- mode = SlurmSettingsMode.from_value(mode)
161
+ mode = SlurmSettingsMode(mode)
162
162
  self._modeCombox.setCurrentText(mode.value)
163
163
 
164
164
  def setMode(self, mode: SlurmSettingsMode) -> None: