tomwer 1.4.0__py3-none-any.whl → 1.4.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.
Files changed (53) hide show
  1. orangecontrib/tomwer/tutorials/test_cor.ows +3 -3
  2. orangecontrib/tomwer/widgets/reconstruction/AxisOW.py +14 -6
  3. orangecontrib/tomwer/widgets/reconstruction/NabuVolumeOW.py +2 -4
  4. tomwer/app/axis.py +3 -0
  5. tomwer/app/multipag.py +3 -11
  6. tomwer/core/process/reconstruction/axis/axis.py +736 -27
  7. tomwer/core/process/reconstruction/axis/mode.py +24 -86
  8. tomwer/core/process/reconstruction/axis/params.py +138 -127
  9. tomwer/core/process/reconstruction/nabu/nabuscores.py +22 -19
  10. tomwer/core/process/reconstruction/nabu/nabuslices.py +1 -5
  11. tomwer/core/process/reconstruction/saaxis/saaxis.py +4 -4
  12. tomwer/core/process/reconstruction/sadeltabeta/sadeltabeta.py +4 -4
  13. tomwer/core/process/reconstruction/tests/test_axis.py +1 -1
  14. tomwer/core/process/reconstruction/tests/test_utils.py +4 -4
  15. tomwer/core/process/reconstruction/utils/cor.py +4 -8
  16. tomwer/core/process/tests/test_axis.py +231 -0
  17. tomwer/core/process/tests/test_nabu.py +3 -1
  18. tomwer/core/scan/nxtomoscan.py +0 -2
  19. tomwer/core/scan/scanbase.py +4 -4
  20. tomwer/core/scan/tests/test_process_registration.py +18 -0
  21. tomwer/gui/reconstruction/axis/AxisMainWindow.py +9 -20
  22. tomwer/gui/reconstruction/axis/AxisOptionsWidget.py +79 -239
  23. tomwer/gui/reconstruction/axis/AxisSettingsWidget.py +17 -38
  24. tomwer/gui/reconstruction/axis/AxisWidget.py +8 -16
  25. tomwer/gui/reconstruction/axis/CalculationWidget.py +200 -44
  26. tomwer/gui/reconstruction/axis/ControlWidget.py +2 -10
  27. tomwer/gui/reconstruction/axis/InputWidget.py +155 -11
  28. tomwer/gui/reconstruction/saaxis/corrangeselector.py +10 -19
  29. tomwer/gui/reconstruction/scores/scoreplot.py +2 -5
  30. tomwer/gui/reconstruction/tests/test_nabu.py +0 -8
  31. tomwer/gui/stitching/config/axisparams.py +0 -2
  32. tomwer/gui/stitching/z_stitching/fineestimation.py +1 -1
  33. tomwer/gui/tests/test_axis_gui.py +15 -31
  34. tomwer/synctools/stacks/reconstruction/axis.py +23 -5
  35. tomwer/synctools/stacks/reconstruction/dkrefcopy.py +1 -1
  36. tomwer/synctools/stacks/reconstruction/nabu.py +2 -2
  37. tomwer/synctools/stacks/reconstruction/normalization.py +1 -1
  38. tomwer/synctools/stacks/reconstruction/saaxis.py +1 -1
  39. tomwer/synctools/stacks/reconstruction/sadeltabeta.py +1 -1
  40. tomwer/tests/orangecontrib/tomwer/widgets/reconstruction/tests/test_axis.py +16 -0
  41. tomwer/tests/test_ewoks/test_single_node_execution.py +1 -1
  42. tomwer/tests/test_ewoks/test_workflows.py +1 -1
  43. tomwer/version.py +1 -1
  44. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/METADATA +3 -3
  45. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/RECORD +49 -52
  46. tomwer/core/process/reconstruction/axis/side.py +0 -8
  47. tomwer/gui/fonts.py +0 -5
  48. tomwer/gui/reconstruction/axis/EstimatedCORWidget.py +0 -394
  49. tomwer/gui/reconstruction/axis/EstimatedCorComboBox.py +0 -118
  50. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/LICENSE +0 -0
  51. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/WHEEL +0 -0
  52. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/entry_points.txt +0 -0
  53. {tomwer-1.4.0.dist-info → tomwer-1.4.0rc0.dist-info}/top_level.txt +0 -0
