tomwer 1.4.19__py3-none-any.whl → 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. orangecontrib/tomwer/tutorials/simple_volume_local_reconstruction.ows +11 -8
  2. orangecontrib/tomwer/tutorials/simple_volume_to_slurm_reconstruction.ows +12 -9
  3. orangecontrib/tomwer/widgets/control/DataDiscoveryOW.py +1 -1
  4. orangecontrib/tomwer/widgets/control/NXTomomillMixIn.py +21 -10
  5. tomwer/app/axis.py +1 -1
  6. tomwer/app/reducedarkflat.py +2 -2
  7. tomwer/core/process/control/datalistener/rpcserver.py +2 -8
  8. tomwer/core/process/drac/binning.py +2 -2
  9. tomwer/core/process/drac/output.py +1 -1
  10. tomwer/core/process/edit/imagekeyeditor.py +4 -6
  11. tomwer/core/process/edit/nxtomoeditor.py +58 -20
  12. tomwer/core/process/output.py +6 -5
  13. tomwer/core/process/reconstruction/axis/anglemode.py +2 -2
  14. tomwer/core/process/reconstruction/axis/axis.py +1 -0
  15. tomwer/core/process/reconstruction/axis/mode.py +2 -2
  16. tomwer/core/process/reconstruction/axis/params.py +4 -4
  17. tomwer/core/process/reconstruction/axis/projectiontype.py +1 -1
  18. tomwer/core/process/reconstruction/axis/side.py +1 -1
  19. tomwer/core/process/reconstruction/darkref/darkrefs.py +2 -2
  20. tomwer/core/process/reconstruction/darkref/darkrefscopy.py +1 -1
  21. tomwer/core/process/reconstruction/darkref/params.py +2 -3
  22. tomwer/core/process/reconstruction/nabu/castvolume.py +4 -1
  23. tomwer/core/process/reconstruction/nabu/helical.py +3 -1
  24. tomwer/core/process/reconstruction/nabu/nabucommon.py +2 -2
  25. tomwer/core/process/reconstruction/nabu/nabuscores.py +1 -1
  26. tomwer/core/process/reconstruction/nabu/nabuslices.py +4 -4
  27. tomwer/core/process/reconstruction/nabu/plane.py +2 -2
  28. tomwer/core/process/reconstruction/nabu/target.py +1 -1
  29. tomwer/core/process/reconstruction/nabu/test/test_castvolume.py +2 -0
  30. tomwer/core/process/reconstruction/nabu/test/test_nabu_utils.py +9 -0
  31. tomwer/core/process/reconstruction/nabu/utils.py +18 -14
  32. tomwer/core/process/reconstruction/normalization/normalization.py +1 -1
  33. tomwer/core/process/reconstruction/normalization/params.py +4 -4
  34. tomwer/core/process/reconstruction/output.py +2 -2
  35. tomwer/core/process/reconstruction/saaxis/params.py +3 -3
  36. tomwer/core/process/reconstruction/saaxis/saaxis.py +5 -1
  37. tomwer/core/process/reconstruction/scores/params.py +2 -2
  38. tomwer/core/process/reconstruction/scores/scores.py +3 -3
  39. tomwer/core/process/reconstruction/tests/test_axis.py +1 -1
  40. tomwer/core/process/reconstruction/tests/test_saaxis.py +56 -66
  41. tomwer/core/process/stitching/metadataholder.py +5 -5
  42. tomwer/core/process/stitching/nabustitcher.py +1 -4
  43. tomwer/core/process/tests/test_normalization.py +2 -1
  44. tomwer/core/scan/edfscan.py +3 -3
  45. tomwer/core/scan/nxtomoscan.py +3 -3
  46. tomwer/core/scan/scanbase.py +3 -3
  47. tomwer/core/scan/scantype.py +1 -1
  48. tomwer/core/settings.py +1 -1
  49. tomwer/core/tomwer_object.py +1 -1
  50. tomwer/core/utils/nxtomoutils.py +2 -2
  51. tomwer/core/utils/spec.py +6 -3
  52. tomwer/gui/cluster/slurm.py +3 -3
  53. tomwer/gui/configuration/level.py +1 -1
  54. tomwer/gui/control/actions.py +1 -1
  55. tomwer/gui/control/datadiscovery.py +1 -1
  56. tomwer/gui/control/datalist.py +1 -1
  57. tomwer/gui/control/reducedarkflatselector.py +4 -4
  58. tomwer/gui/control/series/seriescreator.py +5 -5
  59. tomwer/gui/control/tomoobjdisplaymode.py +1 -1
  60. tomwer/gui/dataportal/gallery.py +6 -6
  61. tomwer/gui/edit/imagekeyeditor.py +7 -9
  62. tomwer/gui/edit/nxtomoeditor.py +420 -112
  63. tomwer/gui/edit/tests/test_nx_editor.py +155 -83
  64. tomwer/gui/reconstruction/axis/CalculationWidget.py +1 -1
  65. tomwer/gui/reconstruction/axis/EstimatedCORWidget.py +12 -8
  66. tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +2 -2
  67. tomwer/gui/reconstruction/axis/InputWidget.py +3 -3
  68. tomwer/gui/reconstruction/darkref/darkrefwidget.py +2 -2
  69. tomwer/gui/reconstruction/nabu/castvolume.py +16 -1
  70. tomwer/gui/reconstruction/nabu/nabuconfig/base.py +2 -4
  71. tomwer/gui/reconstruction/nabu/nabuconfig/ctf.py +6 -6
  72. tomwer/gui/reconstruction/nabu/nabuconfig/nabuconfig.py +1 -1
  73. tomwer/gui/reconstruction/nabu/nabuconfig/phase.py +5 -5
  74. tomwer/gui/reconstruction/nabu/nabuconfig/preprocessing.py +2 -4
  75. tomwer/gui/reconstruction/nabu/nabuconfig/reconstruction.py +78 -52
  76. tomwer/gui/reconstruction/nabu/nabuflow.py +3 -13
  77. tomwer/gui/reconstruction/nabu/slices.py +11 -11
  78. tomwer/gui/reconstruction/nabu/test/test_cast_volume.py +19 -0
  79. tomwer/gui/reconstruction/nabu/volume.py +1 -1
  80. tomwer/gui/reconstruction/normalization/intensity.py +8 -12
  81. tomwer/gui/reconstruction/saaxis/corrangeselector.py +2 -2
  82. tomwer/gui/reconstruction/saaxis/dimensionwidget.py +71 -67
  83. tomwer/gui/reconstruction/sacommon.py +1 -1
  84. tomwer/gui/reconstruction/scores/scoreplot.py +18 -10
  85. tomwer/gui/reconstruction/tests/test_saaxis.py +18 -16
  86. tomwer/gui/stitching/SingleAxisStitchingWidget.py +8 -8
  87. tomwer/gui/stitching/StitchingOptionsWidget.py +1 -1
  88. tomwer/gui/stitching/alignment.py +8 -8
  89. tomwer/gui/stitching/config/axisparams.py +2 -2
  90. tomwer/gui/stitching/config/output.py +1 -1
  91. tomwer/gui/stitching/config/positionoveraxis.py +1 -1
  92. tomwer/gui/stitching/config/stitchingstrategies.py +4 -6
  93. tomwer/gui/stitching/config/tomoobjdetails.py +21 -13
  94. tomwer/gui/stitching/normalization.py +6 -6
  95. tomwer/gui/stitching/tests/test_ZStitchingWindow.py +8 -1
  96. tomwer/gui/stitching/tests/test_preview.py +10 -7
  97. tomwer/gui/stitching/tests/utils.py +27 -18
  98. tomwer/gui/stitching/z_stitching/fineestimation.py +7 -9
  99. tomwer/gui/stitching/z_stitching/tests/test_raw_estimation.py +18 -7
  100. tomwer/gui/stitching/z_stitching/tests/test_stitching_window.py +7 -2
  101. tomwer/gui/utils/buttons.py +54 -36
  102. tomwer/gui/utils/flow.py +2 -2
  103. tomwer/gui/utils/loadingmode.py +1 -1
  104. tomwer/gui/utils/unitsystem.py +44 -33
  105. tomwer/gui/utils/vignettes.py +1 -1
  106. tomwer/gui/visualization/dataviewer.py +7 -7
  107. tomwer/gui/visualization/diffviewer/diffviewer.py +4 -4
  108. tomwer/gui/visualization/diffviewer/shiftwidget.py +4 -6
  109. tomwer/gui/visualization/reconstructionparameters.py +35 -23
  110. tomwer/gui/visualization/scanoverview.py +28 -11
  111. tomwer/gui/visualization/test/test_nx_tomo_metadata_viewer.py +25 -13
  112. tomwer/gui/visualization/test/test_reconstruction_parameters.py +2 -2
  113. tomwer/model/dataset.py +0 -0
  114. tomwer/resources/gui/icons/borders.png +0 -0
  115. tomwer/synctools/utils/scanstages.py +3 -3
  116. tomwer/tasks/reconstruction/cleardarkflat.py +42 -0
  117. tomwer/tests/app/test_stitching.py +1 -1
  118. tomwer/tests/orangecontrib/tomwer/widgets/edit/tests/test_nxtomo_editor.py +32 -20
  119. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_nabu_widget.py +1 -1
  120. tomwer/version.py +2 -2
  121. {tomwer-1.4.19.dist-info → tomwer-1.5.0.dist-info}/METADATA +8 -8
  122. {tomwer-1.4.19.dist-info → tomwer-1.5.0.dist-info}/RECORD +126 -123
  123. {tomwer-1.4.19.dist-info → tomwer-1.5.0.dist-info}/WHEEL +1 -1
  124. {tomwer-1.4.19.dist-info → tomwer-1.5.0.dist-info}/entry_points.txt +0 -0
  125. {tomwer-1.4.19.dist-info → tomwer-1.5.0.dist-info}/licenses/LICENSE +0 -0
  126. {tomwer-1.4.19.dist-info → tomwer-1.5.0.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._dim0Value = 1.0 * MetricSystem.MILLIMETER.value
41
- self._dim1Value = 1.0 * MetricSystem.MILLIMETER.value
42
- self._dim2Value = 1.0 * MetricSystem.MILLIMETER.value
43
- self._displayUnit = MetricSystem.MILLIMETER
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._getDim0DisplayValue())
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._getDim1DisplayValue())
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._getDim2DisplayValue())
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 _getDim0DisplayValue(self) -> float:
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
- self._displayUnit = MetricSystem.from_value(unit)
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(str(self.unit()))
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._getDim0DisplayValue())
114
- self._dim1ValueQLE.setValue(self._getDim1DisplayValue())
115
- self._dim2ValueQLE.setValue(self._getDim2DisplayValue())
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
- :return: metric system used for display
121
- """
122
- return self._displayUnit
123
-
124
- def setValues(
117
+ def setQuantities(
125
118
  self,
126
- dim0: float,
127
- dim1: float,
128
- dim2: float,
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.setDim0value(value=dim0, unit=unit)
140
- self.setDim1value(value=dim1, unit=unit)
141
- self.setDim2value(value=dim2, unit=unit)
131
+ self.setDim0Quantity(value=dim0)
132
+ self.setDim1value(value=dim1)
133
+ self.setDim2Quantity(value=dim2)
142
134
  self.valuesChanged.emit()
143
135
 
144
- def getValues(self) -> tuple:
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, unit)
142
+ :return: (dim0 value, dim1 value, dim2 value)
148
143
  """
