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.
- darfix/core/data_selection.py +11 -2
- darfix/core/dataset.py +72 -157
- darfix/core/grainplot.py +44 -56
- darfix/core/{imageStack.py → image_stack.py} +9 -15
- darfix/core/moment_types.py +6 -0
- darfix/core/{noiseremoval.py → noise_removal.py} +25 -24
- darfix/core/noise_removal_type.py +14 -0
- darfix/core/positioners.py +6 -0
- darfix/core/rocking_curves.py +6 -3
- darfix/core/rocking_curves_map.py +1 -1
- darfix/core/{shiftcorrection.py → shift_correction.py} +1 -2
- darfix/core/state_of_operation.py +7 -46
- darfix/core/utils.py +0 -39
- darfix/dtypes.py +1 -9
- darfix/gui/{binningWidget.py → binning_widget.py} +2 -29
- darfix/gui/{blindSourceSeparationWidget.py → blind_source_separation_widget.py} +4 -16
- darfix/gui/{chooseDimensions.py → choose_dimensions.py} +1 -1
- darfix/gui/concatenate_scans.py +4 -4
- darfix/gui/data_selection/{hdf5_data_selection_widgets.py → hdf5_dataset_selection_widget.py} +3 -56
- darfix/gui/data_selection/line_edits.py +54 -8
- darfix/gui/data_selection/scan_selection_widgets.py +24 -11
- darfix/gui/data_selection/utils.py +11 -0
- darfix/gui/data_selection/{WorkingDirSelectionWidget.py → working_dir_selection_widget.py} +15 -14
- darfix/gui/{dimensionsWidget.py → dimensions_widget.py} +1 -1
- darfix/gui/{displayComponentsWidget.py → display_components_widget.py} +1 -1
- darfix/gui/{filterByDimension.py → filter_by_dimension.py} +1 -1
- darfix/gui/{grainplot/dimensionRangeSlider2D.py → grain_plot/dimension_range_slider_2d.py} +2 -2
- darfix/gui/{grainplot/grainPlotWidget.py → grain_plot/grain_plot_widget.py} +1 -1
- darfix/gui/{grainplot/mosaicityWidget.py → grain_plot/mosaicity_widget.py} +21 -23
- darfix/gui/{magnificationWidget.py → magnification_widget.py} +1 -1
- darfix/gui/{noiseremoval → noise_removal}/noise_removal_widget.py +12 -16
- darfix/gui/{noiseremoval → noise_removal}/operation_list_widget.py +2 -2
- darfix/gui/{noiseremoval → noise_removal}/parameters_widget.py +6 -6
- darfix/gui/{PCAWidget.py → pca_widget.py} +2 -4
- darfix/gui/{projectionWidget.py → projection_widget.py} +1 -1
- darfix/gui/rocking_curves/{rockingCurvesPlot.py → rocking_curves_plot.py} +13 -13
- darfix/gui/rocking_curves/{rockingCurvesWidget.py → rocking_curves_widget.py} +10 -18
- darfix/gui/{roiSelectionWidget.py → roi_selection_widget.py} +9 -101
- darfix/gui/{shiftcorrection/shiftCorrectionWidget.py → shift_correction/shift_correction_widget.py} +4 -7
- darfix/gui/utils/data_path_completer.py +7 -7
- darfix/gui/utils/data_path_selection.py +4 -4
- darfix/gui/utils/{rangeSlider.py → range_slider.py} +1 -1
- darfix/gui/{weakBeamWidget.py → weak_beam_widget.py} +13 -28
- darfix/gui/{zSumWidget.py → zsum_widget.py} +1 -2
- darfix/main.py +19 -3
- darfix/processing/rocking_curves.py +12 -13
- darfix/tasks/binning.py +6 -17
- darfix/tasks/blind_source_separation.py +121 -0
- darfix/tasks/blindsourceseparation.py +8 -131
- darfix/tasks/copy.py +0 -2
- darfix/tasks/data_partition.py +39 -0
- darfix/tasks/datapartition.py +8 -50
- darfix/tasks/dimension_definition.py +197 -0
- darfix/tasks/dimensiondefinition.py +8 -197
- darfix/tasks/grain_plot.py +93 -0
- darfix/tasks/grainplot.py +8 -103
- darfix/tasks/hdf5_data_selection.py +5 -11
- darfix/tasks/hdf5_scans_concatenation.py +4 -4
- darfix/tasks/noise_removal.py +88 -0
- darfix/tasks/noiseremoval.py +8 -86
- darfix/tasks/pca.py +1 -3
- darfix/tasks/projection.py +1 -6
- darfix/tasks/rocking_curves.py +10 -5
- darfix/tasks/roi.py +0 -2
- darfix/tasks/shift_correction.py +45 -0
- darfix/tasks/shiftcorrection.py +8 -43
- darfix/tasks/transformation.py +0 -2
- darfix/tasks/weak_beam.py +71 -0
- darfix/tasks/weakbeam.py +8 -67
- darfix/tasks/zsum.py +1 -1
- darfix/tests/conftest.py +1 -1
- darfix/tests/gui/test_data_path_completer.py +4 -4
- darfix/tests/gui/test_dimension_range_slider_2d.py +2 -2
- darfix/tests/gui/test_range_slider_with_spinboxes.py +1 -1
- darfix/tests/orange/test_ewoks.py +13 -9
- darfix/tests/orange/widgets/test_hdf5_data_selection.py +93 -0
- darfix/tests/tasks/test_data_copy.py +0 -2
- darfix/tests/tasks/{test_dimensiondefinition.py → test_dimension_definition.py} +1 -1
- darfix/tests/tasks/test_weak_beam.py +9 -0
- darfix/tests/test_components_matching.py +2 -2
- darfix/tests/test_dataset.py +2 -28
- darfix/tests/test_dimension.py +1 -1
- darfix/tests/test_generate_grain_maps_nxdict.py +4 -5
- darfix/tests/test_image_operations.py +4 -4
- darfix/tests/test_image_registration.py +17 -17
- darfix/tests/test_image_stack.py +2 -13
- darfix/tests/test_mask.py +1 -1
- darfix/tests/test_moments.py +2 -2
- darfix/tests/test_rocking_curves.py +1 -3
- darfix/tests/test_shift.py +7 -7
- darfix/tests/test_workflow.py +4 -4
- darfix/tests/test_zsum.py +3 -6
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/METADATA +5 -3
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/RECORD +141 -135
- orangecontrib/darfix/widgets/__init__.py +10 -1
- orangecontrib/darfix/widgets/binning.py +3 -3
- orangecontrib/darfix/widgets/blindsourceseparation.py +4 -6
- orangecontrib/darfix/widgets/concatenateHDF5.py +1 -1
- orangecontrib/darfix/widgets/datacopy.py +1 -1
- orangecontrib/darfix/widgets/datapartition.py +7 -102
- orangecontrib/darfix/widgets/{datasetWidgetBase.py → dataset_widget_base.py} +17 -5
- orangecontrib/darfix/widgets/dimensions.py +6 -6
- orangecontrib/darfix/widgets/grainplot.py +3 -3
- orangecontrib/darfix/widgets/hdf5dataselection.py +34 -14
- orangecontrib/darfix/widgets/metadata.py +2 -2
- orangecontrib/darfix/widgets/noiseremoval.py +4 -4
- orangecontrib/darfix/widgets/{operationWidgetBase.py → operation_widget_base.py} +2 -2
- orangecontrib/darfix/widgets/pca.py +2 -2
- orangecontrib/darfix/widgets/projection.py +2 -2
- orangecontrib/darfix/widgets/rockingcurves.py +5 -2
- orangecontrib/darfix/widgets/roiselection.py +24 -106
- orangecontrib/darfix/widgets/rsmhistogram.py +2 -2
- orangecontrib/darfix/widgets/shiftcorrection.py +3 -3
- orangecontrib/darfix/widgets/transformation.py +4 -4
- orangecontrib/darfix/widgets/weakbeam.py +20 -103
- orangecontrib/darfix/widgets/zsum.py +3 -5
- darfix/gui/dataPartitionWidget.py +0 -167
- darfix/gui/data_selection/DataSelectionBase.py +0 -59
- darfix/tests/tasks/test_datapartition.py +0 -52
- /darfix/core/{componentsMatching.py → components_matching.py} +0 -0
- /darfix/core/{datapathfinder.py → data_path_finder.py} +0 -0
- /darfix/core/{imageRegistration.py → image_registration.py} +0 -0
- /darfix/gui/{grainplot → grain_plot}/__init__.py +0 -0
- /darfix/gui/{grainplot → grain_plot}/_oridist_toolbar_buttons.py +0 -0
- /darfix/gui/{grainplot → grain_plot}/flashlight.py +0 -0
- /darfix/gui/{grainplot → grain_plot}/flashlight_mode_action.py +0 -0
- /darfix/gui/{grainplot → grain_plot}/oridist_toolbar.py +0 -0
- /darfix/gui/{grainplot → grain_plot}/utils.py +0 -0
- /darfix/gui/{metadataWidget.py → metadata_widget.py} +0 -0
- /darfix/gui/{operationProcess.py → parallel/operation_process.py} +0 -0
- /darfix/gui/{operationThread.py → parallel/operation_thread.py} +0 -0
- /darfix/gui/rocking_curves/{fitComboBox.py → fit_combobox.py} +0 -0
- /darfix/gui/{roiLimitsToolbar.py → roi_limits_toolbar.py} +0 -0
- /darfix/gui/{rsmHistogramWidget.py → rsm_histogram_widget.py} +0 -0
- /darfix/gui/{rsmWidget.py → rsm_widget.py} +0 -0
- /darfix/gui/{shiftcorrection → shift_correction}/__init__.py +0 -0
- /darfix/gui/{shiftcorrection/shiftInput.py → shift_correction/shift_input.py} +0 -0
- /darfix/gui/utils/{standardButtonBox.py → standard_buttonbox.py} +0 -0
- /darfix/processing/{imageOperations.py → image_operations.py} +0 -0
- /darfix/tests/{test_datapathfinder.py → test_data_path_finder.py} +0 -0
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/WHEEL +0 -0
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/entry_points.txt +0 -0
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/licenses/LICENSE +0 -0
- {darfix-4.2.0.dist-info → darfix-4.3.0.dist-info}/top_level.txt +0 -0
|
@@ -4,7 +4,6 @@ from silx.gui.plot.StackView import StackViewMainWindow
|
|
|
4
4
|
|
|
5
5
|
import darfix
|
|
6
6
|
from darfix import dtypes
|
|
7
|
-
from darfix.core.state_of_operation import Operation
|
|
8
7
|
from darfix.gui.utils.custom_doublespinbox import createCustomDoubleSpinBox
|
|
9
8
|
from darfix.gui.utils.message import missing_dataset_msg
|
|
10
9
|
|
|
@@ -29,8 +28,6 @@ class BinningWidget(qt.QMainWindow):
|
|
|
29
28
|
def __init__(self, parent=None):
|
|
30
29
|
qt.QMainWindow.__init__(self, parent)
|
|
31
30
|
|
|
32
|
-
self._display_tooltip_msg = True
|
|
33
|
-
|
|
34
31
|
widget = qt.QWidget()
|
|
35
32
|
layout = qt.QGridLayout()
|
|
36
33
|
|
|
@@ -38,11 +35,9 @@ class BinningWidget(qt.QMainWindow):
|
|
|
38
35
|
# original dataset, the one treated. Keep it to be able to re-apply modifications
|
|
39
36
|
self._update_dataset = None
|
|
40
37
|
# dataset with applied modifications. This is the one displayed
|
|
41
|
-
self.indices = None
|
|
42
|
-
self.bg_indices = None
|
|
43
38
|
self.bg_dataset = None
|
|
44
39
|
|
|
45
|
-
self._scaleLE = createCustomDoubleSpinBox(
|
|
40
|
+
self._scaleLE = createCustomDoubleSpinBox(0.5)
|
|
46
41
|
_buttons = qt.QDialogButtonBox(parent=self)
|
|
47
42
|
self._okB = _buttons.addButton(_buttons.Ok)
|
|
48
43
|
self._applyB = _buttons.addButton(_buttons.Apply)
|
|
@@ -63,7 +58,7 @@ class BinningWidget(qt.QMainWindow):
|
|
|
63
58
|
normalization=darfix.config.DEFAULT_COLORMAP_NORM,
|
|
64
59
|
)
|
|
65
60
|
)
|
|
66
|
-
layout.addWidget(qt.QLabel("
|
|
61
|
+
layout.addWidget(qt.QLabel("Binning factor: "), 0, 0)
|
|
67
62
|
layout.addWidget(self._scaleLE, 0, 1)
|
|
68
63
|
layout.addWidget(self._sv, 1, 0, 1, 2)
|
|
69
64
|
layout.addWidget(_buttons, 2, 0, 1, 2)
|
|
@@ -93,26 +88,8 @@ class BinningWidget(qt.QMainWindow):
|
|
|
93
88
|
def setDataset(self, dataset: dtypes.Dataset):
|
|
94
89
|
self._dataset = dataset.dataset
|
|
95
90
|
self._update_dataset = dataset.dataset
|
|
96
|
-
self.indices = dataset.indices
|
|
97
|
-
self.bg_indices = dataset.bg_indices
|
|
98
91
|
self.bg_dataset = dataset.bg_dataset
|
|
99
92
|
self.setStack()
|
|
100
|
-
if self._display_tooltip_msg:
|
|
101
|
-
self.display_tooltip_msg()
|
|
102
|
-
|
|
103
|
-
def display_tooltip_msg(self):
|
|
104
|
-
msg = qt.QMessageBox()
|
|
105
|
-
msg.setIcon(qt.QMessageBox.Information)
|
|
106
|
-
msg.setText(
|
|
107
|
-
"Binning can be used to reduce the computation time of the operations in the workflow.\n"
|
|
108
|
-
+ "The scale is the factor to which the images will be rescaled.\n"
|
|
109
|
-
+ "After the correct parameters are found, you can remove the binning widget from the workflow"
|
|
110
|
-
+ " and execute it either with the GUI or using ewoks.\nBinning should be applied after any"
|
|
111
|
-
+ " ROI to have original images size and not the binned one.\n"
|
|
112
|
-
)
|
|
113
|
-
msg.setWindowTitle("Fit succeeded!")
|
|
114
|
-
msg.setStandardButtons(qt.QMessageBox.Ok)
|
|
115
|
-
msg.exec()
|
|
116
93
|
|
|
117
94
|
def setStack(self, dataset=None):
|
|
118
95
|
"""
|
|
@@ -144,10 +121,6 @@ class BinningWidget(qt.QMainWindow):
|
|
|
144
121
|
self._startComputation()
|
|
145
122
|
self.sigApply.emit()
|
|
146
123
|
|
|
147
|
-
def abort(self):
|
|
148
|
-
self._abortB.setEnabled(False)
|
|
149
|
-
self._update_dataset.stop_operation(Operation.BINNING)
|
|
150
|
-
|
|
151
124
|
def apply(self):
|
|
152
125
|
self.sigComputed.emit()
|
|
153
126
|
|
|
@@ -6,10 +6,10 @@ import numpy
|
|
|
6
6
|
from silx.gui import qt
|
|
7
7
|
|
|
8
8
|
from darfix import dtypes
|
|
9
|
-
from darfix.tasks.
|
|
9
|
+
from darfix.tasks.blind_source_separation import Method
|
|
10
10
|
|
|
11
|
-
from .
|
|
12
|
-
from .
|
|
11
|
+
from .display_components_widget import DisplayComponentsWidget
|
|
12
|
+
from .parallel.operation_thread import OperationThread
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class BSSWidget(qt.QMainWindow):
|
|
@@ -104,8 +104,6 @@ class BSSWidget(qt.QMainWindow):
|
|
|
104
104
|
|
|
105
105
|
def setDataset(self, dataset: dtypes.Dataset):
|
|
106
106
|
self.dataset = dataset.dataset
|
|
107
|
-
self.indices = dataset.indices
|
|
108
|
-
self.bg_indices = dataset.bg_indices
|
|
109
107
|
self.bg_dataset = dataset.bg_dataset
|
|
110
108
|
self.computeButton.setEnabled(True)
|
|
111
109
|
self.detectButton.setEnabled(True)
|
|
@@ -113,13 +111,9 @@ class BSSWidget(qt.QMainWindow):
|
|
|
113
111
|
def _nbComponentEdited(self, *args, **kwargs):
|
|
114
112
|
self.sigNbComponentsChanged.emit(int(self.nComponentsLE.text()))
|
|
115
113
|
|
|
116
|
-
def _displayComponents(
|
|
117
|
-
self, dataset: dtypes.ImageDataset, indices, bg_indices, comp, W
|
|
118
|
-
):
|
|
114
|
+
def _displayComponents(self, dataset: dtypes.ImageDataset, comp, W):
|
|
119
115
|
"""
|
|
120
116
|
:param dataset: dataset for which we want to display the components
|
|
121
|
-
:param indices: dataset indices
|
|
122
|
-
:param bg_indices: background indices
|
|
123
117
|
:param comp: components
|
|
124
118
|
:param W: Matrix with the rocking curves values
|
|
125
119
|
"""
|
|
@@ -143,12 +137,6 @@ class BSSWidget(qt.QMainWindow):
|
|
|
143
137
|
self.computeButton.setEnabled(True)
|
|
144
138
|
self.nComponentsLE.setEnabled(True)
|
|
145
139
|
self.detectButton.setEnabled(True)
|
|
146
|
-
if bg_indices is not None:
|
|
147
|
-
# If filter data is activated, the matrix W has reduced dimensionality, so reshaping is not possible
|
|
148
|
-
# Create empty array with shape the total number of frames
|
|
149
|
-
W = numpy.zeros((dataset.nframes, n_comp))
|
|
150
|
-
# Set actual values of W where threshold of filter is True
|
|
151
|
-
W[indices] = W
|
|
152
140
|
self._displayComponentsWidget.setComponents(
|
|
153
141
|
comp,
|
|
154
142
|
W,
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Callable
|
|
4
4
|
|
|
5
|
-
from ewoksorange.gui.
|
|
5
|
+
from ewoksorange.gui.widgets.parameter_form import block_signals
|
|
6
6
|
from silx.gui import qt
|
|
7
7
|
|
|
8
8
|
from darfix.core.dimension import AcquisitionDims
|
darfix/gui/concatenate_scans.py
CHANGED
|
@@ -4,15 +4,15 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
|
|
6
6
|
import h5py
|
|
7
|
-
from ewoksorange.gui.
|
|
7
|
+
from ewoksorange.gui.widgets.parameter_form import block_signals
|
|
8
8
|
from silx.gui import qt
|
|
9
9
|
|
|
10
|
-
from darfix.core.
|
|
11
|
-
from darfix.core.
|
|
10
|
+
from darfix.core.data_path_finder import DETECTOR_KEYWORD
|
|
11
|
+
from darfix.core.data_path_finder import SCAN_KEYWORD
|
|
12
12
|
from darfix.gui.configuration.action import AdvancedConfigurationAction
|
|
13
13
|
from darfix.gui.configuration.action import RequiredConfigurationAction
|
|
14
14
|
from darfix.gui.configuration.level import ConfigurationLevel
|
|
15
|
-
from darfix.gui.data_selection.
|
|
15
|
+
from darfix.gui.data_selection.hdf5_dataset_selection_widget import (
|
|
16
16
|
HDF5DatasetSelectionWidget,
|
|
17
17
|
)
|
|
18
18
|
from darfix.gui.utils.fileselection import FileSelector
|
darfix/gui/data_selection/{hdf5_data_selection_widgets.py → hdf5_dataset_selection_widget.py}
RENAMED
|
@@ -3,9 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
import h5py
|
|
4
4
|
from silx.gui import qt
|
|
5
5
|
|
|
6
|
-
from darfix.core.
|
|
7
|
-
from darfix.core.
|
|
8
|
-
from darfix.core.
|
|
6
|
+
from darfix.core.data_path_finder import DETECTOR_KEYWORD
|
|
7
|
+
from darfix.core.data_path_finder import FIRST_SCAN_KEYWORD
|
|
8
|
+
from darfix.core.data_path_finder import LAST_SCAN_KEYWORD
|
|
9
9
|
from darfix.gui.utils.data_path_selection import DataPathSelection
|
|
10
10
|
from darfix.gui.utils.fileselection import FileSelector
|
|
11
11
|
from darfix.tasks.hdf5_scans_concatenation import ConcatenateHDF5Scans
|
|
@@ -96,56 +96,3 @@ class HDF5DatasetSelectionWidget(qt.QWidget):
|
|
|
96
96
|
|
|
97
97
|
def getInputFile(self) -> str | None:
|
|
98
98
|
return self._inputFileSelector.getFilePath()
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
class HDF5RawDatasetSelectionWidget(HDF5DatasetSelectionWidget):
|
|
102
|
-
"""Same as the 'HDF5DatasetSelectionWidget' but adds an option to keep data on disk and to provide the title"""
|
|
103
|
-
|
|
104
|
-
sigKeepDataOnDiskChanged = qt.Signal(bool)
|
|
105
|
-
sigTitleChanged = qt.Signal(str)
|
|
106
|
-
|
|
107
|
-
def __init__(self, parent: qt.QWidget | None = None) -> None:
|
|
108
|
-
super().__init__(parent)
|
|
109
|
-
self._keepDataOnDisk = qt.QCheckBox("Keep data on disk")
|
|
110
|
-
self.layout().addWidget(self._keepDataOnDisk, 1, 3, 2, 2)
|
|
111
|
-
|
|
112
|
-
self._titleLabel = qt.QLabel("Workflow title")
|
|
113
|
-
self.layout().addWidget(self._titleLabel, 3, 0, 1, 1)
|
|
114
|
-
self._title = qt.QLineEdit("")
|
|
115
|
-
self.layout().addWidget(self._title, 3, 1, 1, 4)
|
|
116
|
-
|
|
117
|
-
# redefine layout because we want to display 'title' just after the file path selection
|
|
118
|
-
self.layout().addWidget(self._detectorDataPath, 4, 0, 1, 5)
|
|
119
|
-
self.layout().addWidget(self._positionerDataPath, 5, 0, 1, 5)
|
|
120
|
-
|
|
121
|
-
# connect signal / slot
|
|
122
|
-
self._keepDataOnDisk.toggled.connect(self.sigKeepDataOnDiskChanged)
|
|
123
|
-
self._title.editingFinished.connect(self._titleChanged)
|
|
124
|
-
|
|
125
|
-
def isKeepingDataOnDisk(self) -> bool:
|
|
126
|
-
return self._keepDataOnDisk.isChecked()
|
|
127
|
-
|
|
128
|
-
def setKeepDataOnDisk(self, value: bool):
|
|
129
|
-
self._keepDataOnDisk.setChecked(value)
|
|
130
|
-
|
|
131
|
-
def getWorkflowTitle(self) -> str:
|
|
132
|
-
return self._title.text()
|
|
133
|
-
|
|
134
|
-
def setWorkflowTitle(self, title: str):
|
|
135
|
-
self._title.setText(title)
|
|
136
|
-
self._titleChanged()
|
|
137
|
-
|
|
138
|
-
def _titleChanged(self, *args, **kwargs):
|
|
139
|
-
self.sigTitleChanged.emit(self._title.text())
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
class HDF5DarkDatasetSelectionWidget(HDF5DatasetSelectionWidget):
|
|
143
|
-
"""Same as the 'HDF5DatasetSelectionWidget' but hide metadata selection that is unused for dark"""
|
|
144
|
-
|
|
145
|
-
def __init__(self, parent: qt.QWidget | None = None) -> None:
|
|
146
|
-
super().__init__(parent)
|
|
147
|
-
# no positioner possible for dark so hide the selection
|
|
148
|
-
self._positionerDataPath.hide()
|
|
149
|
-
|
|
150
|
-
def getMetadataPathSelection(self) -> None:
|
|
151
|
-
return None
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import h5py
|
|
3
4
|
from silx.gui import qt
|
|
4
5
|
from silx.gui.dialog.DatasetDialog import DatasetDialog
|
|
5
6
|
from silx.gui.dialog.GroupDialog import GroupDialog
|
|
@@ -15,52 +16,84 @@ class _BaseLineEdit(qt.QWidget):
|
|
|
15
16
|
dialogSelected = qt.Signal(str)
|
|
16
17
|
editingFinished = qt.Signal()
|
|
17
18
|
|
|
19
|
+
_ERROR_LINE_EDIT_STYLE_SHEET = "border: 2px solid red"
|
|
20
|
+
_INVALID_INPUT_TXT = "Invalid input."
|
|
21
|
+
|
|
18
22
|
def __init__(self, parent: qt.QWidget | None = None, **kwargs) -> None:
|
|
19
23
|
super().__init__(parent, **kwargs)
|
|
20
24
|
|
|
21
25
|
self._lineEdit = qt.QLineEdit()
|
|
26
|
+
self._defaultLineEditStyle = self._lineEdit.styleSheet()
|
|
27
|
+
self._errorMsgLabel = qt.QLabel()
|
|
28
|
+
self._errorMsgLabel.setStyleSheet("color : red")
|
|
29
|
+
self._errorMsgLabel.setText(self._INVALID_INPUT_TXT)
|
|
30
|
+
self._errorMsgLabel.hide()
|
|
22
31
|
browseButton = qt.QPushButton("Browse...")
|
|
23
32
|
|
|
24
33
|
layout = qt.QHBoxLayout(self)
|
|
25
34
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
26
35
|
layout.addWidget(self._lineEdit)
|
|
27
36
|
layout.addWidget(browseButton)
|
|
37
|
+
layout.addWidget(self._errorMsgLabel)
|
|
28
38
|
|
|
29
39
|
browseButton.clicked.connect(self._openDialog)
|
|
30
|
-
self._lineEdit.editingFinished.connect(self.
|
|
40
|
+
self._lineEdit.editingFinished.connect(self._onEditFinished)
|
|
31
41
|
|
|
32
42
|
def _getDialogResult(self) -> str | None:
|
|
33
43
|
raise NotImplementedError()
|
|
34
44
|
|
|
45
|
+
def _isValid(self, result: str) -> bool:
|
|
46
|
+
raise NotImplementedError()
|
|
47
|
+
|
|
35
48
|
def _openDialog(self):
|
|
36
49
|
result = self._getDialogResult()
|
|
37
50
|
if not result:
|
|
38
51
|
return
|
|
39
52
|
|
|
40
53
|
self._lineEdit.setText(result)
|
|
41
|
-
|
|
54
|
+
|
|
55
|
+
if self.validateLineEdit():
|
|
56
|
+
self.dialogSelected.emit(result)
|
|
57
|
+
|
|
58
|
+
def _onEditFinished(self):
|
|
59
|
+
if self.validateLineEdit():
|
|
60
|
+
self.editingFinished.emit()
|
|
61
|
+
|
|
62
|
+
def validateLineEdit(self) -> bool:
|
|
63
|
+
isValid = self._isValid(self._lineEdit.text())
|
|
64
|
+
if isValid:
|
|
65
|
+
self._lineEdit.setStyleSheet(self._defaultLineEditStyle)
|
|
66
|
+
self._errorMsgLabel.hide()
|
|
67
|
+
else:
|
|
68
|
+
self._lineEdit.setStyleSheet(self._ERROR_LINE_EDIT_STYLE_SHEET)
|
|
69
|
+
self._errorMsgLabel.show()
|
|
70
|
+
|
|
71
|
+
return isValid
|
|
42
72
|
|
|
43
73
|
def setText(self, text: str):
|
|
44
74
|
self._lineEdit.setText(text)
|
|
75
|
+
self._onEditFinished()
|
|
45
76
|
|
|
46
77
|
def getText(self) -> str:
|
|
47
78
|
return self._lineEdit.text()
|
|
48
79
|
|
|
49
80
|
|
|
50
|
-
class
|
|
81
|
+
class H5FileLineEdit(_BaseLineEdit):
|
|
51
82
|
"""A line edit for file paths that can filled via a file selection dialog"""
|
|
52
83
|
|
|
53
|
-
|
|
54
|
-
editingFinished = qt.Signal()
|
|
84
|
+
_INVALID_INPUT_TXT = "File does not exist or is not a valid H5 file."
|
|
55
85
|
|
|
56
86
|
def _getDialogResult(self) -> None | str:
|
|
57
|
-
dialog = qt.QFileDialog()
|
|
87
|
+
dialog = qt.QFileDialog(filter="h5 file (*.h5 *.hdf *.hdf5 *.nx *.nxs)")
|
|
58
88
|
result = dialog.exec()
|
|
59
89
|
|
|
60
90
|
if not result:
|
|
61
91
|
return None
|
|
62
92
|
return dialog.selectedFiles()[0]
|
|
63
93
|
|
|
94
|
+
def _isValid(self, result: str) -> bool:
|
|
95
|
+
return h5py.is_hdf5(result)
|
|
96
|
+
|
|
64
97
|
|
|
65
98
|
class DatasetLineEdit(_BaseLineEdit):
|
|
66
99
|
"""
|
|
@@ -68,8 +101,7 @@ class DatasetLineEdit(_BaseLineEdit):
|
|
|
68
101
|
The file needs to be set beforehand with `setFile`
|
|
69
102
|
"""
|
|
70
103
|
|
|
71
|
-
|
|
72
|
-
editingFinished = qt.Signal()
|
|
104
|
+
_INVALID_INPUT_TXT = "Not a valid H5 dataset."
|
|
73
105
|
|
|
74
106
|
def __init__(self, parent: qt.QWidget | None = None, **kwargs) -> None:
|
|
75
107
|
super().__init__(parent, **kwargs)
|
|
@@ -91,6 +123,12 @@ class DatasetLineEdit(_BaseLineEdit):
|
|
|
91
123
|
url = dialog.getSelectedDataUrl()
|
|
92
124
|
return url.data_path() if url else None
|
|
93
125
|
|
|
126
|
+
def _isValid(self, result: str) -> bool:
|
|
127
|
+
if not h5py.is_hdf5(self._file):
|
|
128
|
+
return False
|
|
129
|
+
with h5py.File(self._file) as f:
|
|
130
|
+
return isinstance(f.get(result), h5py.Dataset)
|
|
131
|
+
|
|
94
132
|
|
|
95
133
|
class GroupLineEdit(_BaseLineEdit):
|
|
96
134
|
"""
|
|
@@ -98,6 +136,8 @@ class GroupLineEdit(_BaseLineEdit):
|
|
|
98
136
|
The file needs to be set beforehand with `setFile`
|
|
99
137
|
"""
|
|
100
138
|
|
|
139
|
+
_INVALID_INPUT_TXT = "Not a valid H5 group."
|
|
140
|
+
|
|
101
141
|
dialogSelected = qt.Signal(str)
|
|
102
142
|
editingFinished = qt.Signal()
|
|
103
143
|
|
|
@@ -120,3 +160,9 @@ class GroupLineEdit(_BaseLineEdit):
|
|
|
120
160
|
|
|
121
161
|
url = dialog.getSelectedDataUrl()
|
|
122
162
|
return url.data_path() if url else None
|
|
163
|
+
|
|
164
|
+
def _isValid(self, result: str) -> bool:
|
|
165
|
+
if not h5py.is_hdf5(self._file):
|
|
166
|
+
return False
|
|
167
|
+
with h5py.File(self._file) as f:
|
|
168
|
+
return isinstance(f.get(result), h5py.Group)
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
import os
|
|
5
4
|
|
|
6
5
|
import silx.io
|
|
7
|
-
from ewoksorange.gui.
|
|
6
|
+
from ewoksorange.gui.widgets.parameter_form import block_signals
|
|
8
7
|
from silx.gui import qt
|
|
9
8
|
|
|
10
9
|
from darfix.gui.data_selection.utils import find_detector_name
|
|
11
10
|
from darfix.gui.data_selection.utils import find_scan_names
|
|
12
|
-
from darfix.gui.utils.message import show_error_msg
|
|
13
11
|
|
|
14
12
|
from .line_edits import DatasetLineEdit
|
|
15
|
-
from .line_edits import FileLineEdit
|
|
16
13
|
from .line_edits import GroupLineEdit
|
|
14
|
+
from .line_edits import H5FileLineEdit
|
|
17
15
|
|
|
18
16
|
_logger = logging.getLogger(__file__)
|
|
19
17
|
|
|
@@ -25,10 +23,12 @@ class ScanSelectionWidget(qt.QWidget):
|
|
|
25
23
|
Autofills the detector path when the scan is updated.
|
|
26
24
|
"""
|
|
27
25
|
|
|
26
|
+
sigNewFileSelected = qt.Signal()
|
|
27
|
+
|
|
28
28
|
def __init__(self, parent: qt.QWidget | None = None, **kwargs) -> None:
|
|
29
29
|
super().__init__(parent=parent, **kwargs)
|
|
30
30
|
|
|
31
|
-
self._fileLineEdit =
|
|
31
|
+
self._fileLineEdit = H5FileLineEdit()
|
|
32
32
|
self._scanNameComboBox = qt.QComboBox()
|
|
33
33
|
self._detectorLineEdit = DatasetLineEdit()
|
|
34
34
|
|
|
@@ -44,10 +44,7 @@ class ScanSelectionWidget(qt.QWidget):
|
|
|
44
44
|
|
|
45
45
|
def _onNewFileEdit(self):
|
|
46
46
|
path = self._fileLineEdit.getText()
|
|
47
|
-
|
|
48
|
-
self._onNewFile(path)
|
|
49
|
-
else:
|
|
50
|
-
show_error_msg(f"File '{path}' does not exist")
|
|
47
|
+
self._onNewFile(path)
|
|
51
48
|
|
|
52
49
|
def _onNewFile(self, filePath: str):
|
|
53
50
|
self._detectorLineEdit.setFile(filePath)
|
|
@@ -61,6 +58,7 @@ class ScanSelectionWidget(qt.QWidget):
|
|
|
61
58
|
with block_signals(self._scanNameComboBox):
|
|
62
59
|
self._scanNameComboBox.clear()
|
|
63
60
|
self._scanNameComboBox.addItems(scanNames)
|
|
61
|
+
self.sigNewFileSelected.emit()
|
|
64
62
|
|
|
65
63
|
def _updateDetectorPath(self, scanNumber: str):
|
|
66
64
|
scanUrl = f"{self._fileLineEdit.getText()}::/{scanNumber}"
|
|
@@ -69,10 +67,13 @@ class ScanSelectionWidget(qt.QWidget):
|
|
|
69
67
|
|
|
70
68
|
if detectorName:
|
|
71
69
|
self._detectorLineEdit.setText(f"/{scanNumber}/measurement/{detectorName}")
|
|
70
|
+
else:
|
|
71
|
+
self._detectorLineEdit.setText("")
|
|
72
|
+
|
|
73
|
+
self._detectorLineEdit.validateLineEdit()
|
|
72
74
|
|
|
73
75
|
def setFilePath(self, file: str):
|
|
74
76
|
self._fileLineEdit.setText(file)
|
|
75
|
-
self._onNewFile(file)
|
|
76
77
|
|
|
77
78
|
def getFilePath(self) -> str:
|
|
78
79
|
return self._fileLineEdit.getText()
|
|
@@ -86,6 +87,12 @@ class ScanSelectionWidget(qt.QWidget):
|
|
|
86
87
|
def getDetectorPath(self) -> str:
|
|
87
88
|
return self._detectorLineEdit.getText()
|
|
88
89
|
|
|
90
|
+
def validateSelection(self) -> bool:
|
|
91
|
+
return (
|
|
92
|
+
self._fileLineEdit.validateLineEdit()
|
|
93
|
+
and self._detectorLineEdit.validateLineEdit()
|
|
94
|
+
)
|
|
95
|
+
|
|
89
96
|
|
|
90
97
|
class ScanSelectionWidgetWithPositioners(ScanSelectionWidget):
|
|
91
98
|
"""
|
|
@@ -103,14 +110,20 @@ class ScanSelectionWidgetWithPositioners(ScanSelectionWidget):
|
|
|
103
110
|
self._scanNameComboBox.currentTextChanged.connect(self._updatePositionersPath)
|
|
104
111
|
|
|
105
112
|
def _onNewFile(self, file_path: str):
|
|
106
|
-
super()._onNewFile(file_path)
|
|
107
113
|
self._positionersLineEdit.setFile(file_path)
|
|
114
|
+
super()._onNewFile(file_path)
|
|
108
115
|
|
|
109
116
|
def _updatePositionersPath(self, scan_number: str):
|
|
110
117
|
self._positionersLineEdit.setText(f"/{scan_number}/instrument/positioners")
|
|
118
|
+
self._positionersLineEdit.validateLineEdit()
|
|
111
119
|
|
|
112
120
|
def setPositionersPath(self, data_url: str):
|
|
113
121
|
self._positionersLineEdit.setText(data_url)
|
|
114
122
|
|
|
115
123
|
def getPositionersPath(self) -> str:
|
|
116
124
|
return self._positionersLineEdit.getText()
|
|
125
|
+
|
|
126
|
+
def validateSelection(self) -> bool:
|
|
127
|
+
return (
|
|
128
|
+
super().validateSelection() and self._positionersLineEdit.validateLineEdit()
|
|
129
|
+
)
|
|
@@ -39,6 +39,17 @@ def find_detector_name(scan: h5py.Group) -> str | None:
|
|
|
39
39
|
# Found the LIMA detector
|
|
40
40
|
return instrument_name
|
|
41
41
|
|
|
42
|
+
_logger.debug(
|
|
43
|
+
"Could not find a LIMA detector. Does this file have a NeXus Format ? Try to find any 3D dataset in measurement group."
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# If nothing found, try at least to find a 3D dataset in measurement (Required for concatenate scans file as it does not have a Nexus Format).
|
|
47
|
+
for measurement_name, measurement in scan.get("measurement", {}).items():
|
|
48
|
+
if not isinstance(measurement, h5py.Dataset):
|
|
49
|
+
continue
|
|
50
|
+
if measurement.ndim == 3:
|
|
51
|
+
return measurement_name
|
|
52
|
+
|
|
42
53
|
_logger.warning(
|
|
43
54
|
f"Could not find valid detector in {scan.file}::{instrument_group.name} among {tuple(instrument_group.keys())}"
|
|
44
55
|
)
|
|
@@ -12,23 +12,23 @@ class WorkingDirSelectionWidget(qt.QWidget):
|
|
|
12
12
|
Widget used to obtain a directory name
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
dirChanged = qt.Signal()
|
|
16
|
-
|
|
17
15
|
def __init__(self, parent=None):
|
|
18
16
|
qt.QWidget.__init__(self, parent)
|
|
19
17
|
|
|
20
|
-
self.
|
|
21
|
-
self._dir.editingFinished.connect(self.dirChanged)
|
|
18
|
+
self._directoryLineEdit = qt.QLineEdit("", parent=self)
|
|
22
19
|
self.completer = create_completer()
|
|
23
|
-
self.
|
|
20
|
+
self._directoryLineEdit.setCompleter(self.completer)
|
|
24
21
|
|
|
25
22
|
self._addButton = qt.QPushButton("Select working directory", parent=self)
|
|
26
|
-
self._addButton.pressed.connect(self._selectWorkingDirectory)
|
|
27
23
|
self.setLayout(qt.QHBoxLayout())
|
|
28
24
|
|
|
29
|
-
self.layout().addWidget(self.
|
|
25
|
+
self.layout().addWidget(self._directoryLineEdit)
|
|
30
26
|
self.layout().addWidget(self._addButton)
|
|
31
27
|
|
|
28
|
+
# Connect Signals / Slots
|
|
29
|
+
|
|
30
|
+
self._addButton.pressed.connect(self._selectWorkingDirectory)
|
|
31
|
+
|
|
32
32
|
def _selectWorkingDirectory(self):
|
|
33
33
|
"""
|
|
34
34
|
Select a folder to be used as working directory (task results will be saved at this location)
|
|
@@ -37,14 +37,15 @@ class WorkingDirSelectionWidget(qt.QWidget):
|
|
|
37
37
|
fileDialog.setOption(qt.QFileDialog.ShowDirsOnly)
|
|
38
38
|
fileDialog.setFileMode(qt.QFileDialog.Directory)
|
|
39
39
|
if fileDialog.exec():
|
|
40
|
-
self.
|
|
41
|
-
self.dirChanged.emit()
|
|
40
|
+
self._directoryLineEdit.setText(fileDialog.directory().absolutePath())
|
|
42
41
|
else:
|
|
43
42
|
_logger.warning("Could not open directory")
|
|
44
43
|
|
|
45
|
-
def getDir(self):
|
|
46
|
-
return str(self.
|
|
44
|
+
def getDir(self) -> str:
|
|
45
|
+
return str(self._directoryLineEdit.text())
|
|
46
|
+
|
|
47
|
+
def setDir(self, working_directory: str):
|
|
48
|
+
self._directoryLineEdit.setText(str(working_directory))
|
|
47
49
|
|
|
48
|
-
def
|
|
49
|
-
self.
|
|
50
|
-
self.dirChanged.emit()
|
|
50
|
+
def setDefaultDir(self, default_dir: str):
|
|
51
|
+
self._directoryLineEdit.setPlaceholderText(default_dir + " (default)")
|
|
@@ -6,7 +6,7 @@ import numpy
|
|
|
6
6
|
from silx.gui import qt
|
|
7
7
|
|
|
8
8
|
from darfix.core.dimension import Dimension
|
|
9
|
-
from darfix.tasks.
|
|
9
|
+
from darfix.tasks.dimension_definition import DimensionDefinition
|
|
10
10
|
|
|
11
11
|
_logger = logging.getLogger(__file__)
|
|
12
12
|
|
|
@@ -13,7 +13,7 @@ from silx.gui.plot import StackView
|
|
|
13
13
|
import darfix
|
|
14
14
|
from darfix.io.utils import write_components
|
|
15
15
|
|
|
16
|
-
from .
|
|
16
|
+
from .choose_dimensions import ChooseDimensionDock
|
|
17
17
|
from .utils.utils import select_output_hdf5_file_with_dialog
|
|
18
18
|
|
|
19
19
|
|
|
@@ -2,12 +2,12 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from functools import partial
|
|
4
4
|
|
|
5
|
-
from ewoksorange.gui.
|
|
5
|
+
from ewoksorange.gui.widgets.parameter_form import block_signals
|
|
6
6
|
from silx.gui import qt
|
|
7
7
|
|
|
8
8
|
from darfix.core.dimension import AcquisitionDims
|
|
9
9
|
from darfix.core.dimension import Dimension
|
|
10
|
-
from darfix.gui.utils.
|
|
10
|
+
from darfix.gui.utils.range_slider import RangeSliderWithSpinBox
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class _DimensionRangeSlider(qt.QWidget):
|
|
@@ -12,7 +12,7 @@ from darfix.core.moment_types import MomentType
|
|
|
12
12
|
from ...core.grainplot import GrainPlotMaps
|
|
13
13
|
from ...core.grainplot import generate_grain_maps_nxdict
|
|
14
14
|
from ..utils.utils import select_output_hdf5_file_with_dialog
|
|
15
|
-
from .
|
|
15
|
+
from .mosaicity_widget import MosaicityWidget
|
|
16
16
|
from .utils import MapType
|
|
17
17
|
from .utils import add_image_with_transformation
|
|
18
18
|
|