@@ -2,17 +2,9 @@ from __future__ import annotations
2
2
 
3
3
  from silx.gui import qt
4
4
 
5
- from tomwer.core.process.reconstruction.axis.mode import AxisMode, AXIS_MODE_METADATAS
6
5
  from tomwer.synctools.axis import QAxisRP
7
6
  from tomwer.core.process.reconstruction.axis.params import AxisCalculationInput
8
7
  from tomwer.gui.utils.qt_utils import block_signals
9
- from tomwer.gui.utils.scrollarea import QComboBoxIgnoreWheel, QSpinBoxIgnoreWheel
10
- from tomwer.core.process.reconstruction.axis.params import (
11
- DEFAULT_CMP_N_SUBSAMPLING_Y,
12
- DEFAULT_CMP_OVERSAMPLING,
13
- DEFAULT_CMP_TAKE_LOG,
14
- DEFAULT_CMP_THETA,
15
- )
16
8
 
17
9
 
18
10
  class AxisOptionsWidget(qt.QWidget):
@@ -22,50 +14,12 @@ class AxisOptionsWidget(qt.QWidget):
22
14
  Used as a tab of the AxisSettingsTabWidget
23
15
  """
24
16
 
25
- sigChanged = qt.Signal()
26
- """Emit when the options changed"""
27
-
28
17
  def __init__(self, parent, axis_params):
29
18
  qt.QWidget.__init__(self, parent=parent)
30
19
  assert isinstance(axis_params, QAxisRP)
31
20
  self._axis_params = axis_params
32
21
  self.setLayout(qt.QVBoxLayout())
33
22
 
34
- # cor_options
35
- self._corOptsWidget = qt.QWidget(self)
36
- self._corOptsWidget.setLayout(qt.QFormLayout())
37
- self._corOpts = qt.QLineEdit(self)
38
- self._corOpts.setToolTip(
39
- "Options for methods finding automatically the rotation axis position. 'side', 'near_pos' and 'near_width' are already provided by dedicated interface. The parameters are separated by commas and passed as 'name=value'. Mind the semicolon separator (;)."
40
- )
41
- self._corOpts.setPlaceholderText("low_pass=1; high_pass=20")
42
- self._corOptsWidget.layout().addRow("cor advanced options", self._corOpts)
43
- self.layout().addWidget(self._corOptsWidget)
44
-
45
- # padding option
46
- self._padding_widget = qt.QGroupBox("padding mode")
47
- self._padding_widget.setCheckable(True)
48
- self.layout().addWidget(self._padding_widget)
49
- self._padding_widget.setLayout(qt.QHBoxLayout())
50
-
51
- self._qbPaddingMode = QComboBoxIgnoreWheel(self._padding_widget)
52
- for _mode in (
53
- "constant",
54
- "edge",
55
- "linear_ramp",
56
- "maximum",
57
- "mean",
58
- "median",
59
- "minimum",
60
- "reflect",
61
- "symmetric",
62
- "wrap",
63
- ):
64
- self._qbPaddingMode.addItem(_mode)
65
- def_index = self._qbPaddingMode.findText("edge")
66
- self._qbPaddingMode.setCurrentIndex(def_index)
67
- self._padding_widget.layout().addWidget(self._qbPaddingMode)
68
-
69
23
  # define common options
70
24
  self._commonOpts = qt.QWidget(parent=self)
71
25
  self._commonOpts.setLayout(qt.QFormLayout())
@@ -76,75 +30,39 @@ class AxisOptionsWidget(qt.QWidget):
76
30
  self._qcbDataMode.addItem(data_mode.name(), data_mode)
77
31
  self._qcbDataMode.hide()
78
32
 
33
+ # add scale option
34
+ self._scaleOpt = qt.QCheckBox(parent=self)
35
+ self._commonOpts.layout().addRow("scale the two images", self._scaleOpt)
79
36
  self.layout().addWidget(self._commonOpts)
80
37
 
81
- # composite method advanced options
82
- self._compositeOptsGroup = CompositeOptsGroup(
83
- parent=self, axis_params=axis_params
84
- )
85
- self.layout().addWidget(self._compositeOptsGroup)
38
+ # add near options
39
+ self._nearOpts = _AxisNearOptsWidget(parent=self, axis_params=self._axis_params)
40
+ self.layout().addWidget(self._nearOpts)
86
41
 
87
42
  # set up
88
43
  self.setCalculationInputType(self._axis_params.calculation_input_type)
89
- self._compositeOptsGroup.setVisible(
90
- self._axis_params.mode in (AxisMode.near, AxisMode.composite_coarse_to_fine)
91
- )
92
44
 
93
45
  # connect signal / slot
94
- self._corOpts.editingFinished.connect(self._updateAdvancedCorOptions)
46
+ self._scaleOpt.toggled.connect(self._updateScaleOpt)
95
47
  self._qcbDataMode.currentIndexChanged.connect(self._updateInputType)
96
- self._axis_params.sigChanged.connect(self._axis_params_changed)
97
- self._qbPaddingMode.currentIndexChanged.connect(self._paddingModeChanged)
98
- self._padding_widget.toggled.connect(self._paddingModeChanged)
99
- self._compositeOptsGroup.sigChanged.connect(self.sigChanged)
48
+ self._axis_params.sigChanged.connect(self._updateMode)
100
49
 
101
- def _axis_params_changed(self):
50
+ def _updateMode(self):
102
51
  with block_signals(self):
103
- # update according to AxisCalculationInput
104
52
  index = self._qcbDataMode.findText(
105
53
  self._axis_params.calculation_input_type.name()
106
54
  )
107
55
  if index >= 0:
108
56
  self._qcbDataMode.setCurrentIndex(index)
109
- # update advanced cor options visibility (not relevant if mode is manual or read)
110
- axis_mode = self._axis_params.mode
111
- self._corOptsWidget.setVisible(
112
- axis_mode
113
- not in (
114
- AxisMode.manual,
115
- AxisMode.read,
116
- )
117
- )
118
- # update cor options value
119
- self.setCorOptions(self._axis_params.extra_cor_options)
120
- self.setPaddingMode(self._axis_params.padding_mode)
121
- self._padding_widget.setVisible(
122
- AXIS_MODE_METADATAS[axis_mode].allows_padding
123
- )
124
-
125
- def _updateInputType(self, *arg, **kwargs):
126
- self._axis_params.calculation_input_type = self.getCalculationInputType()
127
- self.sigChanged.emit()
128
-
129
- def _paddingModeChanged(self, *args, **kwargs):
130
- self._axis_params.padding_mode = self.getPaddingMode()
131
- self.sigChanged.emit()
132
57
 
133
- def getPaddingMode(self):
134
- if self._padding_widget.isChecked():
135
- return self._qbPaddingMode.currentText()
136
- else:
137
- return None
58
+ def _updateScaleOpt(self, *arg, **kwargs):
59
+ self._axis_params.scale_img2_to_img1 = self.isImageScaled()
138
60
 
139
- def setPaddingMode(self, mode):
140
- index = self._qbPaddingMode.findText(mode)
141
- if index >= 0:
142
- self._qbPaddingMode.setCurrentIndex(index)
143
- self._paddingModeChanged()
61
+ def isImageScaled(self):
62
+ return self._scaleOpt.isChecked()
144
63
 
145
- def _updateAdvancedCorOptions(self, *args, **kwargs):
146
- self._axis_params.extra_cor_options = self.getCorOptions()
147
- self.sigChanged.emit()
64
+ def _updateInputType(self, *arg, **kwargs):
65
+ self._axis_params.calculation_input_type = self.getCalculationInputType()
148
66
 
149
67
  def getCalculationInputType(self, *arg, **kwargs):
150
68
  return AxisCalculationInput.from_value(self._qcbDataMode.currentText())
@@ -155,159 +73,81 @@ class AxisOptionsWidget(qt.QWidget):
155
73
  self._qcbDataMode.setCurrentIndex(index_dm)
156
74
 
157
75
  def setAxisParams(self, axis):
76
+ self._nearOpts.setAxisParams(axis=axis)
158
77
  self._axis_params = axis
159
78
  with block_signals(self):
79
+ self._scaleOpt.setChecked(axis.scale_img2_to_img1)
160
80
  index = self._qcbDataMode.findText(axis.calculation_input_type.name())
161
81
  self._qcbDataMode.setCurrentIndex(index)
162
- self._compositeOptsGroup.setAxisParams(axis)
163
82
 
164
- def getCorOptions(self):
165
- return self._corOpts.text()
166
83
 
167
- def setCorOptions(self, opts: str | None):
168
- with block_signals(self._axis_params):
169
- self._corOpts.clear()
170
- if opts:
171
- self._corOpts.setText(opts)
172
- self._updateAdvancedCorOptions()
84
+ class _AxisNearOptsWidget(qt.QWidget):
85
+ """GUI dedicated to the near options"""
86
+
87
+ def __init__(self, parent, axis_params):
88
+ qt.QWidget.__init__(self, parent=parent)
89
+ assert isinstance(axis_params, QAxisRP)
90
+ self._axis_params = axis_params
91
+
92
+ self.setLayout(qt.QFormLayout())
93
+
94
+ self._stdMaxOpt = qt.QCheckBox(parent=self)
95
+ self.layout().addRow("look at max standard deviation", self._stdMaxOpt)
173
96
 
174
- def setMode(self, mode: AxisMode):
175
- composite_opts_visible = AxisMode.from_value(mode) in (
176
- AxisMode.composite_coarse_to_fine,
177
- AxisMode.near,
178
- )
179
- self._compositeOptsGroup.setVisible(composite_opts_visible)
97
+ self._nearWX = qt.QSpinBox(parent=self)
98
+ self._nearWX.setMinimum(1)
99
+ self._nearWX.setValue(5)
100
+ self.layout().addRow("window size", self._nearWX)
180
101
 
102
+ self._fineStepX = qt.QDoubleSpinBox(parent=self)
103
+ self._fineStepX.setMinimum(0.05)
104
+ self._fineStepX.setSingleStep(0.05)
105
+ self._fineStepX.setMaximum(1.0)
106
+ self.layout().addRow("fine step x", self._fineStepX)
181
107
 
182
- class CompositeOptsGroup(qt.QGroupBox):
183
- """Group box dedicated to the composite algorithms"""
108
+ # connect signal / Slot
109
+ self._stdMaxOpt.toggled.connect(self._lookForStxMaxChanged)
110
+ self._nearWX.valueChanged.connect(self._windowSizeChanged)
111
+ self._fineStepX.valueChanged.connect(self._fineStepXChanged)
184
112
 
185
- sigChanged = qt.Signal()
186
- """Emit when the options changed"""
113
+ def _lookForStxMaxChanged(self, *args, **kwargs):
114
+ self._axis_params.look_at_stdmax = self.isLookAtStdMax()
187
115
 
188
- def __init__(self, title="composite options", parent=None, axis_params=None):
189
- self._axis_params = axis_params
190
- super().__init__(title, parent)
191
- ## options for the composite mode
192
- self.setLayout(qt.QFormLayout())
193
- self.layout().setContentsMargins(0, 0, 0, 0)
194
-
195
- self._thetaSB = QSpinBoxIgnoreWheel(self)
196
- self._thetaSB.setRange(0, 360)
197
- self._thetaSB.setValue(DEFAULT_CMP_THETA)
198
- self._thetaSB.setToolTip("a radio will be picked each theta degrees")
199
- self._thetaLabel = qt.QLabel("angle interval (in degree)", self)
200
- self._thetaLabel.setToolTip(
201
- "algorithm will take one projection each 'angle interval'. Also know as 'theta'"
202
- )
203
- self.layout().addRow(self._thetaLabel, self._thetaSB)
204
-
205
- self._oversamplingSB = QSpinBoxIgnoreWheel(self)
206
- self._oversamplingSB.setRange(1, 999999)
207
- self._oversamplingSB.setValue(DEFAULT_CMP_OVERSAMPLING)
208
- self._oversamplingSB.setToolTip("sinogram oversampling")
209
- self.layout().addRow("oversampling", self._oversamplingSB)
210
-
211
- self._nearWidthSB = QSpinBoxIgnoreWheel(self)
212
- self._nearWidthSB.setRange(1, 999999)
213
- self._nearWidthSB.setValue(0)
214
- self._nearWidthSB.setToolTip("position to be used with near option")
215
- self._nearWidthLabel = qt.QLabel("near width", self)
216
- self._nearWidthLabel.setToolTip("position to be used with near option")
217
- self.layout().addRow(self._nearWidthLabel, self._nearWidthSB)
218
-
219
- self._subsamplingYSB = QSpinBoxIgnoreWheel(self)
220
- self._subsamplingYSB.setRange(1, 999999)
221
- self._subsamplingYSB.setValue(DEFAULT_CMP_N_SUBSAMPLING_Y)
222
- self._subsamplingYSB.setToolTip("sinogram number of subsampling along y")
223
- self.layout().addRow("n_subsampling_y", self._subsamplingYSB)
224
-
225
- self._takeLogCB = qt.QCheckBox(self)
226
- self._takeLogCB.setToolTip("Take logarithm")
227
- self._takeLogCB.setChecked(DEFAULT_CMP_TAKE_LOG)
228
- self._takeTheLogLabel = qt.QLabel("linearisation (-log(I/I0))")
229
- self._takeTheLogLabel.setToolTip(
230
- "take (-log(I/I0)) as input. Also know as 'take_log' option"
231
- )
232
- self.layout().addRow(self._takeTheLogLabel, self._takeLogCB)
116
+ def isLookAtStdMax(self) -> bool:
117
+ """
233
118
 
