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.
- orangecontrib/tomwer/tutorials/id16b/ID16b_insitu.ows +1 -1
- orangecontrib/tomwer/tutorials/id16b/ID16b_normalization.ows +1 -1
- tomwer/app/axis.py +1 -1
- tomwer/core/process/control/datalistener/rpcserver.py +2 -8
- tomwer/core/process/drac/binning.py +2 -2
- tomwer/core/process/drac/output.py +1 -1
- tomwer/core/process/reconstruction/axis/mode.py +2 -2
- tomwer/core/process/reconstruction/axis/params.py +4 -4
- tomwer/core/process/reconstruction/axis/projectiontype.py +1 -1
- tomwer/core/process/reconstruction/axis/side.py +1 -1
- tomwer/core/process/reconstruction/darkref/params.py +1 -2
- tomwer/core/process/reconstruction/nabu/nabucommon.py +2 -2
- tomwer/core/process/reconstruction/nabu/nabuslices.py +18 -5
- tomwer/core/process/reconstruction/nabu/target.py +1 -1
- tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +9 -0
- tomwer/core/process/reconstruction/nabu/utils.py +3 -0
- tomwer/core/process/reconstruction/normalization/normalization.py +1 -1
- tomwer/core/process/reconstruction/normalization/params.py +3 -3
- tomwer/core/process/reconstruction/saaxis/params.py +3 -3
- tomwer/core/process/reconstruction/saaxis/saaxis.py +5 -1
- tomwer/core/process/reconstruction/scores/params.py +2 -2
- tomwer/core/process/reconstruction/scores/scores.py +3 -3
- tomwer/core/process/reconstruction/tests/test_saaxis.py +56 -66
- tomwer/core/process/tests/test_normalization.py +2 -1
- tomwer/core/scan/scanbase.py +1 -1
- tomwer/core/scan/scantype.py +1 -1
- tomwer/core/settings.py +1 -1
- tomwer/gui/cluster/slurm.py +3 -3
- tomwer/gui/configuration/level.py +1 -1
- tomwer/gui/control/actions.py +1 -1
- tomwer/gui/control/datalist.py +1 -1
- tomwer/gui/control/series/seriescreator.py +5 -5
- tomwer/gui/control/tomoobjdisplaymode.py +1 -1
- tomwer/gui/dataportal/gallery.py +6 -6
- tomwer/gui/edit/tests/test_nx_editor.py +1 -1
- tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +2 -2
- tomwer/gui/reconstruction/axis/InputWidget.py +3 -3
- tomwer/gui/reconstruction/nabu/nabuconfig/base.py +1 -3
- tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -6
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +3 -3
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +3 -3
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +7 -3
- tomwer/gui/reconstruction/nabu/slices.py +6 -6
- tomwer/gui/reconstruction/nabu/volume.py +1 -1
- tomwer/gui/reconstruction/normalization/intensity.py +6 -10
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +2 -2
- tomwer/gui/reconstruction/sacommon.py +2 -2
- tomwer/gui/reconstruction/scores/scoreplot.py +3 -3
- tomwer/gui/reconstruction/tests/test_nabu.py +2 -2
- tomwer/gui/stitching/config/positionoveraxis.py +1 -1
- tomwer/gui/utils/buttons.py +1 -1
- tomwer/gui/utils/flow.py +1 -1
- tomwer/gui/utils/loadingmode.py +1 -1
- tomwer/gui/utils/vignettes.py +1 -1
- tomwer/gui/visualization/dataviewer.py +7 -7
- tomwer/gui/visualization/reconstructionparameters.py +35 -23
- tomwer/gui/visualization/scanoverview.py +28 -11
- tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -2
- tomwer/resources/gui/icons/borders.png +0 -0
- tomwer/synctools/stacks/processingstack.py +19 -3
- tomwer/synctools/stacks/reconstruction/nabu.py +5 -0
- tomwer/synctools/utils/scanstages.py +3 -3
- tomwer/version.py +2 -2
- {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/METADATA +1 -1
- {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/RECORD +69 -68
- {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/WHEEL +0 -0
- {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/entry_points.txt +0 -0
- {tomwer-1.5.0rc0.dist-info → tomwer-1.5.1.dist-info}/licenses/LICENSE +0 -0
- {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, '
|
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, '
|
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
|
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
|
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
|
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
|
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,6 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
|
3
|
-
from
|
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
|
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
|
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
|
64
|
-
return cls
|
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
|
351
|
+
value = Side(value)
|
352
352
|
except ValueError:
|
353
353
|
pass
|
354
354
|
if self.__estimated_cor != value:
|
@@ -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(
|
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
|
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
|
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(
|
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(
|
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
|
-
|
475
|
-
|
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
|
|
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
22
|
-
"""
|
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
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
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,
|
tomwer/core/scan/scanbase.py
CHANGED
@@ -10,7 +10,7 @@ from typing import Iterable
|
|
10
10
|
|
11
11
|
import numpy
|
12
12
|
from silx.io.url import DataUrl
|
13
|
-
from
|
13
|
+
from enum import Enum as _Enum
|
14
14
|
|
15
15
|
from tomoscan.identifier import VolumeIdentifier
|
16
16
|
from tomoscan.normalization import IntensityNormalization
|
tomwer/core/scan/scantype.py
CHANGED
tomwer/core/settings.py
CHANGED
tomwer/gui/cluster/slurm.py
CHANGED
@@ -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
|
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
|
158
|
+
return SlurmSettingsMode(self._modeCombox.currentText())
|
159
159
|
|
160
160
|
def setCurrentSettingsMode(self, mode: SlurmSettingsMode) -> SlurmSettingsMode:
|
161
|
-
mode = SlurmSettingsMode
|
161
|
+
mode = SlurmSettingsMode(mode)
|
162
162
|
self._modeCombox.setCurrentText(mode.value)
|
163
163
|
|
164
164
|
def setMode(self, mode: SlurmSettingsMode) -> None:
|