149
- return (
150
- self.getDim0Value()[0],
151
- self.getDim1Value()[0],
152
- self.getDim2Value()[0],
153
- MetricSystem.METER,
154
- )
155
-
156
- def getDim0Value(self) -> tuple:
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, MetricSystem.METER
159
+ return self._dim0Value
159
160
 
160
- def setDim0value(self, value: str | MetricSystem, unit="mm"):
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
- self._dim0Value = value * MetricSystem.from_value(unit).value
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 getDim1Value(self) -> tuple:
172
- """Return Dim 0 value and unit. Unit is always meter"""
173
- return self._dim1Value, MetricSystem.METER
173
+ def getDim1Quantity(self) -> pint.Quantity:
174
+ """Return Dim 1 Quantity"""
175
+ return self._dim1Value
174
176
 
175
- def setDim1value(self, value: str | MetricSystem, unit="mm"):
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
- self._dim1Value = value * MetricSystem.from_value(unit).value
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 getDim2Value(self) -> tuple:
187
- """Return Dim 0 value and unit. Unit is always meter"""
188
- return self._dim2Value, MetricSystem.METER
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 setDim2value(self, value: str | MetricSystem, unit="mm"):
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
- self._dim2Value = value * MetricSystem.from_value(unit).value
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.unit().value
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.unit().value
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.unit().value
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.from_value(level)
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.from_value(self._scoreMethodCB.currentText())
251
+ return ScoreMethod(self._scoreMethodCB.currentText())
251
252
 