234
- # connect signal / slot
235
- self._thetaSB.valueChanged.connect(self._changed)
236
- self._oversamplingSB.valueChanged.connect(self._changed)
237
- self._subsamplingYSB.valueChanged.connect(self._changed)
238
- self._nearWidthSB.valueChanged.connect(self._changed)
239
- self._takeLogCB.toggled.connect(self._changed)
119
+ :return: is the option for looking at max standard deviation is
120
+ activated
121
+ """
122
+ return self._stdMaxOpt.isChecked()
240
123
 
241
- def setAxisParams(self, axis_params):
242
- with block_signals(self):
243
- self.setConfiguration(axis_params.composite_options)
244
- self._axis_params = axis_params
124
+ def _windowSizeChanged(self, *args, **kwargs):
125
+ self._axis_params.near_wx = self.getWindowSize()
245
126
 
246
- def _changed(self):
247
- if self._axis_params is not None:
248
- self._axis_params.composite_options = self.getConfiguration()
249
- self.sigChanged.emit()
250
-
251
- def getTheta(self) -> int:
252
- return self._thetaSB.value()
253
-
254
- def setTheta(self, theta: int) -> None:
255
- self._thetaSB.setValue(theta)
256
-
257
- def getOversampling(self) -> int:
258
- return self._oversamplingSB.value()
259
-
260
- def setOversampling(self, oversampling: int) -> None:
261
- self._oversamplingSB.setValue(oversampling)
262
-
263
- def getNearWidth(self) -> int:
264
- return self._nearWidthSB.value()
265
-
266
- def setNearWidth(self, value) -> int:
267
- return self._nearWidthSB.setValue(value)
268
-
269
- def getSubSamplingY(self) -> int:
270
- return self._subsamplingYSB.value()
271
-
272
- def setSubSamplingY(self, subsampling: int) -> None:
273
- self._subsamplingYSB.setValue(subsampling)
274
-
275
- def getTakeLog(self) -> bool:
276
- return self._takeLogCB.isChecked()
277
-
278
- def setTakeLog(self, log: bool) -> None:
279
- self._takeLogCB.setChecked(log)
280
-
281
- def getConfiguration(self) -> dict:
282
-
283
- return {
284
- "theta": self.getTheta(),
285
- "oversampling": self.getOversampling(),
286
- "n_subsampling_y": self.getSubSamplingY(),
287
- "take_log": self.getTakeLog(),
288
- "near_width": self.getNearWidth(),
289
- }
290
-
291
- def setConfiguration(self, opts: dict) -> None:
292
- if not isinstance(opts, dict):
293
- raise TypeError("opts should be an instance of dict")
294
- # theta
295
- theta = opts.get("theta", None)
296
- if theta is not None:
297
- self.setTheta(theta=theta)
298
- # oversampling
299
- oversampling = opts.get("oversampling", None)
300
- if oversampling is not None:
301
- self.setOversampling(oversampling)
302
- # n subsampling y
303
- n_subsampling_y = opts.get("n_subsampling_y", None)
304
- if n_subsampling_y is not None:
305
- self.setSubSamplingY(n_subsampling_y)
306
- # near_width
307
- near_width = opts.get("near_width", None)
308
- if near_width is not None:
309
- self.setNearWidth(near_width)
310
- # take log
311
- take_log = opts.get("take_log", None)
312
- if take_log is not None:
313
- self.setTakeLog(take_log)
127
+ def getWindowSize(self) -> int:
128
+ """
129
+
130
+ :return: window size for near search
131
+ """
132
+ return self._nearWX.value()
133
+
134
+ def _fineStepXChanged(self, *args, **kwargs):
135
+ self._axis_params.fine_step_x = self.getFineStepX()
136
+
137
+ def getFineStepX(self) -> float:
138
+ """
139
+
140
+ :return: fine step x for near calculation
141
+ """
142
+ return self._fineStepX.value()
143
+
144
+ def setAxisParams(self, axis: QAxisRP):
145
+ """
146
+
147
+ :param axis: axis to edit
148
+ """
149
+ with block_signals(self):
150
+ self._axis_params = axis
151
+ self._stdMaxOpt.setChecked(axis.look_at_stdmax)
152
+ self._nearWX.setValue(axis.near_wx)
153
+ self._fineStepX.setValue(axis.fine_step_x)
@@ -152,7 +152,6 @@ class AxisSettingsWidget(qt.QWidget):
152
152
  with block_signals(self._axisParams):
153
153
  self._axisParams.mode = mode
154
154
  self._mainWidget._calculationWidget.setMode(mode)
155
- self._mainWidget._optionsWidget.setMode(mode)
156
155
  self._updateAxisView()
157
156
  self._axisParams.sigChanged.emit()
158
157
 
@@ -231,14 +230,14 @@ class AxisSettingsWidget(qt.QWidget):
231
230
 
232
231
  # expose API
233
232
 
234
- def setEstimatedCor(self, value):
235
- self._mainWidget.setEstimatedCorValue(value=value)
233
+ def updateAutomaticallyEstimatedCor(self):
234
+ return self._mainWidget.updateAutomaticallyEstimatedCor()
236
235
 
237
- def updateXRotationAxisPixelPositionOnNewScan(self) -> bool:
238
- return self._mainWidget.updateXRotationAxisPixelPositionOnNewScan()
236
+ def setUpdateAutomaticallyEstimatedCor(self, value):
237
+ self._mainWidget.setUpdateAutomaticallyEstimatedCor(value)
239
238
 
240
- def setUpdateXRotationAxisPixelPositionOnNewScan(self, update: bool):
241
- self._mainWidget.setUpdateXRotationAxisPixelPositionOnNewScan(update=update)
239
+ def setEstimatedCor(self, value):
240
+ self._mainWidget.setEstimatedCorValue(value=value)
242
241
 
243
242
  def getEstimatedCor(self):
244
243
  return self._mainWidget.getEstimatedCor()
@@ -267,12 +266,6 @@ class AxisSettingsWidget(qt.QWidget):
267
266
  def setModeLock(self, mode):
268
267
  return self._mainWidget.setModeLock(mode=mode)
269
268
 
270
- def isYAxisInverted(self) -> bool:
271
- return self._mainWidget.isYAxisInverted()
272
-
273
- def setYAxisInverted(self, checked: bool):
274
- return self._mainWidget.setYAxisInverted(checked=checked)
275
-
276
269
 
277
270
  class ManualAxisSelectionWidget(qt.QWidget):
278
271
  sigResetZoomRequested = qt.Signal()
@@ -499,8 +492,6 @@ class AxisSettingsTabWidget(qt.QTabWidget):
499
492
  sigModeChanged = qt.Signal(str)
500
493
  """Signal emit when mode (algorithm) is changed"""
501
494
 
502
- sigUpdateXRotAxisPixelPosOnNewScan = qt.Signal()
503
-
504
495
  def __init__(
505
496
  self,
506
497
  recons_params: QAxisRP | None,
@@ -526,9 +517,12 @@ class AxisSettingsTabWidget(qt.QTabWidget):
526
517
  spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
527
518
  widget.layout().addWidget(spacer)
528
519
 
520
+ self._optionsSA = qt.QScrollArea(parent=self)
521
+ self._optionsSA.setWidget(self._optionsWidget)
529
522
  self.addTab(self._calculationWidget, "calculation")
530
- self.addTab(self._optionsWidget, "options")
523
+ self.addTab(self._optionsSA, "options")
531
524
  # simplify set up. Hide options
525
+ self._optionsSA.hide()
532
526
  self.addTab(self._inputWidget, "input")
533
527
 
534
528
  # set up
@@ -538,11 +532,11 @@ class AxisSettingsTabWidget(qt.QTabWidget):
538
532
  # connect signal / slot
539
533
  self._calculationWidget.sigLockModeChanged.connect(self.sigLockModeChanged)
540
534
  self.sigModeChanged.connect(self._updatePossibleInput)
541
- self.sigModeChanged.connect(self._updatePossibleOptions)
542
535
  self._inputWidget._sigUrlChanged.connect(self._urlChanged)
543
536
  self._calculationWidget.sigModeChanged.connect(self.sigModeChanged)
544
- self._calculationWidget.sigUpdateXRotAxisPixelPosOnNewScan.connect(
545
- self.sigUpdateXRotAxisPixelPosOnNewScan
537
+ # not very nice but very convenient to have the setting near at the same level
538
+ self._calculationWidget._qleNearPosQLE.textChanged.connect(
539
+ self._inputWidget._changed
546
540
  )
547
541
 
548
542
  def _urlChanged(self):
@@ -550,7 +544,6 @@ class AxisSettingsTabWidget(qt.QTabWidget):
550
544
 
551
545
  def setScan(self, scan):
552
546
  if scan is not None:
553
- self._calculationWidget.setScan(scan)
554
547
  self._inputWidget.setScan(scan)
555
548
 
556
549
  def setAxisParams(self, axis):
@@ -569,10 +562,6 @@ class AxisSettingsTabWidget(qt.QTabWidget):
569
562
  self._inputWidget.setEnabled(True)
570
563
  self._inputWidget.setValidInputs(valid_inputs)
571
564
 
572
- def _updatePossibleOptions(self):
573
- mode = self.getMode()
574
- self._optionsWidget.setMode(mode)
575
-
576
565
  # expose API
577
566
  def isModeLock(self) -> bool:
578
567
  return self._calculationWidget.isModeLock()
@@ -586,25 +575,15 @@ class AxisSettingsTabWidget(qt.QTabWidget):
586
575
  def getEstimatedCor(self):
587
576
  return self._calculationWidget.getEstimatedCor()
588
577
 
589
- def updateXRotationAxisPixelPositionOnNewScan(self) -> bool:
590
- return self._calculationWidget.updateXRotationAxisPixelPositionOnNewScan()
591
-
592
- def setUpdateXRotationAxisPixelPositionOnNewScan(self, update: bool):
593
- self._calculationWidget.setUpdateXRotationAxisPixelPositionOnNewScan(
594
- update=update
595
- )
596
-
597
578
  def getMode(self):
598
579
  """Return algorithm to use for axis calculation"""
599
580
  return self._calculationWidget.getMode()
600
581
 
601
- def isYAxisInverted(self) -> bool:
602
- return self._calculationWidget._estimatedCorWidget.isYAxisInverted()
582
+ def updateAutomaticallyEstimatedCor(self):
583
+ return self._calculationWidget.updateAutomaticallyEstimatedCor()
603
584
 
604
- def setYAxisInverted(self, checked: bool):
605
- return self._calculationWidget._estimatedCorWidget.setYAxisInverted(
606
- checked=checked
607
- )
585
+ def setUpdateAutomaticallyEstimatedCor(self, value):
586
+ self._calculationWidget.setUpdateAutomaticallyEstimatedCor(value)
608
587
 
609
588
 
610
589
  class _ShiftControl(qt.QWidget):
@@ -131,15 +131,18 @@ class AxisWidget(qt.QMainWindow):
131
131
  if mode is axis_mode.AxisMode.manual:
132
132
  self._setModeLockFrmSettings(False)
133
133
 
134
+ def updateAutomaticallyEstimatedCor(self):
135
+ return self._settingsWidget.updateAutomaticallyEstimatedCor()
136
+
137
+ def setUpdateAutomaticallyEstimatedCor(self, value):
138
+ self._settingsWidget.setUpdateAutomaticallyEstimatedCor(value)
139
+
134
140
  def setEstimatedCor(self, value):
135
141
  self._settingsWidget.setEstimatedCor(value=value)
136
142
 
137
143
  def getEstimatedCor(self):
138
144
  return self._settingsWidget.getEstimatedCor()
139
145
 
140
- def updateXRotationAxisPixelPositionOnNewScan(self) -> bool:
141
- return self._settingsWidget.updateXRotationAxisPixelPositionOnNewScan()
142
-
143
146
  def _setModeLockFrmSettings(self, lock: bool):
144
147
  # only lock the push button
145
148
  with block_signals(self):
@@ -230,12 +233,9 @@ class AxisWidget(qt.QMainWindow):
230
233
 
231
234
  if self._scan is not None:
232
235
  self._scan.axis_params.sigAxisUrlChanged.disconnect(self._updatePlot)
233
- update_x_rotation_axis_pixel_position = (
234
- self._settingsWidget._mainWidget.updateXRotationAxisPixelPositionOnNewScan()
235
- )
236
236
  if (
237
- update_x_rotation_axis_pixel_position
238
- and scan.x_rotation_axis_pixel_position is not None
237
+ scan.x_rotation_axis_pixel_position is not None
238
+ and self.updateAutomaticallyEstimatedCor()
239
239
  ):
240
240
  self.setEstimatedCor(scan.x_rotation_axis_pixel_position)
241
241
 
@@ -495,8 +495,6 @@ class AxisWidget(qt.QMainWindow):
495
495
  if self._imgA is not None and self._imgB is not None:
496
496
  self.setImages(imgA=self._imgA, imgB=self._imgB, flipB=self._flipB)
497
497
 
498
- # expose API
499
-
500
498
  def getXShift(self):
501
499
  return self._settingsWidget.getXShift()
502
500
 
@@ -526,9 +524,3 @@ class AxisWidget(qt.QMainWindow):
526
524
 
527
525
  def setModeLock(self, mode):
528
526
  return self._settingsWidget.setModeLock(mode=mode)
529
-
530
- def isYAxisInverted(self) -> bool:
531
- return self._settingsWidget.isYAxisInverted()
532
-
533
- def setYAxisInverted(self, checked: bool):
534
- return self._settingsWidget.setYAxisInverted(checked=checked)