tomwer 1.4.19__py3-none-any.whl → 1.5.0rc3__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/axis.py +1 -1
- tomwer/app/reducedarkflat.py +2 -2
- 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/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/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/darkrefs.py +2 -2
- tomwer/core/process/reconstruction/darkref/darkrefscopy.py +1 -1
- tomwer/core/process/reconstruction/darkref/params.py +2 -3
- tomwer/core/process/reconstruction/nabu/castvolume.py +4 -1
- tomwer/core/process/reconstruction/nabu/helical.py +3 -1
- tomwer/core/process/reconstruction/nabu/nabucommon.py +2 -2
- 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/target.py +1 -1
- tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +2 -0
- tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +9 -0
- tomwer/core/process/reconstruction/nabu/utils.py +18 -14
- tomwer/core/process/reconstruction/normalization/normalization.py +1 -1
- tomwer/core/process/reconstruction/normalization/params.py +4 -4
- tomwer/core/process/reconstruction/output.py +2 -2
- tomwer/core/process/reconstruction/saaxis/params.py +3 -3
- tomwer/core/process/reconstruction/saaxis/saaxis.py +1 -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_axis.py +1 -1
- tomwer/core/process/stitching/metadataholder.py +5 -5
- tomwer/core/process/stitching/nabustitcher.py +1 -4
- tomwer/core/process/tests/test_normalization.py +2 -1
- tomwer/core/scan/edfscan.py +3 -3
- tomwer/core/scan/nxtomoscan.py +3 -3
- tomwer/core/scan/scanbase.py +3 -3
- tomwer/core/scan/scantype.py +1 -1
- tomwer/core/settings.py +1 -1
- tomwer/core/tomwer_object.py +1 -1
- tomwer/core/utils/nxtomoutils.py +2 -2
- tomwer/core/utils/spec.py +6 -3
- tomwer/gui/cluster/slurm.py +3 -3
- tomwer/gui/configuration/level.py +1 -1
- tomwer/gui/control/actions.py +1 -1
- tomwer/gui/control/datadiscovery.py +1 -1
- tomwer/gui/control/datalist.py +1 -1
- tomwer/gui/control/reducedarkflatselector.py +4 -4
- 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/imagekeyeditor.py +7 -9
- tomwer/gui/edit/nxtomoeditor.py +420 -112
- tomwer/gui/edit/tests/test_nx_editor.py +155 -83
- tomwer/gui/reconstruction/axis/CalculationWidget.py +1 -1
- tomwer/gui/reconstruction/axis/EstimatedCORWidget.py +12 -8
- tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +2 -2
- tomwer/gui/reconstruction/axis/InputWidget.py +3 -3
- tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -2
- tomwer/gui/reconstruction/nabu/castvolume.py +16 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -6
- tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +1 -1
- tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +5 -5
- tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +2 -4
- tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +78 -52
- tomwer/gui/reconstruction/nabu/nabuflow.py +3 -13
- tomwer/gui/reconstruction/nabu/slices.py +11 -11
- tomwer/gui/reconstruction/nabu/test/test_cast_volume.py +19 -0
- tomwer/gui/reconstruction/nabu/volume.py +1 -1
- tomwer/gui/reconstruction/normalization/intensity.py +8 -12
- tomwer/gui/reconstruction/saaxis/corrangeselector.py +2 -2
- tomwer/gui/reconstruction/saaxis/dimensionwidget.py +71 -67
- tomwer/gui/reconstruction/sacommon.py +1 -1
- tomwer/gui/reconstruction/scores/scoreplot.py +18 -10
- 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/positionoveraxis.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 +2 -2
- tomwer/gui/utils/loadingmode.py +1 -1
- tomwer/gui/utils/unitsystem.py +44 -33
- tomwer/gui/utils/vignettes.py +1 -1
- tomwer/gui/visualization/dataviewer.py +7 -7
- tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
- tomwer/gui/visualization/diffviewer/shiftwidget.py +4 -6
- tomwer/gui/visualization/reconstructionparameters.py +35 -23
- tomwer/gui/visualization/scanoverview.py +28 -11
- tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +25 -13
- tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -2
- tomwer/model/dataset.py +0 -0
- tomwer/synctools/utils/scanstages.py +3 -3
- 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 +4 -4
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/METADATA +8 -8
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/RECORD +124 -122
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/WHEEL +1 -1
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/entry_points.txt +0 -0
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/licenses/LICENSE +0 -0
- {tomwer-1.4.19.dist-info → tomwer-1.5.0rc3.dist-info}/top_level.txt +0 -0
@@ -4,12 +4,14 @@ contains gui relative to semi-automatic axis calculation
|
|
4
4
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
|
+
import pint
|
7
8
|
from typing import Iterable
|
8
9
|
|
9
10
|
from silx.gui import qt
|
10
|
-
from pyunitsystem.metricsystem import MetricSystem
|
11
11
|
from tomwer.gui.utils.qt_utils import block_signals
|
12
12
|
|
13
|
+
_ureg = pint.get_application_registry()
|
14
|
+
|
13
15
|
|
14
16
|
class DimensionWidget(qt.QGroupBox):
|
15
17
|
"""
|
@@ -37,10 +39,10 @@ class DimensionWidget(qt.QGroupBox):
|
|
37
39
|
assert dims_colors is None or (
|
38
40
|
isinstance(dims_colors, Iterable) and len(dims_colors) == 3
|
39
41
|
)
|
40
|
-
self.
|
41
|
-
self.
|
42
|
-
self.
|
43
|
-
self.
|
42
|
+
self._displayUnit = _ureg.millimeter
|
43
|
+
self._dim0Value: pint.Quantity = 1.0 * self._displayUnit
|
44
|
+
self._dim1Value: pint.Quantity = 1.0 * self._displayUnit
|
45
|
+
self._dim2Value: pint.Quantity = 1.0 * self._displayUnit
|
44
46
|
# defined unit to display values. Always stored in m (International
|
45
47
|
# System)
|
46
48
|
## set GUI
|
@@ -53,7 +55,7 @@ class DimensionWidget(qt.QGroupBox):
|
|
53
55
|
self._dim0ValueQLE.setRange(0, 999999999999)
|
54
56
|
self._dim0ValueQLE.setDecimals(10)
|
55
57
|
self._dim0ValueQLE.setSingleStep(0.0001)
|
56
|
-
self._dim0ValueQLE.setValue(self.
|
58
|
+
self._dim0ValueQLE.setValue(self._dim0Value.magnitude)
|
57
59
|
if dims_colors is not None:
|
58
60
|
stylesheet = f"background-color: {dims_colors[0]}"
|
59
61
|
self._dim0ValueQLE.setStyleSheet(stylesheet)
|
@@ -65,7 +67,7 @@ class DimensionWidget(qt.QGroupBox):
|
|
65
67
|
self._dim1ValueQLE.setRange(0, 999999999999)
|
66
68
|
self._dim1ValueQLE.setDecimals(10)
|
67
69
|
self._dim1ValueQLE.setSingleStep(0.0001)
|
68
|
-
self._dim1ValueQLE.setValue(self.
|
70
|
+
self._dim1ValueQLE.setValue(self._dim1Value.magnitude)
|
69
71
|
if dims_colors is not None:
|
70
72
|
stylesheet = f"background-color: {dims_colors[1]}"
|
71
73
|
self._dim1ValueQLE.setStyleSheet(stylesheet)
|
@@ -77,7 +79,7 @@ class DimensionWidget(qt.QGroupBox):
|
|
77
79
|
self._dim2ValueQLE.setRange(0, 999999999999)
|
78
80
|
self._dim2ValueQLE.setDecimals(10)
|
79
81
|
self._dim2ValueQLE.setSingleStep(0.0001)
|
80
|
-
self._dim2ValueQLE.setValue(self.
|
82
|
+
self._dim2ValueQLE.setValue(self._dim2Value.magnitude)
|
81
83
|
if dims_colors is not None:
|
82
84
|
stylesheet = f"background-color: {dims_colors[2]}"
|
83
85
|
self._dim2ValueQLE.setStyleSheet(stylesheet)
|
@@ -91,42 +93,32 @@ class DimensionWidget(qt.QGroupBox):
|
|
91
93
|
self._dim1ValueQLE.editingFinished.connect(self._userSetDim1)
|
92
94
|
self._dim2ValueQLE.editingFinished.connect(self._userSetDim2)
|
93
95
|
|
94
|
-
def
|
95
|
-
return self._dim0Value / self._displayUnit.value
|
96
|
-
|
97
|
-
def _getDim1DisplayValue(self) -> float:
|
98
|
-
return self._dim1Value / self._displayUnit.value
|
99
|
-
|
100
|
-
def _getDim2DisplayValue(self) -> float:
|
101
|
-
return self._dim2Value / self._displayUnit.value
|
102
|
-
|
103
|
-
def setUnit(self, unit):
|
96
|
+
def setUnit(self, unit: pint.Unit):
|
104
97
|
"""
|
105
98
|
define with which unit we should display the size
|
106
99
|
:param unit: metric to be used for display. Internally this is always stored using the international metric system
|
107
100
|
"""
|
108
|
-
|
101
|
+
if not isinstance(unit, pint.Unit):
|
102
|
+
raise TypeError(
|
103
|
+
f"unit is expected be an instance of {pint.Unit}. Got {type(unit)}"
|
104
|
+
)
|
109
105
|
for widget in (self._dim0ValueQLE, self._dim1ValueQLE, self._dim2ValueQLE):
|
110
|
-
widget.setSuffix(
|
106
|
+
widget.setSuffix(f"{self._displayUnit:~}")
|
107
|
+
# convert current values
|
108
|
+
self._dim0Value = self._dim0Value.magnitude * self._displayUnit
|
109
|
+
self._dim1Value = self._dim1Value.magnitude * self._displayUnit
|
110
|
+
self._dim2Value = self._dim2Value.magnitude * self._displayUnit
|
111
111
|
# update displayed values
|
112
112
|
with block_signals(self):
|
113
|
-
self._dim0ValueQLE.setValue(self.
|
114
|
-
self._dim1ValueQLE.setValue(self.
|
115
|
-
self._dim2ValueQLE.setValue(self.
|
116
|
-
|
117
|
-
def unit(self) -> MetricSystem:
|
118
|
-
"""
|
113
|
+
self._dim0ValueQLE.setValue(self._dim0Value.magnitude)
|
114
|
+
self._dim1ValueQLE.setValue(self._dim1Value.magnitude)
|
115
|
+
self._dim2ValueQLE.setValue(self._dim2Value.magnitude)
|
119
116
|
|
120
|
-
|
121
|
-
"""
|
122
|
-
return self._displayUnit
|
123
|
-
|
124
|
-
def setValues(
|
117
|
+
def setQuantities(
|
125
118
|
self,
|
126
|
-
dim0:
|
127
|
-
dim1:
|
128
|
-
dim2:
|
129
|
-
unit: str | MetricSystem = "mm",
|
119
|
+
dim0: pint.Quantity,
|
120
|
+
dim1: pint.Quantity,
|
121
|
+
dim2: pint.Quantity,
|
130
122
|
) -> None:
|
131
123
|
"""
|
132
124
|
|
@@ -136,66 +128,78 @@ class DimensionWidget(qt.QGroupBox):
|
|
136
128
|
:param unit: unit used for the provided values
|
137
129
|
"""
|
138
130
|
with block_signals(self):
|
139
|
-
self.
|
140
|
-
self.setDim1value(value=dim1
|
141
|
-
self.
|
131
|
+
self.setDim0Quantity(value=dim0)
|
132
|
+
self.setDim1value(value=dim1)
|
133
|
+
self.setDim2Quantity(value=dim2)
|
142
134
|
self.valuesChanged.emit()
|
143
135
|
|
144
|
-
def
|
136
|
+
def getQuantities(
|
137
|
+
self, cast_unit_to: None | pint.Unit = None
|
138
|
+
) -> tuple[pint.Quantity]:
|
145
139
|
"""
|
140
|
+
:param cast_unit_to: if given will cast the quantities to the requested unit
|
146
141
|
|
147
|
-
:return: (dim0 value, dim1 value, dim2 value
|
142
|
+
:return: (dim0 value, dim1 value, dim2 value)
|
148
143
|
"""
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
144
|
+
if cast_unit_to is None:
|
145
|
+
return (
|
146
|
+
self.getDim0Quantity(),
|
147
|
+
self.getDim1Quantity(),
|
148
|
+
self.getDim2Quantity(),
|
149
|
+
)
|
150
|
+
else:
|
151
|
+
return (
|
152
|
+
self.getDim0Quantity().to(cast_unit_to),
|
153
|
+
self.getDim1Quantity().to(cast_unit_to),
|
154
|
+
self.getDim2Quantity().to(cast_unit_to),
|
155
|
+
)
|
156
|
+
|
157
|
+
def getDim0Quantity(self) -> tuple:
|
157
158
|
"""Return Dim 0 value and unit. Unit is always meter"""
|
158
|
-
return self._dim0Value
|
159
|
+
return self._dim0Value
|
159
160
|
|
160
|
-
def
|
161
|
+
def setDim0Quantity(self, value: pint.Quantity):
|
161
162
|
"""
|
162
163
|
|
163
164
|
:param value: value to set to dim 0.
|
164
165
|
:return:
|
165
166
|
"""
|
166
|
-
|
167
|
+
assert isinstance(value, pint.Quantity)
|
168
|
+
self._dim0Value = value
|
167
169
|
with block_signals(self):
|
168
|
-
self._dim0ValueQLE.setValue(self._dim0Value)
|
170
|
+
self._dim0ValueQLE.setValue(self._dim0Value.magnitude)
|
169
171
|
self.valuesChanged.emit()
|
170
172
|
|
171
|
-
def
|
172
|
-
"""Return Dim
|
173
|
-
return self._dim1Value
|
173
|
+
def getDim1Quantity(self) -> pint.Quantity:
|
174
|
+
"""Return Dim 1 Quantity"""
|
175
|
+
return self._dim1Value
|
174
176
|
|
175
|
-
def setDim1value(self, value:
|
177
|
+
def setDim1value(self, value: pint.Quantity):
|
176
178
|
"""
|
177
179
|
|
178
180
|
:param value: value to set to dim 1.
|
179
181
|
:return:
|
180
182
|
"""
|
181
|
-
|
183
|
+
assert isinstance(value, pint.Quantity)
|
184
|
+
self._dim1Value = value
|
182
185
|
with block_signals(self):
|
183
|
-
self._dim1ValueQLE.setValue(self._dim1Value)
|
186
|
+
self._dim1ValueQLE.setValue(self._dim1Value.magnitude)
|
184
187
|
self.valuesChanged.emit()
|
185
188
|
|
186
|
-
def
|
187
|
-
"""Return Dim
|
188
|
-
return self._dim2Value
|
189
|
+
def getDim2Quantity(self) -> pint.Quantity:
|
190
|
+
"""Return Dim 2 value and unit. Unit is always meter"""
|
191
|
+
return self._dim2Value
|
189
192
|
|
190
|
-
def
|
193
|
+
def setDim2Quantity(self, value: pint.Quantity):
|
191
194
|
"""
|
192
195
|
|
193
196
|
:param value: value to set to dim 2.
|
194
197
|
:return:
|
195
198
|
"""
|
196
|
-
|
199
|
+
assert isinstance(value, pint.Quantity)
|
200
|
+
self._dim2Value = value
|
197
201
|
with block_signals(self):
|
198
|
-
self._dim2ValueQLE.setValue(self._dim2Value)
|
202
|
+
self._dim2ValueQLE.setValue(self._dim2Value.magnitude)
|
199
203
|
self.valuesChanged.emit()
|
200
204
|
|
201
205
|
def _valuesChanged(self, *args, **kwargs):
|
@@ -204,17 +208,17 @@ class DimensionWidget(qt.QGroupBox):
|
|
204
208
|
def _userSetDim0(self):
|
205
209
|
"""callback when the user modify the dim 0 QDSP"""
|
206
210
|
with block_signals(self):
|
207
|
-
self._dim0Value = self._dim0ValueQLE.value() * self.
|
211
|
+
self._dim0Value = self._dim0ValueQLE.value() * self._displayUnit
|
208
212
|
self.valuesChanged.emit()
|
209
213
|
|
210
214
|
def _userSetDim1(self):
|
211
215
|
"""callback when the user modify the dim 1 QDSP"""
|
212
216
|
with block_signals(self):
|
213
|
-
self._dim1Value = self._dim1ValueQLE.value() * self.
|
217
|
+
self._dim1Value = self._dim1ValueQLE.value() * self._displayUnit
|
214
218
|
self.valuesChanged.emit()
|
215
219
|
|
216
220
|
def _userSetDim2(self):
|
217
221
|
"""callback when the user modify the dim 2 QDSP"""
|
218
222
|
with block_signals(self):
|
219
|
-
self._dim2Value = self._dim2ValueQLE.value() * self.
|
223
|
+
self._dim2Value = self._dim2ValueQLE.value() * self._displayUnit
|
220
224
|
self.valuesChanged.emit()
|
@@ -107,7 +107,7 @@ class NabuWidgetWithToolbar(qt.QMainWindow):
|
|
107
107
|
self._nabuSettings.setConfiguration(config)
|
108
108
|
|
109
109
|
def setConfigurationLevel(self, level):
|
110
|
-
level = ConfigurationLevel
|
110
|
+
level = ConfigurationLevel(level)
|
111
111
|
if level == ConfigurationLevel.REQUIRED:
|
112
112
|
self._minimalisticAction.setChecked(True)
|
113
113
|
elif level == ConfigurationLevel.ADVANCED:
|
@@ -5,6 +5,7 @@ contains gui to select a slice in a volume
|
|
5
5
|
from __future__ import annotations
|
6
6
|
|
7
7
|
import logging
|
8
|
+
import pint
|
8
9
|
import os
|
9
10
|
import weakref
|
10
11
|
from contextlib import AbstractContextManager
|
@@ -247,10 +248,10 @@ class VariableSelection(qt.QWidget):
|
|
247
248
|
self._img_width = width
|
248
249
|
|
249
250
|
def getScoreMethod(self):
|
250
|
-
return ScoreMethod
|
251
|
+
return ScoreMethod(self._scoreMethodCB.currentText())
|
251
252
|
|
252
253
|
def setScoreMethod(self, method):
|
253
|
-
method_value = ScoreMethod
|
254
|
+
method_value = ScoreMethod(method).value
|
254
255
|
index = self._scoreMethodCB.findText(method_value)
|
255
256
|
self._scoreMethodCB.setCurrentIndex(index)
|
256
257
|
|
@@ -670,7 +671,7 @@ class ScorePlot(qt.QWidget):
|
|
670
671
|
:param scores: cor value (float) as key and
|
671
672
|
tuple(url: DataUrl, score: float) as value
|
672
673
|
"""
|
673
|
-
score_method = ScoreMethod
|
674
|
+
score_method = ScoreMethod(score_method)
|
674
675
|
if not update_only_scores:
|
675
676
|
self.clear()
|
676
677
|
self._scores = scores
|
@@ -739,7 +740,9 @@ class ScorePlot(qt.QWidget):
|
|
739
740
|
self._plot.getPlotWidget().clear()
|
740
741
|
self._varValueWidget.setImgWidth(None)
|
741
742
|
|
742
|
-
def setVoxelSize(
|
743
|
+
def setVoxelSize(
|
744
|
+
self, dim0: pint.Quantity, dim1: pint.Quantity, dim2: pint.Quantity
|
745
|
+
):
|
743
746
|
"""
|
744
747
|
|
745
748
|
:param dim0:
|
@@ -747,9 +750,11 @@ class ScorePlot(qt.QWidget):
|
|
747
750
|
:param dim2:
|
748
751
|
:param unit:
|
749
752
|
"""
|
750
|
-
self._voxelSizeW.
|
753
|
+
self._voxelSizeW.setQuantities(dim0=dim0, dim1=dim1, dim2=dim2)
|
751
754
|
|
752
|
-
def setVolumeSize(
|
755
|
+
def setVolumeSize(
|
756
|
+
self, dim0: pint.Quantity, dim1: pint.Quantity, dim2: pint.Quantity
|
757
|
+
):
|
753
758
|
"""
|
754
759
|
|
755
760
|
:param dim0:
|
@@ -757,14 +762,15 @@ class ScorePlot(qt.QWidget):
|
|
757
762
|
:param dim2:
|
758
763
|
:param unit:
|
759
764
|
"""
|
760
|
-
self._volumeSizeW.
|
765
|
+
self._volumeSizeW.setQuantities(dim0=dim0, dim1=dim1, dim2=dim2)
|
761
766
|
|
762
767
|
def getDim0N(self):
|
763
768
|
"""return the number of elements in dimension 0 according to voxel
|
764
769
|
size and volume size"""
|
765
770
|
return int(
|
766
771
|
numpy.ceil(
|
767
|
-
self._volumeSizeW.
|
772
|
+
self._volumeSizeW.getDim0Quantity().to_base_units().magnitude
|
773
|
+
/ self._voxelSizeW.getDim0Quantity().to_base_units().magnitude
|
768
774
|
)
|
769
775
|
)
|
770
776
|
|
@@ -773,7 +779,8 @@ class ScorePlot(qt.QWidget):
|
|
773
779
|
size and volume size"""
|
774
780
|
return int(
|
775
781
|
numpy.ceil(
|
776
|
-
self._volumeSizeW.
|
782
|
+
self._volumeSizeW.getDim1Quantity().to_base_units().magnitude
|
783
|
+
/ self._voxelSizeW.getDim1Quantity().to_base_units().magnitude
|
777
784
|
)
|
778
785
|
)
|
779
786
|
|
@@ -782,7 +789,8 @@ class ScorePlot(qt.QWidget):
|
|
782
789
|
size and volume size"""
|
783
790
|
return int(
|
784
791
|
numpy.ceil(
|
785
|
-
self._volumeSizeW.
|
792
|
+
self._volumeSizeW.getDim2Quantity().to_base_units().magnitude
|
793
|
+
/ self._voxelSizeW.getDim2Quantity().to_base_units().magnitude
|
786
794
|
)
|
787
795
|
)
|
788
796
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
3
3
|
|
4
4
|
|
5
5
|
import os
|
6
|
+
import pint
|
6
7
|
import shutil
|
7
8
|
import tempfile
|
8
9
|
|
@@ -12,7 +13,6 @@ import pytest
|
|
12
13
|
from silx.gui import qt
|
13
14
|
from silx.gui.utils.testutils import TestCaseQt
|
14
15
|
from silx.io.url import DataUrl
|
15
|
-
from pyunitsystem.metricsystem import MetricSystem
|
16
16
|
|
17
17
|
from tomwer.core.process.reconstruction.saaxis.params import (
|
18
18
|
ReconstructionMode,
|
@@ -26,6 +26,9 @@ from tomwer.gui.reconstruction.saaxis.saaxis import SAAxisWindow
|
|
26
26
|
from tomwer.tests.utils import skip_gui_test
|
27
27
|
|
28
28
|
|
29
|
+
_ureg = pint.get_application_registry()
|
30
|
+
|
31
|
+
|
29
32
|
@pytest.mark.skipif(skip_gui_test(), reason="skip gui test")
|
30
33
|
class TestDimensionWidget(TestCaseQt):
|
31
34
|
"""Test that the axis widget work correctly"""
|
@@ -39,51 +42,50 @@ class TestDimensionWidget(TestCaseQt):
|
|
39
42
|
|
40
43
|
def testDimension(self):
|
41
44
|
"""Insure setting dimensions values and unit are correct"""
|
42
|
-
self.assertTrue(self._window.unit() is MetricSystem.MILLIMETER)
|
43
45
|
# check initial values
|
44
46
|
self.assertEqual(
|
45
|
-
self._window.
|
46
|
-
(0.
|
47
|
+
self._window.getQuantities(),
|
48
|
+
(1.0 * _ureg.millimeter, 1.0 * _ureg.millimeter, 1.0 * _ureg.millimeter),
|
47
49
|
)
|
48
50
|
# set dim 0 to 20 mm
|
49
51
|
self._window._dim0ValueQLE.setValue(20)
|
50
52
|
self._window._dim0ValueQLE.editingFinished.emit()
|
51
53
|
self.qapp.processEvents()
|
52
54
|
self.assertEqual(
|
53
|
-
self._window.
|
54
|
-
(0.02, 0.001, 0.001
|
55
|
+
self._window.getQuantities(cast_unit_to=_ureg.meter),
|
56
|
+
(0.02 * _ureg.meter, 0.001 * _ureg.meter, 0.001 * _ureg.meter),
|
55
57
|
)
|
56
58
|
# set dim 1 to 0.6 millimeter
|
57
59
|
self._window._dim1ValueQLE.setValue(0.6)
|
58
60
|
self._window._dim1ValueQLE.editingFinished.emit()
|
59
61
|
self.qapp.processEvents()
|
60
62
|
self.assertEqual(
|
61
|
-
self._window.
|
62
|
-
(0.02, 0.0006, 0.001
|
63
|
+
self._window.getQuantities(cast_unit_to=_ureg.meter),
|
64
|
+
(0.02 * _ureg.meter, 0.0006 * _ureg.meter, 0.001 * _ureg.meter),
|
63
65
|
)
|
64
66
|
# change display to micrometer
|
65
|
-
self._window.setUnit(
|
67
|
+
self._window.setUnit(_ureg.millimeter)
|
66
68
|
self.assertEqual(
|
67
|
-
self._window.
|
68
|
-
(0.02, 0.0006, 0.001
|
69
|
+
self._window.getQuantities(cast_unit_to=_ureg.meter),
|
70
|
+
(0.02 * _ureg.meter, 0.0006 * _ureg.meter, 0.001 * _ureg.meter),
|
69
71
|
)
|
70
72
|
self.assertEqual(
|
71
|
-
self._window.
|
72
|
-
20 *
|
73
|
+
self._window._dim0Value,
|
74
|
+
20 * _ureg.millimeter,
|
73
75
|
)
|
74
76
|
self._window._dim2ValueQLE.setValue(500)
|
75
77
|
self._window._dim2ValueQLE.editingFinished.emit()
|
76
78
|
self.qapp.processEvents()
|
77
79
|
self.assertEqual(
|
78
|
-
self._window.
|
79
|
-
(0.02, 0.0006, 0.
|
80
|
+
self._window.getQuantities(cast_unit_to=_ureg.meter),
|
81
|
+
(0.02 * _ureg.meter, 0.0006 * _ureg.meter, 0.5 * _ureg.meter),
|
80
82
|
)
|
81
83
|
|
82
84
|
def testConstructorWithColors(self):
|
83
85
|
"""Insure passing colors works"""
|
84
86
|
DimensionWidget(title="title", dims_colors=("#ffff5a", "#62efff", "#ff5bff"))
|
85
87
|
|
86
|
-
def
|
88
|
+
def testConstructorWithDimNames(self):
|
87
89
|
"""Insure passing colors works"""
|
88
90
|
DimensionWidget(title="title", dims_name=("x", "y", "z"))
|
89
91
|
|
@@ -54,7 +54,7 @@ class SingleAxisStitchingWidget(qt.QWidget, _SingleAxisMixIn):
|
|
54
54
|
# filter stitching types that does belong to the axis (GUI is specific to a given axis. The other have no sense at this level)
|
55
55
|
stitching_types = filter(
|
56
56
|
lambda s_type: s_type.lower().startswith(self.axis_alias(axis).lower()),
|
57
|
-
StitchingType
|
57
|
+
[item.value for item in StitchingType],
|
58
58
|
)
|
59
59
|
for mode in stitching_types:
|
60
60
|
self._stitchingTypeCB.addItem(mode)
|
@@ -84,10 +84,10 @@ class SingleAxisStitchingWidget(qt.QWidget, _SingleAxisMixIn):
|
|
84
84
|
self.sigStitchingTypeChanged.emit(self.getStitchingType().value)
|
85
85
|
|
86
86
|
def getStitchingType(self):
|
87
|
-
return StitchingType
|
87
|
+
return StitchingType(self._stitchingTypeCB.currentText())
|
88
88
|
|
89
89
|
def setStitchingType(self, mode):
|
90
|
-
mode = StitchingType
|
90
|
+
mode = StitchingType(mode)
|
91
91
|
idx = self._stitchingTypeCB.findText(mode.value)
|
92
92
|
if idx >= 0:
|
93
93
|
self._stitchingTypeCB.setCurrentIndex(idx)
|
@@ -102,7 +102,7 @@ class SingleAxisStitchingWidget(qt.QWidget, _SingleAxisMixIn):
|
|
102
102
|
],
|
103
103
|
)
|
104
104
|
)
|
105
|
-
return tuple([StitchingType
|
105
|
+
return tuple([StitchingType(mode) for mode in pre_proc_modes])
|
106
106
|
|
107
107
|
def get_available_post_processing_stitching_mode(self):
|
108
108
|
post_proc_modes: tuple[str] = tuple(
|
@@ -114,7 +114,7 @@ class SingleAxisStitchingWidget(qt.QWidget, _SingleAxisMixIn):
|
|
114
114
|
],
|
115
115
|
)
|
116
116
|
)
|
117
|
-
return tuple([StitchingType
|
117
|
+
return tuple([StitchingType(mode) for mode in post_proc_modes])
|
118
118
|
|
119
119
|
def addTomoObj(self, tomo_obj: TomwerObject):
|
120
120
|
self._mainWidget.addTomoObj(tomo_obj)
|
@@ -132,10 +132,10 @@ class SingleAxisStitchingWidget(qt.QWidget, _SingleAxisMixIn):
|
|
132
132
|
for tomo_obj in tomo_objs:
|
133
133
|
if (
|
134
134
|
isinstance(tomo_obj, NXtomoScan)
|
135
|
-
and tomo_obj.
|
136
|
-
and tomo_obj.
|
135
|
+
and tomo_obj.sample_x_pixel_size is not None
|
136
|
+
and tomo_obj.sample_y_pixel_size is not None
|
137
137
|
):
|
138
|
-
return tomo_obj.
|
138
|
+
return tomo_obj.sample_x_pixel_size, tomo_obj.sample_y_pixel_size
|
139
139
|
elif (
|
140
140
|
isinstance(tomo_obj, TomwerVolumeBase)
|
141
141
|
and tomo_obj.voxel_size is not None
|
@@ -272,7 +272,7 @@ class StitchingOptionsWidget(qt.QWidget):
|
|
272
272
|
self._normalizationBySampleWidget.setConfiguration(normalization_by_sample)
|
273
273
|
|
274
274
|
def _stitchingTypeChanged(self, stitching_type: str):
|
275
|
-
stitching_type = StitchingType
|
275
|
+
stitching_type = StitchingType(stitching_type)
|
276
276
|
self._alignmentGroup.setAlignmentAxis1Enabled(
|
277
277
|
stitching_type is StitchingType.Z_POSTPROC
|
278
278
|
)
|
@@ -33,8 +33,8 @@ class _AlignmentGroupBox(qt.QGroupBox):
|
|
33
33
|
|
34
34
|
# alignment axis 1
|
35
35
|
self._alignmentAxis1CB = qt.QComboBox(self)
|
36
|
-
for alignment in AlignmentAxis1
|
37
|
-
self._alignmentAxis1CB.addItem(alignment)
|
36
|
+
for alignment in AlignmentAxis1:
|
37
|
+
self._alignmentAxis1CB.addItem(alignment.value)
|
38
38
|
self.layout().addRow("Axis 1 alignment", self._alignmentAxis1CB)
|
39
39
|
self._alignmentAxis1CB.setToolTip(
|
40
40
|
f"Alignment to do in case of volumes with different size over axis 1. Only possible for post-processing (reconstructed volume). See {self.ALIGNMENT_DOC} for details."
|
@@ -42,8 +42,8 @@ class _AlignmentGroupBox(qt.QGroupBox):
|
|
42
42
|
|
43
43
|
# alignment axis 2
|
44
44
|
self._alignmentAxis2CB = qt.QComboBox(self)
|
45
|
-
for alignment in AlignmentAxis2
|
46
|
-
self._alignmentAxis2CB.addItem(alignment)
|
45
|
+
for alignment in AlignmentAxis2:
|
46
|
+
self._alignmentAxis2CB.addItem(alignment.value)
|
47
47
|
self.layout().addRow("Axis 2 alignment", self._alignmentAxis2CB)
|
48
48
|
self._alignmentAxis2CB.setToolTip(
|
49
49
|
f"Alignment to do in case of frames with different size over axis 2. See {self.ALIGNMENT_DOC} for details."
|
@@ -61,19 +61,19 @@ class _AlignmentGroupBox(qt.QGroupBox):
|
|
61
61
|
self.setAlignmentAxis2(self.DEFAULT_ALIGNMENT_AXIS_2)
|
62
62
|
|
63
63
|
def getAlignmentAxis1(self) -> AlignmentAxis1:
|
64
|
-
return AlignmentAxis1
|
64
|
+
return AlignmentAxis1(self._alignmentAxis1CB.currentText())
|
65
65
|
|
66
66
|
def setAlignmentAxis1(self, alignment: AlignmentAxis1):
|
67
|
-
alignment = AlignmentAxis1
|
67
|
+
alignment = AlignmentAxis1(alignment)
|
68
68
|
self._alignmentAxis1CB.setCurrentIndex(
|
69
69
|
self._alignmentAxis1CB.findText(alignment.value)
|
70
70
|
)
|
71
71
|
|
72
72
|
def getAlignmentAxis2(self) -> AlignmentAxis2:
|
73
|
-
return AlignmentAxis2
|
73
|
+
return AlignmentAxis2(self._alignmentAxis2CB.currentText())
|
74
74
|
|
75
75
|
def setAlignmentAxis2(self, alignment: AlignmentAxis2):
|
76
|
-
alignment = AlignmentAxis2
|
76
|
+
alignment = AlignmentAxis2(alignment)
|
77
77
|
self._alignmentAxis2CB.setCurrentIndex(
|
78
78
|
self._alignmentAxis2CB.findText(alignment.value)
|
79
79
|
)
|
@@ -80,10 +80,10 @@ class StitcherAxisParams(qt.QWidget):
|
|
80
80
|
return self._axis
|
81
81
|
|
82
82
|
def getShiftSearchMethod(self) -> StitchShiftAlgorithm:
|
83
|
-
return StitchShiftAlgorithm
|
83
|
+
return StitchShiftAlgorithm(self._shiftSearchMethodCB.currentText())
|
84
84
|
|
85
85
|
def setShiftSearchMethod(self, method: StitchShiftAlgorithm | str) -> None:
|
86
|
-
method = StitchShiftAlgorithm
|
86
|
+
method = StitchShiftAlgorithm(method)
|
87
87
|
idx = self._shiftSearchMethodCB.findText(method.value)
|
88
88
|
self._shiftSearchMethodCB.setCurrentIndex(idx)
|
89
89
|
|
@@ -85,7 +85,7 @@ class StitchingOutput(qt.QWidget):
|
|
85
85
|
self._updateOutputForStitchingType(StitchingType.Z_PREPROC)
|
86
86
|
|
87
87
|
def _updateOutputForStitchingType(self, stitching_type):
|
88
|
-
self.__stitching_type = StitchingType
|
88
|
+
self.__stitching_type = StitchingType(stitching_type)
|
89
89
|
self._preProcOutput.setVisible(self.__stitching_type is StitchingType.Z_PREPROC)
|
90
90
|
self._postProcOutput.setVisible(
|
91
91
|
self.__stitching_type is StitchingType.Z_POSTPROC
|
@@ -51,8 +51,8 @@ class StitchingStrategies(qt.QWidget, _SingleAxisMixIn):
|
|
51
51
|
super().__init__(parent)
|
52
52
|
self.setLayout(qt.QFormLayout())
|
53
53
|
self._stitchingStrategyCG = QComboBox(parent=self)
|
54
|
-
for strategy in OverlapStitchingStrategy
|
55
|
-
self._stitchingStrategyCG.addItem(strategy)
|
54
|
+
for strategy in OverlapStitchingStrategy:
|
55
|
+
self._stitchingStrategyCG.addItem(strategy.value)
|
56
56
|
self._stitchingStrategyCG.setToolTip(
|
57
57
|
"stitcher behavior is also know as stitching strategy. It define the behavior to have on overlaping areas"
|
58
58
|
)
|
@@ -76,12 +76,10 @@ class StitchingStrategies(qt.QWidget, _SingleAxisMixIn):
|
|
76
76
|
self.sigChanged.emit()
|
77
77
|
|
78
78
|
def getStitchingStrategy(self) -> OverlapStitchingStrategy:
|
79
|
-
return OverlapStitchingStrategy.
|
80
|
-
self._stitchingStrategyCG.currentText()
|
81
|
-
)
|
79
|
+
return OverlapStitchingStrategy(self._stitchingStrategyCG.currentText())
|
82
80
|
|
83
81
|
def setStitchingStrategy(self, strategy: OverlapStitchingStrategy | str):
|
84
|
-
strategy = OverlapStitchingStrategy
|
82
|
+
strategy = OverlapStitchingStrategy(strategy)
|
85
83
|
idx = self._stitchingStrategyCG.findText(strategy.value)
|
86
84
|
if idx >= 0:
|
87
85
|
self._stitchingStrategyCG.setCurrentIndex(idx)
|