darfix 4.2.0__py3-none-any.whl → 4.3.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 (144) hide show
  1. darfix/core/data_selection.py +11 -2
  2. darfix/core/dataset.py +72 -157
  3. darfix/core/grainplot.py +44 -56
  4. darfix/core/{imageStack.py → image_stack.py} +9 -15
  5. darfix/core/moment_types.py +6 -0
  6. darfix/core/{noiseremoval.py → noise_removal.py} +25 -24
  7. darfix/core/noise_removal_type.py +14 -0
  8. darfix/core/positioners.py +6 -0
  9. darfix/core/rocking_curves.py +6 -3
  10. darfix/core/rocking_curves_map.py +1 -1
  11. darfix/core/{shiftcorrection.py → shift_correction.py} +1 -2
  12. darfix/core/state_of_operation.py +7 -46
  13. darfix/core/utils.py +0 -39
  14. darfix/dtypes.py +1 -9
  15. darfix/gui/{binningWidget.py → binning_widget.py} +2 -29
  16. darfix/gui/{blindSourceSeparationWidget.py → blind_source_separation_widget.py} +4 -16
  17. darfix/gui/{chooseDimensions.py → choose_dimensions.py} +1 -1
  18. darfix/gui/concatenate_scans.py +4 -4
  19. darfix/gui/data_selection/{hdf5_data_selection_widgets.py → hdf5_dataset_selection_widget.py} +3 -56
  20. darfix/gui/data_selection/line_edits.py +54 -8
  21. darfix/gui/data_selection/scan_selection_widgets.py +24 -11
  22. darfix/gui/data_selection/utils.py +11 -0
  23. darfix/gui/data_selection/{WorkingDirSelectionWidget.py → working_dir_selection_widget.py} +15 -14
  24. darfix/gui/{dimensionsWidget.py → dimensions_widget.py} +1 -1
  25. darfix/gui/{displayComponentsWidget.py → display_components_widget.py} +1 -1
  26. darfix/gui/{filterByDimension.py → filter_by_dimension.py} +1 -1
  27. darfix/gui/{grainplot/dimensionRangeSlider2D.py → grain_plot/dimension_range_slider_2d.py} +2 -2
  28. darfix/gui/{grainplot/grainPlotWidget.py → grain_plot/grain_plot_widget.py} +1 -1
  29. darfix/gui/{grainplot/mosaicityWidget.py → grain_plot/mosaicity_widget.py} +21 -23
  30. darfix/gui/{magnificationWidget.py → magnification_widget.py} +1 -1
  31. darfix/gui/{noiseremoval → noise_removal}/noise_removal_widget.py +12 -16
  32. darfix/gui/{noiseremoval → noise_removal}/operation_list_widget.py +2 -2
  33. darfix/gui/{noiseremoval → noise_removal}/parameters_widget.py +6 -6
  34. darfix/gui/{PCAWidget.py → pca_widget.py} +2 -4
  35. darfix/gui/{projectionWidget.py → projection_widget.py} +1 -1
  36. darfix/gui/rocking_curves/{rockingCurvesPlot.py → rocking_curves_plot.py} +13 -13
  37. darfix/gui/rocking_curves/{rockingCurvesWidget.py → rocking_curves_widget.py} +10 -18
  38. darfix/gui/{roiSelectionWidget.py → roi_selection_widget.py} +9 -101
  39. darfix/gui/{shiftcorrection/shiftCorrectionWidget.py → shift_correction/shift_correction_widget.py} +4 -7
  40. darfix/gui/utils/data_path_completer.py +7 -7
  41. darfix/gui/utils/data_path_selection.py +4 -4
  42. darfix/gui/utils/{rangeSlider.py → range_slider.py} +1 -1
  43. darfix/gui/{weakBeamWidget.py → weak_beam_widget.py} +13 -28
  44. darfix/gui/{zSumWidget.py → zsum_widget.py} +1 -2
  45. darfix/main.py +19 -3
  46. darfix/processing/rocking_curves.py +12 -13
  47. darfix/tasks/binning.py +6 -17
  48. darfix/tasks/blind_source_separation.py +121 -0
  49. darfix/tasks/blindsourceseparation.py +8 -131
  50. darfix/tasks/copy.py +0 -2
  51. darfix/tasks/data_partition.py +39 -0
  52. darfix/tasks/datapartition.py +8 -50
  53. darfix/tasks/dimension_definition.py +197 -0
  54. darfix/tasks/dimensiondefinition.py +8 -197
  55. darfix/tasks/grain_plot.py +93 -0
  56. darfix/tasks/grainplot.py +8 -103
  57. darfix/tasks/hdf5_data_selection.py +5 -11
  58. darfix/tasks/hdf5_scans_concatenation.py +4 -4
  59. darfix/tasks/noise_removal.py +88 -0
  60. darfix/tasks/noiseremoval.py +8 -86
  61. darfix/tasks/pca.py +1 -3
  62. darfix/tasks/projection.py +1 -6
  63. darfix/tasks/rocking_curves.py +10 -5
  64. darfix/tasks/roi.py +0 -2
  65. darfix/tasks/shift_correction.py +45 -0
  66. darfix/tasks/shiftcorrection.py +8 -43
  67. darfix/tasks/transformation.py +0 -2
  68. darfix/tasks/weak_beam.py +71 -0
  69. darfix/tasks/weakbeam.py +8 -67
  70. darfix/tasks/zsum.py +1 -1
  71. darfix/tests/conftest.py +1 -1
  72. darfix/tests/gui/test_data_path_completer.py +4 -4
  73. darfix/tests/gui/test_dimension_range_slider_2d.py +2 -2
  74. darfix/tests/gui/test_range_slider_with_spinboxes.py +1 -1
  75. darfix/tests/orange/test_ewoks.py +13 -9
  76. darfix/tests/orange/widgets/test_hdf5_data_selection.py +93 -0
  77. darfix/tests/tasks/test_data_copy.py +0 -2
  78. darfix/tests/tasks/{test_dimensiondefinition.py → test_dimension_definition.py} +1 -1
  79. darfix/tests/tasks/test_weak_beam.py +9 -0
  80. darfix/tests/test_components_matching.py +2 -2
  81. darfix/tests/test_dataset.py +2 -28
  82. darfix/tests/test_dimension.py +1 -1
  83. darfix/tests/test_generate_grain_maps_nxdict.py +4 -5
  84. darfix/tests/test_image_operations.py +4 -4
  85. darfix/tests/test_image_registration.py +17 -17
  86. darfix/tests/test_image_stack.py +2 -13
  87. darfix/tests/test_mask.py +1 -1
  88. darfix/tests/test_moments.py +2 -2
  89. darfix/tests/test_rocking_curves.py +1 -3
  90. darfix/tests/test_shift.py +7 -7
  91. darfix/tests/test_workflow.py +4 -4
  92. darfix/tests/test_zsum.py +3 -6
  93. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/METADATA +5 -3
  94. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/RECORD +141 -135
  95. orangecontrib/darfix/widgets/__init__.py +10 -1
  96. orangecontrib/darfix/widgets/binning.py +3 -3
  97. orangecontrib/darfix/widgets/blindsourceseparation.py +4 -6
  98. orangecontrib/darfix/widgets/concatenateHDF5.py +1 -1
  99. orangecontrib/darfix/widgets/datacopy.py +1 -1
  100. orangecontrib/darfix/widgets/datapartition.py +7 -102
  101. orangecontrib/darfix/widgets/{datasetWidgetBase.py → dataset_widget_base.py} +17 -5
  102. orangecontrib/darfix/widgets/dimensions.py +6 -6
  103. orangecontrib/darfix/widgets/grainplot.py +3 -3
  104. orangecontrib/darfix/widgets/hdf5dataselection.py +34 -14
  105. orangecontrib/darfix/widgets/metadata.py +2 -2
  106. orangecontrib/darfix/widgets/noiseremoval.py +4 -4
  107. orangecontrib/darfix/widgets/{operationWidgetBase.py → operation_widget_base.py} +2 -2
  108. orangecontrib/darfix/widgets/pca.py +2 -2
  109. orangecontrib/darfix/widgets/projection.py +2 -2
  110. orangecontrib/darfix/widgets/rockingcurves.py +5 -2
  111. orangecontrib/darfix/widgets/roiselection.py +24 -106
  112. orangecontrib/darfix/widgets/rsmhistogram.py +2 -2
  113. orangecontrib/darfix/widgets/shiftcorrection.py +3 -3
  114. orangecontrib/darfix/widgets/transformation.py +4 -4
  115. orangecontrib/darfix/widgets/weakbeam.py +20 -103
  116. orangecontrib/darfix/widgets/zsum.py +3 -5
  117. darfix/gui/dataPartitionWidget.py +0 -167
  118. darfix/gui/data_selection/DataSelectionBase.py +0 -59
  119. darfix/tests/tasks/test_datapartition.py +0 -52
  120. /darfix/core/{componentsMatching.py → components_matching.py} +0 -0
  121. /darfix/core/{datapathfinder.py → data_path_finder.py} +0 -0
  122. /darfix/core/{imageRegistration.py → image_registration.py} +0 -0
  123. /darfix/gui/{grainplot → grain_plot}/__init__.py +0 -0
  124. /darfix/gui/{grainplot → grain_plot}/_oridist_toolbar_buttons.py +0 -0
  125. /darfix/gui/{grainplot → grain_plot}/flashlight.py +0 -0
  126. /darfix/gui/{grainplot → grain_plot}/flashlight_mode_action.py +0 -0
  127. /darfix/gui/{grainplot → grain_plot}/oridist_toolbar.py +0 -0
  128. /darfix/gui/{grainplot → grain_plot}/utils.py +0 -0
  129. /darfix/gui/{metadataWidget.py → metadata_widget.py} +0 -0
  130. /darfix/gui/{operationProcess.py → parallel/operation_process.py} +0 -0
  131. /darfix/gui/{operationThread.py → parallel/operation_thread.py} +0 -0
  132. /darfix/gui/rocking_curves/{fitComboBox.py → fit_combobox.py} +0 -0
  133. /darfix/gui/{roiLimitsToolbar.py → roi_limits_toolbar.py} +0 -0
  134. /darfix/gui/{rsmHistogramWidget.py → rsm_histogram_widget.py} +0 -0
  135. /darfix/gui/{rsmWidget.py → rsm_widget.py} +0 -0
  136. /darfix/gui/{shiftcorrection → shift_correction}/__init__.py +0 -0
  137. /darfix/gui/{shiftcorrection/shiftInput.py → shift_correction/shift_input.py} +0 -0
  138. /darfix/gui/utils/{standardButtonBox.py → standard_buttonbox.py} +0 -0
  139. /darfix/processing/{imageOperations.py → image_operations.py} +0 -0
  140. /darfix/tests/{test_datapathfinder.py → test_data_path_finder.py} +0 -0
  141. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/WHEEL +0 -0
  142. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/entry_points.txt +0 -0
  143. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/licenses/LICENSE +0 -0
  144. {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/top_level.txt +0 -0
@@ -6,12 +6,11 @@ from silx.gui.colors import Colormap
6
6
  from silx.gui.plot.items import ImageBase
7
7
  from silx.image.marchingsquares import find_contours
8
8
 
9
- from darfix.gui.grainplot.dimensionRangeSlider2D import DimensionRangeSlider2D
9
+ from darfix.gui.grain_plot.dimension_range_slider_2d import DimensionRangeSlider2D
10
10
 
11
+ from ...core.grainplot import GrainPlotData
11
12
  from ...core.grainplot import GrainPlotMaps
12
13
  from ...core.grainplot import MultiDimMomentType
13
- from ...core.grainplot import OrientationDistData
14
- from ...core.grainplot import compute_mosaicity
15
14
  from ...core.moment_types import MomentType
16
15
  from .flashlight import PlotWithFlashlight
17
16
  from .oridist_toolbar import OriDistButtonIds
@@ -27,8 +26,7 @@ class MosaicityWidget(qt.QWidget):
27
26
  super().__init__(parent)
28
27
 
29
28
  self._grainPlotMaps: GrainPlotMaps | None = None
30
- self._orientation_dist_data: OrientationDistData | None = None
31
- self._mosaicity: numpy.ndarray | None = None
29
+ self._orientation_dist_data: GrainPlotData | None = None
32
30
  self.contours = {}
33
31
 
34
32
  layout = qt.QGridLayout()
@@ -86,7 +84,7 @@ class MosaicityWidget(qt.QWidget):
86
84
  layout.addWidget(separator, 2, 0, 1, 2)
87
85
 
88
86
  #
89
- # zsum threshold
87
+ # zsum threshold and colormap selection
90
88
  # Row 3
91
89
  #
92
90
 
@@ -98,8 +96,15 @@ class MosaicityWidget(qt.QWidget):
98
96
  """ Discard mosa values below this threshold """
99
97
  self._thresholdSB.setButtonSymbols(qt.QAbstractSpinBox.ButtonSymbols.NoButtons)
100
98
  self._thresholdSB.editingFinished.connect(self._computeMosaicityAndOriDist)
101
- thresholdLayout.addWidget(qt.QLabel("ZSum Threshold : "))
99
+ self._colormapCB = qt.QComboBox()
100
+ """ Combo box to select one of the colormap of `colorstamps` package. """
101
+ self._colormapCB.addItems(["hsv", "cut", "orangeBlue", "flat"])
102
+ self._colormapCB.currentTextChanged.connect(self._computeMosaicityAndOriDist)
103
+ thresholdLayout.addWidget(qt.QLabel("ZSum Threshold"))
102
104
  thresholdLayout.addWidget(self._thresholdSB)
105
+ thresholdLayout.addSpacing(20)
106
+ thresholdLayout.addWidget(qt.QLabel("Colormap"))
107
+ thresholdLayout.addWidget(self._colormapCB)
103
108
  thresholdLayout.addStretch(1)
104
109
  layout.addLayout(thresholdLayout, 3, 0)
105
110
 
@@ -123,7 +128,7 @@ class MosaicityWidget(qt.QWidget):
123
128
  return self._sliders.indexDimY()
124
129
 
125
130
  def getMosaicity(self):
126
- return self._mosaicity
131
+ return self._orientation_dist_data.mosaicity
127
132
 
128
133
  def getContoursImage(self):
129
134
  return self._oriDistPlot.getImage()
@@ -147,13 +152,14 @@ class MosaicityWidget(qt.QWidget):
147
152
  self._computeMosaicityAndOriDist()
148
153
 
149
154
  def _plotMosaicity(self):
150
- if self._grainPlotMaps is None:
155
+ if self._grainPlotMaps is None or self._orientation_dist_data is None:
151
156
  return
152
157
 
153
- if self._mosaicity is not None:
154
- add_image_with_transformation(
155
- self._mosaicityPlot, self._mosaicity, self._grainPlotMaps.transformation
156
- )
158
+ add_image_with_transformation(
159
+ self._mosaicityPlot,
160
+ self._orientation_dist_data.mosaicity,
161
+ self._grainPlotMaps.transformation,
162
+ )
157
163
 
158
164
  def _plotOrientationData(self, state=None):
159
165
  if self._grainPlotMaps is None or self._orientation_dist_data is None:
@@ -360,22 +366,14 @@ class MosaicityWidget(qt.QWidget):
360
366
  zsum = self._grainPlotMaps.zsum.copy()
361
367
  zsum[maskZsum] = 0
362
368
 
363
- self._mosaicity = compute_mosaicity(
364
- self._grainPlotMaps.moments_dims,
365
- x_dimension=self.dimension1,
366
- y_dimension=self.dimension2,
367
- x_dimension_range=self._sliders.rangeDimX(),
368
- y_dimension_range=self._sliders.rangeDimY(),
369
- )
370
- self._mosaicity[maskZsum] = 0, 0, 0 # Black
371
-
372
- self._orientation_dist_data = OrientationDistData(
369
+ self._orientation_dist_data = GrainPlotData(
373
370
  self._grainPlotMaps,
374
371
  x_dimension=self.dimension1,
375
372
  y_dimension=self.dimension2,
376
373
  x_dimension_range=self._sliders.rangeDimX(),
377
374
  y_dimension_range=self._sliders.rangeDimY(),
378
375
  zsum=zsum,
376
+ colormap_name=self._colormapCB.currentText(),
379
377
  )
380
378
  self._plotMosaicity()
381
379
  self._plotOrientationData()
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from enum import Enum as _Enum
4
4
 
5
- from ewoksorange.gui.parameterform import block_signals
5
+ from ewoksorange.gui.widgets.parameter_form import block_signals
6
6
  from silx.gui import qt
7
7
 
8
8
 
@@ -11,13 +11,13 @@ from silx.gui.widgets.FrameBrowser import HorizontalSliderWithBrowser
11
11
 
12
12
  from darfix import config
13
13
  from darfix import dtypes
14
- from darfix.core.noiseremoval import BackgroundType
15
- from darfix.core.noiseremoval import NoiseRemovalOperation
16
- from darfix.core.noiseremoval import add_background_data_into_operation
17
- from darfix.core.noiseremoval import apply_noise_removal_operation
18
- from darfix.core.noiseremoval import operation_to_str
19
- from darfix.core.state_of_operation import Operation
20
- from darfix.gui.operationThread import OperationThread
14
+ from darfix.core.noise_removal import BackgroundType
15
+ from darfix.core.noise_removal import NoiseRemovalOperation
16
+ from darfix.core.noise_removal import add_background_data_into_operation
17
+ from darfix.core.noise_removal import apply_noise_removal_operation
18
+ from darfix.core.noise_removal import operation_to_str
19
+ from darfix.core.noise_removal_type import NoiseRemovalType
20
+ from darfix.gui.parallel.operation_thread import OperationThread
21
21
 
22
22
  from .operation_list_widget import OperationListWidget
23
23
  from .parameters_widget import ParametersWidget
@@ -158,10 +158,6 @@ class NoiseRemovalWidget(qt.QWidget):
158
158
  self._parametersWidget.bsBackgroundCB.addItem(
159
159
  BackgroundType.DARK_DATA.value
160
160
  )
161
- if dataset.bg_indices is not None:
162
- self._parametersWidget.bsBackgroundCB.addItem(
163
- BackgroundType.UNUSED_DATA.value
164
- )
165
161
  self._parametersWidget.bsBackgroundCB.addItem(BackgroundType.DATA.value)
166
162
 
167
163
  opersations = self._operationList.getOperations()
@@ -177,14 +173,14 @@ class NoiseRemovalWidget(qt.QWidget):
177
173
  == qt.QMessageBox.StandardButton.Yes
178
174
  ):
179
175
  for operation in opersations:
180
- if operation["type"] is Operation.BS:
176
+ if operation["type"] is NoiseRemovalType.BS:
181
177
  self._computeBackgroundAsync(operation)
182
178
  else:
183
179
  self._operationList.clear()
184
180
 
185
181
  def _launchBackgroundSubtraction(self):
186
182
  operation = NoiseRemovalOperation(
187
- type=Operation.BS,
183
+ type=NoiseRemovalType.BS,
188
184
  parameters={
189
185
  "method": self._parametersWidget.bsMethodsCB.currentText(),
190
186
  "background_type": self._parametersWidget.bsBackgroundCB.currentText(),
@@ -226,7 +222,7 @@ class NoiseRemovalWidget(qt.QWidget):
226
222
  size = self._parametersWidget.hpSizeCB.currentText()
227
223
 
228
224
  operation = NoiseRemovalOperation(
229
- type=Operation.HP,
225
+ type=NoiseRemovalType.HP,
230
226
  parameters={
231
227
  "kernel_size": int(size),
232
228
  },
@@ -247,7 +243,7 @@ class NoiseRemovalWidget(qt.QWidget):
247
243
  top_threshold = None
248
244
 
249
245
  operation = NoiseRemovalOperation(
250
- type=Operation.THRESHOLD,
246
+ type=NoiseRemovalType.THRESHOLD,
251
247
  parameters={
252
248
  "bottom": bottom_threshold,
253
249
  "top": top_threshold,
@@ -261,7 +257,7 @@ class NoiseRemovalWidget(qt.QWidget):
261
257
  if mask is None:
262
258
  return
263
259
  operation = NoiseRemovalOperation(
264
- type=Operation.MASK,
260
+ type=NoiseRemovalType.MASK,
265
261
  parameters={"mask": mask},
266
262
  )
267
263
  self._operationList.append(operation)
@@ -2,8 +2,8 @@ from __future__ import annotations
2
2
 
3
3
  from silx.gui import qt
4
4
 
5
- from ...core.noiseremoval import NoiseRemovalOperation
6
- from ...core.noiseremoval import operation_to_str
5
+ from ...core.noise_removal import NoiseRemovalOperation
6
+ from ...core.noise_removal import operation_to_str
7
7
 
8
8
 
9
9
  class OperationListWidget(qt.QWidget):
@@ -5,9 +5,9 @@ from typing import Optional
5
5
  from silx.gui import qt
6
6
  from silx.gui.widgets.WaitingPushButton import WaitingPushButton
7
7
 
8
- from darfix.core.noiseremoval import NoiseRemovalOperation
9
- from darfix.core.noiseremoval import Operation
10
- from darfix.processing.imageOperations import Method
8
+ from darfix.core.noise_removal import NoiseRemovalOperation
9
+ from darfix.core.noise_removal import NoiseRemovalType
10
+ from darfix.processing.image_operations import Method
11
11
 
12
12
  _logger = logging.getLogger(__file__)
13
13
 
@@ -98,19 +98,19 @@ class ParametersWidget(qt.QWidget):
98
98
  # follow history to obtain last values set by the user
99
99
  for operation in history:
100
100
  try:
101
- if operation["type"] is Operation.BS:
101
+ if operation["type"] is NoiseRemovalType.BS:
102
102
  index = self.bsMethodsCB.findText(
103
103
  str(operation["parameters"]["method"])
104
104
  )
105
105
  if index > 0:
106
106
  self.bsMethodsCB.setCurrentIndex(index)
107
- elif operation["type"] is Operation.HP:
107
+ elif operation["type"] is NoiseRemovalType.HP:
108
108
  index = self.hpSizeCB.findText(
109
109
  str(operation["parameters"]["kernel_size"])
110
110
  )
111
111
  if index > 0:
112
112
  self.hpSizeCB.setCurrentIndex(index)
113
- elif operation["type"] is Operation.THRESHOLD:
113
+ elif operation["type"] is NoiseRemovalType.THRESHOLD:
114
114
  if operation["parameters"]["bottom"] is not None:
115
115
  self.bottomLE.setText(str(operation["parameters"]["bottom"]))
116
116
  if operation["parameters"]["top"] is not None:
@@ -6,7 +6,7 @@ from silx.gui.plot import Plot1D
6
6
 
7
7
  from darfix import dtypes
8
8
 
9
- from .operationThread import OperationThread
9
+ from .parallel.operation_thread import OperationThread
10
10
 
11
11
 
12
12
  class PCAPlot(Plot1D):
@@ -43,7 +43,7 @@ class PCAWidget(qt.QMainWindow):
43
43
  def _computePCA(self):
44
44
  try:
45
45
  self._thread = OperationThread(self, self._dataset.pca)
46
- self._thread.setArgs(return_vals=True, indices=self.indices)
46
+ self._thread.setArgs(return_vals=True)
47
47
  self._thread.finished.connect(self._updateData)
48
48
  self._thread.start()
49
49
  except Exception as e:
@@ -51,8 +51,6 @@ class PCAWidget(qt.QMainWindow):
51
51
 
52
52
  def setDataset(self, dataset: dtypes.Dataset):
53
53
  self._dataset = dataset.dataset
54
- self.indices = dataset.indices
55
- self.bg_indices = dataset.bg_indices
56
54
  self.bg_dataset = dataset.bg_dataset
57
55
  self._computePCA()
58
56
 
@@ -4,7 +4,7 @@ from silx.gui.plot.StackView import StackViewMainWindow
4
4
 
5
5
  from .. import config
6
6
  from ..dtypes import ImageDataset
7
- from .chooseDimensions import ChooseDimensionWidget
7
+ from .choose_dimensions import ChooseDimensionWidget
8
8
 
9
9
 
10
10
  class ProjectionWidget(qt.QWidget):
@@ -10,6 +10,8 @@ from silx.gui.plot import StackView
10
10
  from silx.gui.plot.items.image import ImageStack
11
11
 
12
12
  import darfix
13
+ from darfix.math import bivariate_gaussian
14
+ from darfix.math import gaussian
13
15
 
14
16
  from ...core.dataset import ImageDataset
15
17
  from ...core.dimension import Dimension
@@ -65,11 +67,9 @@ class RockingCurvesPlot(qt.QWidget):
65
67
  layout.addWidget(self._fitPlotGroup)
66
68
 
67
69
  self._dataset: ImageDataset | None = None
68
- self._indices = None
69
70
 
70
71
  def setDataset(self, dataset: Dataset):
71
72
  self._dataset = dataset.dataset
72
- self._indices = dataset.indices
73
73
 
74
74
  if self._dataset.dims.ndim == 3:
75
75
  # fitplot would be a 3D plot ? Not implemented for now.
@@ -87,7 +87,7 @@ class RockingCurvesPlot(qt.QWidget):
87
87
  if self._dataset is None:
88
88
  stack = None
89
89
  else:
90
- stack = self._dataset.as_array3d(self._indices)
90
+ stack = self._dataset.as_array3d()
91
91
 
92
92
  self._sv.setStack(stack)
93
93
  self._sv.setFrameNumber(nframe)
@@ -206,7 +206,7 @@ class RockingCurvesPlot(qt.QWidget):
206
206
  return
207
207
 
208
208
  try:
209
- data = self._dataset.as_array3d(self._indices)
209
+ data = self._dataset.as_array3d()
210
210
  if isinstance(data, numpy.ndarray):
211
211
  rocking_curve = data[:, int(py), int(px)]
212
212
  else:
@@ -224,8 +224,6 @@ class RockingCurvesPlot(qt.QWidget):
224
224
  raise TooManyDimensionsForRockingCurvesError()
225
225
 
226
226
  def _plot2DRockingCurve(self, dataset: ImageDataset, rocking_curve: numpy.ndarray):
227
- y_values = numpy.zeros(dataset.nframes)
228
- y_values[self._indices] = rocking_curve
229
227
  dim1 = dataset.dims.get(1)
230
228
  dim0 = dataset.dims.get(0)
231
229
  assert dim1 is not None
@@ -242,7 +240,9 @@ class RockingCurvesPlot(qt.QWidget):
242
240
  )
243
241
 
244
242
  try:
245
- y_gauss, pars = fit_2d_rocking_curve(rocking_curve, x_values)
243
+ _, pars = fit_2d_rocking_curve(rocking_curve, x_values)
244
+ # Recompute fitted y without any masking (Better vizualisation of the gaussian contours)
245
+ y_gauss = bivariate_gaussian(x_values, *pars)
246
246
 
247
247
  except (TypeError, RuntimeError):
248
248
  _logger.warning("Cannot fit", exc_info=True)
@@ -272,7 +272,7 @@ class RockingCurvesPlot(qt.QWidget):
272
272
  def _plot1DRockingCurve(self, dataset: ImageDataset, rocking_curve: numpy.ndarray):
273
273
  dim = dataset.dims.get(0)
274
274
  assert dim is not None
275
- motor_values = dataset.get_metadata_values(key=dim.name, indices=self._indices)
275
+ motor_values = dataset.get_metadata_values(key=dim.name)
276
276
  if self._axisTypeComboBox.getCurrentAxisType() == "dims":
277
277
  self._fitPlot.setGraphXLabel(dim.name)
278
278
  x = motor_values
@@ -288,7 +288,9 @@ class RockingCurvesPlot(qt.QWidget):
288
288
  self._fitPlot.setGraphYLabel("Intensity")
289
289
  i = self._sv.getFrameNumber()
290
290
  try:
291
- y_gauss, pars = fit_1d_rocking_curve(rocking_curve, x)
291
+ _, pars = fit_1d_rocking_curve(rocking_curve, x)
292
+ # Recompute fitted y without any masking (Better vizualisation of the gaussian contours)
293
+ y_gauss = gaussian(x, *pars)
292
294
  self._lastFitParamsLabel.setText(
293
295
  "AMP:{:.3f} PEAK:{:.3f} FWHM:{:.3f} BG:{:.3f}".format(*pars)
294
296
  )
@@ -296,9 +298,7 @@ class RockingCurvesPlot(qt.QWidget):
296
298
  _logger.warning("Cannot fit", exc_info=True)
297
299
  y_gauss = numpy.full_like(rocking_curve, numpy.nan)
298
300
  else:
299
- x_gauss = numpy.linspace(x[0], x[-1], len(y_gauss))
300
- self._fitPlot.addCurve(x_gauss, y_gauss, legend="fit", color="r")
301
- i_gauss = i * int((len(y_gauss) - 1) / (len(x) - 1))
302
- self._addFitMarker(x_gauss[i_gauss], y_gauss[i_gauss])
301
+ self._fitPlot.addCurve(x, y_gauss, legend="fit", color="r")
302
+ self._addFitMarker(x[i], y_gauss[i])
303
303
 
304
304
  self._addDataMarker(x[i], rocking_curve[i])
@@ -1,14 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import numpy
4
- from ewoksorange.gui.parameterform import block_signals
4
+ from ewoksorange.gui.widgets.parameter_form import block_signals
5
5
  from silx.gui import qt
6
6
  from silx.gui.colors import Colormap
7
7
  from silx.gui.plot import Plot2D
8
8
  from silx.io.dictdump import dicttonx
9
9
 
10
10
  from ... import dtypes
11
- from ...core.dataset import Operation
11
+ from ...core.rocking_curves import compute_residuals
12
12
  from ...core.rocking_curves import generate_rocking_curves_nxdict
13
13
  from ...core.rocking_curves_map import MAPS_1D
14
14
  from ...core.rocking_curves_map import MAPS_2D
@@ -17,8 +17,8 @@ from ...core.utils import NoDimensionsError
17
17
  from ...core.utils import TooManyDimensionsForRockingCurvesError
18
18
  from ..utils.message import missing_dataset_msg
19
19
  from ..utils.utils import select_output_hdf5_file_with_dialog
20
- from .fitComboBox import FitComboBox
21
- from .rockingCurvesPlot import RockingCurvesPlot
20
+ from .fit_combobox import FitComboBox
21
+ from .rocking_curves_plot import RockingCurvesPlot
22
22
 
23
23
  # "Residuals" are not given by the fit but computed by the widget.
24
24
  # It needs to be handled separately of other `MAPS` values
@@ -43,12 +43,12 @@ class RockingCurvesWidget(qt.QWidget):
43
43
  """
44
44
 
45
45
  sigFitClicked = qt.Signal()
46
+ sigAbortClicked = qt.Signal()
46
47
 
47
48
  def __init__(self, parent=None):
48
49
  qt.QWidget.__init__(self, parent)
49
50
 
50
51
  self.dataset = None
51
- self.indices = None
52
52
  self._update_dataset = None
53
53
  self._residuals_cache = None
54
54
  self.maps = None
@@ -77,7 +77,8 @@ class RockingCurvesWidget(qt.QWidget):
77
77
  self._abortFitBtn = qt.QPushButton("Abort")
78
78
  self._abortFitBtn.hide()
79
79
  self._abortFitBtn.clicked.connect(self.__abort)
80
- layout.addWidget(self._abortFitBtn)
80
+ self._abortFitBtn.clicked.connect(self.sigAbortClicked)
81
+ fitLayout.addWidget(self._abortFitBtn)
81
82
 
82
83
  self._mapsCB = qt.QComboBox(self)
83
84
  self._mapsCB.hide()
@@ -102,7 +103,6 @@ class RockingCurvesWidget(qt.QWidget):
102
103
  if not dataset.dataset.dims.ndim:
103
104
  raise NoDimensionsError("RockingCurvesWidget")
104
105
  self.dataset = dataset.dataset
105
- self.indices = dataset.indices
106
106
  self._update_dataset = dataset.dataset
107
107
  self._residuals_cache = None
108
108
 
@@ -133,8 +133,7 @@ class RockingCurvesWidget(qt.QWidget):
133
133
 
134
134
  self._launchFitBtn.hide()
135
135
  self.sigFitClicked.emit()
136
- # TODO: Abort button is not working
137
- # self._abortFit.show()
136
+ self._abortFitBtn.show()
138
137
 
139
138
  def _computeResiduals(self) -> numpy.ndarray | None:
140
139
  """Note: The computation is cached as long as the dataset is loaded."""
@@ -145,12 +144,7 @@ class RockingCurvesWidget(qt.QWidget):
145
144
  if self._residuals_cache is not None:
146
145
  return self._residuals_cache
147
146
 
148
- self._residuals_cache = numpy.sqrt(
149
- numpy.subtract(
150
- self._update_dataset.zsum(self.indices), self.dataset.zsum(self.indices)
151
- )
152
- ** 2
153
- )
147
+ self._residuals_cache = compute_residuals(self._update_dataset, self.dataset)
154
148
  return self._residuals_cache
155
149
 
156
150
  def _displayMap(self, map_name: str):
@@ -178,9 +172,7 @@ class RockingCurvesWidget(qt.QWidget):
178
172
  self._addImage(self.maps[self._mapsCB.currentIndex()])
179
173
 
180
174
  def __abort(self):
181
- self._abortFitBtn.setEnabled(False)
182
- if self.dataset is not None:
183
- self.dataset.stop_operation(Operation.FIT)
175
+ self._abortFitBtn.hide()
184
176
 
185
177
  def onFitFinished(self):
186
178
  self._abortFitBtn.hide()
@@ -4,8 +4,6 @@ __date__ = "26/04/2021"
4
4
 
5
5
  import logging
6
6
 
7
- import silx
8
- from packaging.version import Version
9
7
  from silx.gui import qt
10
8
  from silx.gui.colors import Colormap
11
9
  from silx.gui.plot.items.roi import RectangleROI
@@ -16,7 +14,7 @@ import darfix
16
14
  from darfix import dtypes
17
15
  from darfix.core.roi import clampROI
18
16
 
19
- from .roiLimitsToolbar import RoiLimitsToolBar
17
+ from .roi_limits_toolbar import RoiLimitsToolBar
20
18
 
21
19
  _logger = logging.getLogger(__file__)
22
20
 
@@ -26,29 +24,11 @@ class ROISelectionWidget(qt.QWidget):
26
24
  Widget that allows the user to pick a ROI in any image of the dataset.
27
25
  """
28
26
 
29
- sigValidate = qt.Signal()
30
- """Emit when user wants to keep the current resized dataset and move to next widget"""
31
-
32
- sigApply = qt.Signal()
33
- """Emit when user wants to Apply a ROI. Then we wait for a refinement or a validation"""
34
-
35
- sigReset = qt.Signal()
36
- """Emit when user wants to come back to the initial dataset"""
37
-
38
- sigROIChanged = qt.Signal()
39
- """Emit when the roi is changed"""
40
-
41
27
  def __init__(self, parent=None):
42
28
  super().__init__(parent)
43
29
 
44
30
  self.setLayout(qt.QVBoxLayout())
45
31
  self._sv = StackViewMainWindow()
46
- _buttons = qt.QDialogButtonBox(parent=self)
47
-
48
- self._okB = _buttons.addButton(_buttons.Ok)
49
- self._applyB = _buttons.addButton(_buttons.Apply)
50
- self._resetB = _buttons.addButton(_buttons.Reset)
51
- self._okB.setDefault(False)
52
32
 
53
33
  self._sv.setColormap(
54
34
  Colormap(
@@ -58,20 +38,13 @@ class ROISelectionWidget(qt.QWidget):
58
38
  )
59
39
  self._sv.setKeepDataAspectRatio(True)
60
40
  self.layout().addWidget(self._sv)
61
- self.layout().addWidget(_buttons)
62
41
 
63
- if Version(silx.version) < Version("2.0.0"):
64
- plot = self._sv.getPlot()
65
- else:
66
- plot = self._sv.getPlotWidget()
42
+ plot = self._sv.getPlotWidget()
67
43
 
68
44
  self._roiManager = RegionOfInterestManager(plot)
69
45
 
70
46
  self._roi = RectangleROI()
71
- if Version(silx.version) < Version("2.0.0"):
72
- self._roi.setLabel("ROI")
73
- else:
74
- self._roi.setText("ROI")
47
+ self._roi.setText("ROI")
75
48
  self._roi.setGeometry(origin=(0, 0), size=(10, 10))
76
49
  self._roi.setEditable(True)
77
50
  self._roiManager.addRoi(self._roi)
@@ -79,20 +52,15 @@ class ROISelectionWidget(qt.QWidget):
79
52
  self._roiToolBar = RoiLimitsToolBar(roiManager=self._roiManager)
80
53
  self._sv.addToolBar(qt.Qt.BottomToolBarArea, self._roiToolBar)
81
54
 
82
- # connect signal / slot
83
- self._applyB.clicked.connect(self.applyRoi)
84
- self._okB.clicked.connect(self.sigValidate)
85
- self._resetB.clicked.connect(self.sigReset)
86
- # self._roiManager.sigRoiChanged.connect(self.sigROIChanged)
87
- self._roi.sigRegionChanged.connect(self.sigROIChanged)
88
-
89
- def setDataset(self, dataset: dtypes.Dataset):
55
+ def setDataset(self, dataset: dtypes.Dataset, roiEnabled: bool = True):
90
56
  """Saves the dataset and updates the stack with the dataset data."""
91
57
  if dataset.dataset.title != "":
92
58
  self._sv.setGraphTitle(dataset.dataset.title)
93
- self.setStack(dataset=dataset.dataset)
59
+ self._roi.setVisible(roiEnabled)
60
+ self._roiToolBar.setEnabled(roiEnabled)
61
+ self._setStack(dataset=dataset.dataset)
94
62
 
95
- def _setROIForNewDataset(self, dataset: dtypes.ImageDataset):
63
+ def setROIForNewDataset(self, dataset: dtypes.ImageDataset):
96
64
  if not isinstance(dataset, dtypes.ImageDataset):
97
65
  raise dtypes.DatasetTypeError(dataset)
98
66
  first_frame_shape = dataset.frame_shape
@@ -100,7 +68,7 @@ class ROISelectionWidget(qt.QWidget):
100
68
  size = first_frame_shape[1] // 5, first_frame_shape[0] // 5
101
69
  self.setRoi(center=center, size=size)
102
70
 
103
- def setStack(self, dataset: dtypes.ImageDataset):
71
+ def _setStack(self, dataset: dtypes.ImageDataset):
104
72
  """
105
73
  Sets new data to the stack.
106
74
  Maintains the current frame showed in the view.
@@ -145,63 +113,6 @@ class ROISelectionWidget(qt.QWidget):
145
113
  """
146
114
  return self._roi
147
115
 
148
- def applyRoi(self):
149
- """
150
- Function to apply the region of interest at the data of the dataset
151
- and show the new data in the stack. Dataset data is not yet replaced.
152
- A new roi is created in the middle of the new stack.
153
- """
154
- if self._sv.getPlotWidget().getActiveImage() is None:
155
- return
156
-
157
- self.enableApplyingROI(False)
158
- self.sigApply.emit()
159
-
160
- def enableApplyingROI(self, enable: bool) -> None:
161
- self._applyB.setEnabled(enable)
162
-
163
- def _fitROIToDataset(self, dataset: dtypes.ImageDataset):
164
- """
165
- This function is called when the ROI is applied to the dataset.
166
- The ROI must be updated to match the contour of the new shape.
167
- """
168
- dataset_shape = dataset.frame_shape
169
- self._roi.setGeometry(
170
- size=dataset_shape[::-1],
171
- center=(dataset_shape[1] / 2.0, dataset_shape[0] / 2.0),
172
- )
173
-
174
- def setVisible(self, visible):
175
- super().setVisible(visible) # sets okB as default
176
- self._okB.setDefault(False)
177
-
178
- def getDataset(self) -> dtypes.Dataset:
179
- return self._update_dataset
180
-
181
- def getStackViewColormap(self):
182
- """
183
- Returns the colormap from the stackView
184
-
185
- :rtype: silx.gui.colors.Colormap
186
- """
187
- return self._sv.getColormap()
188
-
189
- def setStackViewColormap(self, colormap):
190
- """
191
- Sets the stackView colormap
192
-
193
- :param colormap: Colormap to set
194
- :type colormap: silx.gui.colors.Colormap
195
- """
196
- self._sv.setColormap(colormap)
197
-
198
- def clearStack(self):
199
- """
200
- Clears stack.
201
- """
202
- self._sv.setStack(None)
203
- self._roi.setGeometry(origin=(0, 0), size=(10, 10))
204
-
205
116
  def clampRoiToDataset(self, dataset: dtypes.ImageDataset):
206
117
  frame_height, frame_width = dataset.frame_shape
207
118
  # warning: we need to invert the order of the frame shape (frame_height, frame_width) vs (frame_width, frame_height)
@@ -215,6 +126,3 @@ class ROISelectionWidget(qt.QWidget):
215
126
  origin=new_origin,
216
127
  size=new_size,
217
128
  )
218
-
219
- def enableValidation(self, isAllowed: bool) -> None:
220
- self._okB.setEnabled(isAllowed)
@@ -13,10 +13,10 @@ import darfix
13
13
 
14
14
  from ... import dtypes
15
15
  from ...core.dataset import ImageDataset
16
- from ..filterByDimension import FilterByDimensionWidget
17
- from ..operationProcess import OperationProcess
16
+ from ..filter_by_dimension import FilterByDimensionWidget
17
+ from ..parallel.operation_process import OperationProcess
18
18
  from ..utils.message import missing_dataset_msg
19
- from .shiftInput import ShiftInput
19
+ from .shift_input import ShiftInput
20
20
 
21
21
  _logger = logging.getLogger(__file__)
22
22
 
@@ -30,8 +30,6 @@ class ShiftCorrectionWidget(qt.QMainWindow):
30
30
  super().__init__(parent=parent)
31
31
  self.setWindowFlags(qt.Qt.WindowType.Widget)
32
32
  self._input_dataset: ImageDataset | None = None
33
- self.indices = None
34
- self.bg_indices = None
35
33
  self.bg_dataset = None
36
34
  self._axis = None
37
35
 
@@ -100,7 +98,6 @@ class ShiftCorrectionWidget(qt.QMainWindow):
100
98
  self,
101
99
  dataset.find_shift,
102
100
  self._axis,
103
- indices=self.indices,
104
101
  )
105
102
  self.thread_detection.finished.connect(self._updateShift)
106
103
  self.thread_detection.start()
@@ -160,6 +157,6 @@ class ShiftCorrectionWidget(qt.QMainWindow):
160
157
  def refreshPlot(self) -> None:
161
158
  # TODO is there another way to refresh plot ?
162
159
  if self._axis is None:
163
- self._sv.setStack(self._input_dataset.as_array3d(self.indices))
160
+ self._sv.setStack(self._input_dataset.as_array3d())
164
161
  else:
165
162
  self._sv.setStack(self._input_dataset.z_sum_along_axis(self._axis))