252
253
  def setScoreMethod(self, method):
253
- method_value = ScoreMethod.from_value(method).value
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.from_value(score_method)
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(self, dim0, dim1, dim2, unit: str | float):
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.setValues(dim0=dim0, dim1=dim1, dim2=dim2, unit=unit)
753
+ self._voxelSizeW.setQuantities(dim0=dim0, dim1=dim1, dim2=dim2)
751
754
 
752
- def setVolumeSize(self, dim0, dim1, dim2, unit: str | float):
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.setValues(dim0=dim0, dim1=dim1, dim2=dim2, unit=unit)
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.getDim0Value()[0] / self._voxelSizeW.getDim0Value()[0]
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.getDim1Value()[0] / self._voxelSizeW.getDim1Value()[0]
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.getDim2Value()[0] / self._voxelSizeW.getDim2Value()[0]
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.getValues(),
46
- (0.001, 0.001, 0.001, MetricSystem.METER),
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.getValues(),
54
- (0.02, 0.001, 0.001, MetricSystem.METER),
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.getValues(),
62
- (0.02, 0.0006, 0.001, MetricSystem.METER),
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(MetricSystem.MICROMETER)
67
+ self._window.setUnit(_ureg.millimeter)
66
68
  self.assertEqual(
67
- self._window.getValues(),
68
- (0.02, 0.0006, 0.001, MetricSystem.METER),
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._dim0ValueQLE.value(),
72
- 20 * MetricSystem.MILLIMETER.value / MetricSystem.MICROMETER.value,
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.getValues(),
79
- (0.02, 0.0006, 0.0005, MetricSystem.METER),
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 testConstructorWithdimNames(self):
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.values(),
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.from_value(self._stitchingTypeCB.currentText())
87
+ return StitchingType(self._stitchingTypeCB.currentText())
88
88
 
89
89
  def setStitchingType(self, mode):
90
- mode = StitchingType.from_value(mode)
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.from_value(mode) for mode in pre_proc_modes])
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.from_value(mode) for mode in post_proc_modes])
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.x_pixel_size is not None
136
- and tomo_obj.y_pixel_size is not None
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.x_pixel_size, tomo_obj.y_pixel_size
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.from_value(stitching_type)
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.values():
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.values():
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.from_value(self._alignmentAxis1CB.currentText())
64
+ return AlignmentAxis1(self._alignmentAxis1CB.currentText())
65
65
 
