tomwer 1.4.19__py3-none-any.whl → 1.5.0rc0__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/simple_volume_local_reconstruction.ows +11 -8
- orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +12 -9
- orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -1
- orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +21 -10
- tomwer/app/reducedarkflat.py +2 -2
- tomwer/core/process/edit/imagekeyeditor.py +4 -6
- tomwer/core/process/edit/nxtomoeditor.py +58 -20
- tomwer/core/process/output.py +6 -5
- tomwer/core/process/reconstruction/axis/anglemode.py +2 -2
- tomwer/core/process/reconstruction/axis/axis.py +1 -0
- tomwer/core/process/reconstruction/darkref/darkrefs.py +2 -2
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +1 -1
- tomwer/core/process/reconstruction/darkref/params.py +1 -1
- tomwer/core/process/reconstruction/nabu/castvolume.py +4 -1
- tomwer/core/process/reconstruction/nabu/helical.py +3 -1
- tomwer/core/process/reconstruction/nabu/nabuscores.py +1 -1
- tomwer/core/process/reconstruction/nabu/nabuslices.py +4 -4
- tomwer/core/process/reconstruction/nabu/plane.py +2 -2
- tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +2 -0
- tomwer/core/process/reconstruction/nabu/utils.py +15 -14
- tomwer/core/process/reconstruction/normalization/params.py +1 -1
- tomwer/core/process/reconstruction/output.py +2 -2
- tomwer/core/process/reconstruction/tests/test_axis.py +1 -1
- tomwer/core/process/stitching/metadataholder.py +5 -5
- tomwer/core/process/stitching/nabustitcher.py +1 -4
- tomwer/core/scan/edfscan.py +3 -3
- tomwer/core/scan/nxtomoscan.py +3 -3
- tomwer/core/scan/scanbase.py +2 -2
- tomwer/core/tomwer_object.py +1 -1
- tomwer/core/utils/nxtomoutils.py +2 -2
- tomwer/core/utils/spec.py +6 -3
- tomwer/gui/control/datadiscovery.py +1 -1
- tomwer/gui/control/reducedarkflatselector.py +4 -4
- tomwer/gui/edit/imagekeyeditor.py +7 -9
- tomwer/gui/edit/nxtomoeditor.py +420 -112
- tomwer/gui/edit/tests/test_nx_editor.py +154 -82
- tomwer/gui/reconstruction/axis/CalculationWidget.py +1 -1
- tomwer/gui/reconstruction/axis/EstimatedCORWidget.py +12 -8
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -2
- tomwer/gui/reconstruction/nabu/castvolume.py +16 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/base.py +1 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +1 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +2 -2
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +2 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +71 -49
- tomwer/gui/reconstruction/nabu/nabuflow.py +3 -13
- tomwer/gui/reconstruction/nabu/slices.py +6 -6
- tomwer/gui/reconstruction/nabu/test/test_cast_volume.py +19 -0
- tomwer/gui/reconstruction/normalization/intensity.py +2 -2
- tomwer/gui/reconstruction/saaxis/dimensionwidget.py +71 -67
- tomwer/gui/reconstruction/scores/scoreplot.py +15 -7
- tomwer/gui/reconstruction/tests/test_saaxis.py +18 -16
- tomwer/gui/stitching/SingleAxisStitchingWidget.py +8 -8
- tomwer/gui/stitching/StitchingOptionsWidget.py +1 -1
- tomwer/gui/stitching/alignment.py +8 -8
- tomwer/gui/stitching/config/axisparams.py +2 -2
- tomwer/gui/stitching/config/output.py +1 -1
- tomwer/gui/stitching/config/stitchingstrategies.py +4 -6
- tomwer/gui/stitching/config/tomoobjdetails.py +21 -13
- tomwer/gui/stitching/normalization.py +6 -6
- tomwer/gui/stitching/tests/test_ZStitchingWindow.py +8 -1
- tomwer/gui/stitching/tests/test_preview.py +10 -7
- tomwer/gui/stitching/tests/utils.py +27 -18
- tomwer/gui/stitching/z_stitching/fineestimation.py +7 -9
- tomwer/gui/stitching/z_stitching/tests/test_raw_estimation.py +18 -7
- tomwer/gui/stitching/z_stitching/tests/test_stitching_window.py +7 -2
- tomwer/gui/utils/buttons.py +53 -35
- tomwer/gui/utils/flow.py +1 -1
- tomwer/gui/utils/unitsystem.py +44 -33
- tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
- tomwer/gui/visualization/diffviewer/shiftwidget.py +4 -6
- tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +25 -13
- tomwer/model/dataset.py +0 -0
- tomwer/tasks/reconstruction/cleardarkflat.py +42 -0
- tomwer/tests/app/test_stitching.py +1 -1
- tomwer/tests/orangecontrib/tomwer/widgets/edit/tests/test_nxtomo_editor.py +32 -20
- tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_widget.py +1 -1
- tomwer/version.py +3 -3
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/METADATA +8 -8
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/RECORD +84 -82
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/WHEEL +1 -1
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/entry_points.txt +0 -0
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/licenses/LICENSE +0 -0
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc0.dist-info}/top_level.txt +0 -0
tomwer/gui/utils/unitsystem.py
CHANGED
@@ -9,14 +9,14 @@ from __future__ import annotations
|
|
9
9
|
|
10
10
|
|
11
11
|
import logging
|
12
|
+
import pint
|
12
13
|
|
13
14
|
from silx.gui import qt
|
14
|
-
from pyunitsystem.metricsystem import MetricSystem
|
15
|
-
|
16
|
-
from tomwer.core.utils.char import MU_CHAR
|
17
15
|
|
18
16
|
_logger = logging.getLogger(__name__)
|
19
17
|
|
18
|
+
_ureg = pint.get_application_registry()
|
19
|
+
|
20
20
|
|
21
21
|
class PixelEntry(qt.QWidget):
|
22
22
|
valueChanged = qt.Signal()
|
@@ -69,6 +69,17 @@ class MetricEntry(qt.QWidget):
|
|
69
69
|
editingFinished = qt.Signal()
|
70
70
|
"""emit when editing is finished"""
|
71
71
|
|
72
|
+
valueChanged = qt.Signal()
|
73
|
+
"""emit when the metric value change"""
|
74
|
+
|
75
|
+
_ExposedUnits: set[_ureg.Unit] = {
|
76
|
+
_ureg.nanometer,
|
77
|
+
_ureg.micrometer,
|
78
|
+
_ureg.mm,
|
79
|
+
_ureg.cm,
|
80
|
+
_ureg.m,
|
81
|
+
}
|
82
|
+
|
72
83
|
class DoubleValidator(qt.QDoubleValidator):
|
73
84
|
def __init__(self, *args, **kwargs):
|
74
85
|
super().__init__(*args, **kwargs)
|
@@ -80,22 +91,15 @@ class MetricEntry(qt.QWidget):
|
|
80
91
|
else:
|
81
92
|
return super().validate(a0, a1)
|
82
93
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
"mm": MetricSystem.MILLIMETER.value,
|
87
|
-
"cm": MetricSystem.CENTIMETER.value,
|
88
|
-
"m": MetricSystem.METER.value,
|
89
|
-
}
|
90
|
-
|
91
|
-
valueChanged = qt.Signal()
|
92
|
-
"""emit when the metric value change"""
|
93
|
-
|
94
|
-
def __init__(self, name, value=0.0, default_unit="m", parent=None):
|
94
|
+
def __init__(
|
95
|
+
self, name, value=0.0, default_unit: pint.Unit = _ureg.meter, parent=None
|
96
|
+
):
|
95
97
|
qt.QWidget.__init__(self, parent)
|
96
|
-
|
97
|
-
|
98
|
-
|
98
|
+
if default_unit not in self._ExposedUnits:
|
99
|
+
raise ValueError(
|
100
|
+
f"Unable to use {default_unit} as default unit. Must be in {self._ExposedUnits}"
|
101
|
+
)
|
102
|
+
self._base_unit: pint.Unit = default_unit
|
99
103
|
|
100
104
|
self.setLayout(qt.QHBoxLayout())
|
101
105
|
self._label = qt.QLabel(name, parent=self)
|
@@ -105,11 +109,9 @@ class MetricEntry(qt.QWidget):
|
|
105
109
|
self.layout().addWidget(self._qlePixelSize)
|
106
110
|
|
107
111
|
self._qcbUnit = qt.QComboBox(parent=self)
|
108
|
-
self.
|
109
|
-
|
110
|
-
|
111
|
-
self._qcbUnit.addItem("cm")
|
112
|
-
self._qcbUnit.addItem("m")
|
112
|
+
for unit in self._ExposedUnits:
|
113
|
+
self._qcbUnit.addItem(f"{unit:~}")
|
114
|
+
|
113
115
|
self.layout().addWidget(self._qcbUnit)
|
114
116
|
self._resetBaseUnit()
|
115
117
|
|
@@ -128,10 +130,9 @@ class MetricEntry(qt.QWidget):
|
|
128
130
|
self._label.setText(text)
|
129
131
|
|
130
132
|
def getCurrentUnit(self):
|
131
|
-
|
132
|
-
return self._CONVERSION[self._qcbUnit.currentText()]
|
133
|
+
return _ureg.Unit(self._qcbUnit.currentText())
|
133
134
|
|
134
|
-
def setValue(self, value_m, displayed_unit:
|
135
|
+
def setValue(self, value_m, displayed_unit: pint.Unit = _ureg.meter):
|
135
136
|
"""
|
136
137
|
|
137
138
|
:param value: pixel size in international metric system (meter)
|
@@ -155,16 +156,20 @@ class MetricEntry(qt.QWidget):
|
|
155
156
|
self._qlePixelSize.setText(txt)
|
156
157
|
self._resetBaseUnit(displayed_unit=displayed_unit)
|
157
158
|
|
158
|
-
def _resetBaseUnit(self, displayed_unit=None):
|
159
|
+
def _resetBaseUnit(self, displayed_unit: pint.Unit | None = None):
|
159
160
|
"""Simple reset of the combobox according to the base_unit"""
|
161
|
+
if displayed_unit is not None and not isinstance(displayed_unit, pint.Unit):
|
162
|
+
raise TypeError(
|
163
|
+
f"'displayed_unit' should be a {pint.Unit}. Got {type(displayed_unit)}"
|
164
|
+
)
|
160
165
|
displayed_unit = displayed_unit or self._base_unit
|
161
|
-
index = self._qcbUnit.findText(displayed_unit)
|
162
|
-
if index
|
166
|
+
index = self._qcbUnit.findText(f"{displayed_unit:~}")
|
167
|
+
if index < 0:
|
163
168
|
raise ValueError("unrecognized base unit")
|
164
169
|
else:
|
165
170
|
self._qcbUnit.setCurrentIndex(index)
|
166
171
|
|
167
|
-
def getValue(self) ->
|
172
|
+
def getValue(self) -> pint.Quantity | None:
|
168
173
|
"""
|
169
174
|
|
170
175
|
:return: the value in meter
|
@@ -177,7 +182,13 @@ class MetricEntry(qt.QWidget):
|
|
177
182
|
def setValidator(self, validator):
|
178
183
|
self._qlePixelSize.setValidator(validator)
|
179
184
|
|
180
|
-
def setUnit(self, unit):
|
181
|
-
|
185
|
+
def setUnit(self, unit: pint.Unit):
|
186
|
+
assert isinstance(
|
187
|
+
unit, pint.Unit
|
188
|
+
), f"unit is expected to be a pint.Unit. Got {type(unit)}"
|
189
|
+
unit = f"{unit:~}"
|
182
190
|
idx = self._qcbUnit.findText(unit)
|
183
|
-
|
191
|
+
if idx >= 0:
|
192
|
+
self._qcbUnit.setCurrentIndex(idx)
|
193
|
+
else:
|
194
|
+
_logger.error(f"Unhandled unit ({unit})")
|
@@ -7,13 +7,13 @@ from __future__ import annotations
|
|
7
7
|
import functools
|
8
8
|
import logging
|
9
9
|
import os
|
10
|
+
from enum import Enum
|
10
11
|
|
11
12
|
import numpy
|
12
13
|
from processview.core.dataset import DatasetIdentifier
|
13
14
|
from silx.gui import icons as silx_icons
|
14
15
|
from silx.gui import qt
|
15
16
|
from silx.io.url import DataUrl
|
16
|
-
from silx.utils.enum import Enum as _Enum
|
17
17
|
|
18
18
|
from tomwer.core.scan.nxtomoscan import NXtomoScan
|
19
19
|
from tomwer.core.scan.scanbase import TomwerScanBase
|
@@ -55,7 +55,7 @@ class _FrameSelector(qt.QWidget):
|
|
55
55
|
sigSelectedUrlChanged = qt.Signal()
|
56
56
|
"""signal emitted when the selected url changed"""
|
57
57
|
|
58
|
-
class FrameType(
|
58
|
+
class FrameType(Enum):
|
59
59
|
DARKS = "darks"
|
60
60
|
FLATS = "flats"
|
61
61
|
PROJ = "projections"
|
@@ -110,10 +110,10 @@ class _FrameSelector(qt.QWidget):
|
|
110
110
|
return None
|
111
111
|
|
112
112
|
def getTypeSelected(self):
|
113
|
-
return self.FrameType
|
113
|
+
return self.FrameType(self._frameTypeCB.currentText())
|
114
114
|
|
115
115
|
def _typeChanged(self, *args, **kwargs):
|
116
|
-
type_selected = self.FrameType
|
116
|
+
type_selected = self.FrameType(self.getTypeSelected())
|
117
117
|
self._proj_normalized.setVisible(
|
118
118
|
type_selected in (self.FrameType.PROJ, self.FrameType.ALIGN_PROJ)
|
119
119
|
)
|
@@ -5,11 +5,11 @@ contains gui for diffviewer shift
|
|
5
5
|
"""
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
|
+
from enum import Enum
|
8
9
|
|
9
10
|
import sys
|
10
11
|
|
11
12
|
from silx.gui import qt
|
12
|
-
from silx.utils.enum import Enum as _Enum
|
13
13
|
|
14
14
|
from tomwer.utils import docstring
|
15
15
|
|
@@ -54,7 +54,7 @@ class TwoFramesShiftTab(qt.QTabWidget, _FrameShiftsBase):
|
|
54
54
|
lrflip is a boolean notifying if we should flip image or not before applying the shift
|
55
55
|
"""
|
56
56
|
|
57
|
-
class ShiftMode(
|
57
|
+
class ShiftMode(Enum):
|
58
58
|
RELATIVE = "relative shift"
|
59
59
|
ABSOLUTE = "absolute shift"
|
60
60
|
|
@@ -206,7 +206,7 @@ class Relative2FramesShift(qt.QWidget, _FrameShiftsBase):
|
|
206
206
|
self._controlWidget.setFocus(qt.Qt.OtherFocusReason)
|
207
207
|
|
208
208
|
def move(self, direction: str):
|
209
|
-
direction = _ControlArrowWidget.Direction
|
209
|
+
direction = _ControlArrowWidget.Direction(direction)
|
210
210
|
shift = self._shiftStepSize.value()
|
211
211
|
if direction is _ControlArrowWidget.Direction.RIGHT:
|
212
212
|
self._xShiftQLE.setValue(self._xShiftQLE.value() + shift)
|
@@ -290,14 +290,12 @@ class _ControlArrowWidget(qt.QWidget):
|
|
290
290
|
sigMoved = qt.Signal(str)
|
291
291
|
"""signal emit when one direction is activated. Will contain the direction in which we want to move"""
|
292
292
|
|
293
|
-
class Direction(
|
293
|
+
class Direction(Enum):
|
294
294
|
LEFT = "left"
|
295
295
|
RIGHT = "right"
|
296
296
|
UP = "up"
|
297
297
|
DOWN = "down"
|
298
298
|
|
299
|
-
VALID_DIRECTIONS = Direction.members()
|
300
|
-
|
301
299
|
ARROW_BUTTON_SIZE = 30
|
302
300
|
|
303
301
|
QKEY_TO_DIR = {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
|
3
3
|
import numpy
|
4
|
+
import pint
|
4
5
|
from nxtomo.application.nxtomo import NXtomo
|
5
6
|
from silx.gui import qt
|
6
7
|
from nxtomo.nxobject.nxdetector import ImageKey
|
@@ -9,6 +10,8 @@ from tomwer.core.scan.nxtomoscan import NXtomoScan
|
|
9
10
|
from tomwer.gui.visualization.nxtomometadata import NXtomoMetadataViewer
|
10
11
|
from tomwer.tests.conftest import qtapp # noqa F401
|
11
12
|
|
13
|
+
_ureg = pint.get_application_registry()
|
14
|
+
|
12
15
|
|
13
16
|
def test_nx_editor(
|
14
17
|
tmp_path,
|
@@ -16,18 +19,18 @@ def test_nx_editor(
|
|
16
19
|
):
|
17
20
|
# 1.0 create nx tomo with raw data
|
18
21
|
nx_tomo = NXtomo()
|
19
|
-
nx_tomo.instrument.detector.x_pixel_size = 2.6e-6
|
20
|
-
nx_tomo.instrument.detector.y_pixel_size = 2.5e-6
|
22
|
+
nx_tomo.instrument.detector.x_pixel_size = 2.6e-6 * _ureg.meter
|
23
|
+
nx_tomo.instrument.detector.y_pixel_size = 2.5e-6 * _ureg.meter
|
21
24
|
nx_tomo.instrument.detector.field_of_view = "Half"
|
22
|
-
nx_tomo.instrument.detector.distance = 59.0
|
25
|
+
nx_tomo.instrument.detector.distance = 59.0 * _ureg.meter
|
23
26
|
nx_tomo.instrument.detector.x_flipped = True
|
24
27
|
nx_tomo.instrument.detector.y_flipped = False
|
25
|
-
nx_tomo.energy = 12.8
|
26
|
-
nx_tomo.sample.x_translation = numpy.arange(12)
|
27
|
-
nx_tomo.sample.z_translation = numpy.arange(2, 14)
|
28
|
+
nx_tomo.energy = 12.8 * _ureg.keV
|
29
|
+
nx_tomo.sample.x_translation = numpy.arange(12) * _ureg.meter
|
30
|
+
nx_tomo.sample.z_translation = numpy.arange(2, 14) * _ureg.meter
|
28
31
|
nx_tomo.instrument.detector.image_key_control = [ImageKey.PROJECTION.value] * 12
|
29
32
|
nx_tomo.instrument.detector.data = numpy.empty(shape=(12, 10, 10))
|
30
|
-
nx_tomo.sample.rotation_angle = numpy.linspace(0, 180, num=12)
|
33
|
+
nx_tomo.sample.rotation_angle = numpy.linspace(0, 180, num=12) * _ureg.degree
|
31
34
|
|
32
35
|
file_path = os.path.join(tmp_path, "nxtomo.nx")
|
33
36
|
entry = "entry0000"
|
@@ -49,13 +52,22 @@ def test_nx_editor(
|
|
49
52
|
return current_value is None
|
50
53
|
return expected_value == current_value
|
51
54
|
|
52
|
-
assert check_metric(
|
53
|
-
|
54
|
-
|
55
|
-
|
55
|
+
assert check_metric(
|
56
|
+
2.6e-6,
|
57
|
+
widget._xDetectorPixelSizeMetricEntry.getValue().to(_ureg.meter).magnitude,
|
58
|
+
)
|
59
|
+
assert widget._xDetectorPixelSizeMetricEntry._qcbUnit.currentText() == "m"
|
60
|
+
assert check_metric(
|
61
|
+
2.5e-6,
|
62
|
+
widget._yDetectorPixelSizeMetricEntry.getValue().to(_ureg.meter).magnitude,
|
63
|
+
)
|
64
|
+
assert widget._yDetectorPixelSizeMetricEntry._qcbUnit.currentText() == "m"
|
56
65
|
|
57
|
-
assert check_metric(
|
58
|
-
|
66
|
+
assert check_metric(
|
67
|
+
59,
|
68
|
+
widget._sampleDetectorDistanceMetricEntry.getValue().to(_ureg.meter).magnitude,
|
69
|
+
)
|
70
|
+
assert widget._sampleDetectorDistanceMetricEntry._qcbUnit.currentText() == "m"
|
59
71
|
|
60
72
|
assert "Half" == widget._fieldOfViewCB.currentText()
|
61
73
|
assert widget._xFlippedCB.isChecked()
|
tomwer/model/dataset.py
ADDED
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
"""
|
2
|
+
Contains task to clear reduced dark and flat frames
|
3
|
+
"""
|
4
|
+
|
5
|
+
from __future__ import annotations
|
6
|
+
|
7
|
+
from tomoscan.scanbase import TomoScanBase as TomoscanScanBase
|
8
|
+
|
9
|
+
from processview.core.manager import DatasetState, ProcessManager
|
10
|
+
from processview.core.superviseprocess import SuperviseProcess
|
11
|
+
|
12
|
+
from tomwer.tasks.task import Task
|
13
|
+
from tomwer.core.scan.scanbase import TomwerScanBase
|
14
|
+
from tomwer.core.scan.scanfactory import ScanFactory
|
15
|
+
from tomwer.core.utils.scanutils import data_identifier_to_scan
|
16
|
+
from tomwer.core.reconstruction.darkflat import params as dkrf_reconsparams
|
17
|
+
from tomwer.utils import docstring
|
18
|
+
|
19
|
+
|
20
|
+
class ClearReducedDarkAndFlat(
|
21
|
+
Task,
|
22
|
+
SuperviseProcess,
|
23
|
+
input_names=("data",),
|
24
|
+
output_names=("data",),
|
25
|
+
):
|
26
|
+
"""
|
27
|
+
Task to clear reduced darks and flats. Both on disk and on the object cache.
|
28
|
+
th goal of this task is to make sure the scan is cleared of any reduced frames to reprocess it later.
|
29
|
+
"""
|
30
|
+
|
31
|
+
def run(self):
|
32
|
+
scan = self.inputs.data
|
33
|
+
if not isinstance(scan, TomoscanScanBase):
|
34
|
+
raise TypeError(
|
35
|
+
f"scan should be an instance of {TomoscanScanBase}. Got {type(scan)}"
|
36
|
+
)
|
37
|
+
scan.set_reduced_flats(None)
|
38
|
+
scan.reduced_flats_infos = None
|
39
|
+
scan.set_reduced_darks(None)
|
40
|
+
scan.reduced_darks_infos = None
|
41
|
+
|
42
|
+
self.outputs.data = scan
|
@@ -32,7 +32,7 @@ def _create_objects_for_stitching(stitching_type: StitchingType, output_dir) ->
|
|
32
32
|
]
|
33
33
|
)
|
34
34
|
|
35
|
-
stitching_type = StitchingType
|
35
|
+
stitching_type = StitchingType(stitching_type)
|
36
36
|
if stitching_type is StitchingType.Y_PREPROC:
|
37
37
|
nxtomos, positions, _ = test_y_preprocessing_stitching.build_nxtomos(
|
38
38
|
output_dir=output_dir, flip_lr=False, flip_ud=False
|
@@ -3,6 +3,7 @@ import pickle
|
|
3
3
|
|
4
4
|
import numpy
|
5
5
|
import pytest
|
6
|
+
import pint
|
6
7
|
from nxtomomill.nexus.nxtomo import NXtomo
|
7
8
|
from orangecanvas.scheme.readwrite import literal_dumps
|
8
9
|
from silx.gui.utils.testutils import SignalListener
|
@@ -15,15 +16,21 @@ from tomwer.tests.utils import skip_gui_test
|
|
15
16
|
from tomwer.gui.utils.qt_utils import QSignalSpy
|
16
17
|
from tomwer.tests.conftest import qtapp # noqa F401
|
17
18
|
|
19
|
+
_ureg = pint.get_application_registry()
|
20
|
+
|
18
21
|
|
19
22
|
def getDefaultConfig() -> dict:
|
20
23
|
"""return the configuration of the NXtomo editor. First value is the value of the field, second is: is the associated lock button locked or not"""
|
21
24
|
return {
|
22
25
|
NXtomoEditorKeys.ENERGY: (5.9, False),
|
26
|
+
NXtomoEditorKeys.SAMPLE_SOURCE_DISTANCE: (-55.2, False),
|
27
|
+
NXtomoEditorKeys.PROPAGATION_DISTANCE: (10.1, True),
|
23
28
|
NXtomoEditorKeys.SAMPLE_DETECTOR_DISTANCE: (2.4, True),
|
24
29
|
NXtomoEditorKeys.FIELD_OF_VIEW: ("Full", False),
|
25
|
-
NXtomoEditorKeys.
|
26
|
-
NXtomoEditorKeys.
|
30
|
+
NXtomoEditorKeys.DETECTOR_X_PIXEL_SIZE: (0.023, True),
|
31
|
+
NXtomoEditorKeys.DETECTOR_Y_PIXEL_SIZE: (0.025, True),
|
32
|
+
NXtomoEditorKeys.SAMPLE_X_PIXEL_SIZE: (0.24, True),
|
33
|
+
NXtomoEditorKeys.SAMPLE_Y_PIXEL_SIZE: (0.26, True),
|
27
34
|
NXtomoEditorKeys.X_FLIPPED: (True, True),
|
28
35
|
NXtomoEditorKeys.Y_FLIPPED: (False, False),
|
29
36
|
NXtomoEditorKeys.X_TRANSLATION: (0.0,),
|
@@ -49,41 +56,41 @@ def test_NXtomoEditorOW(
|
|
49
56
|
signal_listener = SignalListener()
|
50
57
|
window.sigScanReady.connect(signal_listener)
|
51
58
|
# set up the widget to define and lock distance, energy and x pixel size
|
52
|
-
distance_widget = window.widget.mainWidget.
|
53
|
-
distance_widget.setValue(0.6)
|
54
|
-
distance_widget.setUnit(
|
55
|
-
distance_locker = window.widget.mainWidget.
|
59
|
+
distance_widget = window.widget.mainWidget._sampleDetectorDistanceMetricEntry
|
60
|
+
distance_widget.setValue(value_m=0.6)
|
61
|
+
distance_widget.setUnit(_ureg.millimeter)
|
62
|
+
distance_locker = window.widget.mainWidget._sampleDetectorDistanceLB
|
56
63
|
distance_locker.setLock(True)
|
57
64
|
energy_widget = window.widget.mainWidget._energyEntry
|
58
65
|
energy_widget.setValue(88.058)
|
59
66
|
energy_locker = window.widget.mainWidget._energyLockerLB
|
60
67
|
energy_locker.setLock(True)
|
61
|
-
x_pixel_widget = window.widget.mainWidget.
|
62
|
-
x_pixel_widget.setValue(45)
|
63
|
-
x_pixel_widget.setUnit(
|
64
|
-
x_pixel_locker = window.widget.mainWidget.
|
68
|
+
x_pixel_widget = window.widget.mainWidget._xDetectorPixelSizeMetricEntry
|
69
|
+
x_pixel_widget.setValue(value_m=45)
|
70
|
+
x_pixel_widget.setUnit(_ureg.nanometer)
|
71
|
+
x_pixel_locker = window.widget.mainWidget._xDetectorPixelSizeLB
|
65
72
|
x_pixel_locker.setLock(True)
|
66
73
|
|
67
74
|
# 1.0 create nx tomos with raw data
|
68
75
|
nx_tomo = NXtomo()
|
69
76
|
nx_tomo.instrument.detector.x_pixel_size = (
|
70
|
-
0.023 # should be overwrite by the configuration / lock buttons
|
77
|
+
0.023 * _ureg.meter # should be overwrite by the configuration / lock buttons
|
71
78
|
)
|
72
79
|
nx_tomo.instrument.detector.y_pixel_size = (
|
73
|
-
0.025 # should be overwrite by the configuration / lock buttons
|
80
|
+
0.025 * _ureg.meter # should be overwrite by the configuration / lock buttons
|
74
81
|
)
|
75
82
|
nx_tomo.instrument.detector.field_of_view = "full"
|
76
83
|
nx_tomo.instrument.detector.distance = (
|
77
|
-
2.4 # should be overwrite by the configuration / lock buttons
|
84
|
+
2.4 * _ureg.meter # should be overwrite by the configuration / lock buttons
|
78
85
|
)
|
79
86
|
nx_tomo.instrument.detector.x_flipped = (
|
80
87
|
False # should be overwrite by the configuration / lock buttons
|
81
88
|
)
|
82
89
|
nx_tomo.instrument.detector.y_flipped = True
|
83
|
-
nx_tomo.energy = 5.9
|
90
|
+
nx_tomo.energy = 5.9 * _ureg.keV
|
84
91
|
nx_tomo.instrument.detector.image_key_control = [ImageKey.PROJECTION.value] * 12
|
85
92
|
nx_tomo.instrument.detector.data = numpy.empty(shape=(12, 10, 10))
|
86
|
-
nx_tomo.sample.rotation_angle = numpy.linspace(0, 20, num=12)
|
93
|
+
nx_tomo.sample.rotation_angle = numpy.linspace(0, 20, num=12) * _ureg.degree
|
87
94
|
|
88
95
|
file_path = os.path.join(tmp_path, "nxtomo.nx")
|
89
96
|
entry = "entry0000"
|
@@ -109,18 +116,20 @@ def test_NXtomoEditorOW(
|
|
109
116
|
detector_data_as="as_numpy_array",
|
110
117
|
)
|
111
118
|
numpy.testing.assert_almost_equal(
|
112
|
-
overwrite_nx_tomo.instrument.detector.x_pixel_size.
|
119
|
+
overwrite_nx_tomo.instrument.detector.x_pixel_size.to_base_units().magnitude,
|
120
|
+
(45e-9 * _ureg.meter).to_base_units().magnitude,
|
113
121
|
)
|
114
122
|
assert (
|
115
|
-
overwrite_nx_tomo.instrument.detector.y_pixel_size
|
116
|
-
== nx_tomo.instrument.detector.y_pixel_size
|
123
|
+
overwrite_nx_tomo.instrument.detector.y_pixel_size
|
124
|
+
== nx_tomo.instrument.detector.y_pixel_size
|
117
125
|
)
|
118
126
|
assert (
|
119
127
|
overwrite_nx_tomo.instrument.detector.field_of_view
|
120
128
|
== nx_tomo.instrument.detector.field_of_view
|
121
129
|
)
|
122
130
|
numpy.testing.assert_almost_equal(
|
123
|
-
overwrite_nx_tomo.instrument.detector.distance.
|
131
|
+
overwrite_nx_tomo.instrument.detector.distance.to_base_units().magnitude,
|
132
|
+
(6.0e-4 * _ureg.meter).to_base_units().magnitude,
|
124
133
|
)
|
125
134
|
assert (
|
126
135
|
overwrite_nx_tomo.instrument.detector.x_flipped
|
@@ -131,7 +140,10 @@ def test_NXtomoEditorOW(
|
|
131
140
|
overwrite_nx_tomo.instrument.detector.y_flipped
|
132
141
|
== True # is not locked and is initially set to False (should load it and ignore overwriting)
|
133
142
|
)
|
134
|
-
numpy.testing.assert_almost_equal(
|
143
|
+
numpy.testing.assert_almost_equal(
|
144
|
+
overwrite_nx_tomo.energy.to_base_units().magnitude,
|
145
|
+
(88.058 * _ureg.keV).to_base_units().magnitude,
|
146
|
+
)
|
135
147
|
numpy.testing.assert_array_almost_equal(
|
136
148
|
overwrite_nx_tomo.instrument.detector.data,
|
137
149
|
nx_tomo.instrument.detector.data,
|
@@ -101,7 +101,7 @@ class TestNabuWidget(TestCaseQt):
|
|
101
101
|
self.wait_processing()
|
102
102
|
self.assertEqual(self.widget.getMode(), _NabuMode.HALF_ACQ)
|
103
103
|
self.patch_fov(value=FOV.FULL.value)
|
104
|
-
self.scan.
|
104
|
+
self.scan.clear_cache()
|
105
105
|
self.widget.process(self.scan)
|
106
106
|
self.wait_processing()
|
107
107
|
self.assertEqual(self.widget.getMode(), _NabuMode.FULL_FIELD)
|
tomwer/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: tomwer
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.5.0rc0
|
4
4
|
Summary: "tomography workflow tools"
|
5
5
|
Home-page: https://gitlab.esrf.fr/tomotools/tomwer
|
6
6
|
Author: Henri Payno, Pierre Paleo, Pierre-Olivier Autran, Jérôme Lesaint, Alessandro Mirone
|
@@ -18,22 +18,22 @@ Classifier: Operating System :: POSIX
|
|
18
18
|
Classifier: Natural Language :: English
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
20
20
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
21
|
-
Requires-Python: >=3.
|
21
|
+
Requires-Python: >=3.9
|
22
22
|
Description-Content-Type: text/x-rst
|
23
23
|
License-File: LICENSE
|
24
24
|
Requires-Dist: numpy
|
25
25
|
Requires-Dist: setuptools
|
26
26
|
Requires-Dist: psutil
|
27
|
-
Requires-Dist: silx[full]
|
28
|
-
Requires-Dist: tomoscan>=2.
|
29
|
-
Requires-Dist: nxtomo
|
30
|
-
Requires-Dist: nxtomomill>=1.
|
27
|
+
Requires-Dist: silx[full]>=2.1.1
|
28
|
+
Requires-Dist: tomoscan>=2.2.0a6
|
29
|
+
Requires-Dist: nxtomo>=2.0.0dev2
|
30
|
+
Requires-Dist: nxtomomill>=1.2.0dev1
|
31
31
|
Requires-Dist: processview>=1.5.0
|
32
32
|
Requires-Dist: ewoks>=0.1.1
|
33
33
|
Requires-Dist: ewokscore<1.1.0
|
34
34
|
Requires-Dist: sluurp>=0.4.1
|
35
35
|
Requires-Dist: packaging
|
36
|
-
Requires-Dist:
|
36
|
+
Requires-Dist: pint
|
37
37
|
Requires-Dist: tqdm
|
38
38
|
Provides-Extra: full-base
|
39
39
|
Requires-Dist: orange-canvas-core; extra == "full-base"
|
@@ -227,7 +227,7 @@ Requires-Dist: ewoksnotify[full]; extra == "test"
|
|
227
227
|
Requires-Dist: pyicat_plus; extra == "test"
|
228
228
|
Requires-Dist: nabu>=2023.3.1dev; extra == "test"
|
229
229
|
Requires-Dist: pytest-asyncio; extra == "test"
|
230
|
-
Requires-Dist: tomoscan[test]>=2.
|
230
|
+
Requires-Dist: tomoscan[test]>=2.2.0a6; extra == "test"
|
231
231
|
Provides-Extra: setup-requires
|
232
232
|
Requires-Dist: setuptools; extra == "setup-requires"
|
233
233
|
Requires-Dist: numpy>=1.12; extra == "setup-requires"
|