66
66
  def setAlignmentAxis1(self, alignment: AlignmentAxis1):
67
- alignment = AlignmentAxis1.from_value(alignment)
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.from_value(self._alignmentAxis2CB.currentText())
73
+ return AlignmentAxis2(self._alignmentAxis2CB.currentText())
74
74
 
75
75
  def setAlignmentAxis2(self, alignment: AlignmentAxis2):
76
- alignment = AlignmentAxis2.from_value(alignment)
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.from_value(self._shiftSearchMethodCB.currentText())
83
+ return StitchShiftAlgorithm(self._shiftSearchMethodCB.currentText())
84
84
 
85
85
  def setShiftSearchMethod(self, method: StitchShiftAlgorithm | str) -> None:
86
- method = StitchShiftAlgorithm.from_value(method)
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.from_value(stitching_type)
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
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  import functools
5
5
  import numpy
6
6
  from silx.gui import qt
7
- from silx.utils.enum import Enum as _Enum
7
+ from enum import Enum as _Enum
8
8
 
9
9
  from tomwer.core.tomwer_object import TomwerObject
10
10
  from tomwer.gui import icons
@@ -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.values():
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.from_value(
80
- self._stitchingStrategyCG.currentText()
81
- )
79
+ return OverlapStitchingStrategy(self._stitchingStrategyCG.currentText())
82
80
 
83
81
  def setStitchingStrategy(self, strategy: OverlapStitchingStrategy | str):
84
- strategy = OverlapStitchingStrategy.from_value(strategy)
82
+ strategy = OverlapStitchingStrategy(strategy)
85
83
  idx = self._stitchingStrategyCG.findText(strategy.value)
86
84
  if idx >= 0:
87
85
  self._stitchingStrategyCG.setCurrentIndex(idx)