diff options
Diffstat (limited to 'silx/gui/plot/_BaseMaskToolsWidget.py')
-rw-r--r-- | silx/gui/plot/_BaseMaskToolsWidget.py | 124 |
1 files changed, 64 insertions, 60 deletions
diff --git a/silx/gui/plot/_BaseMaskToolsWidget.py b/silx/gui/plot/_BaseMaskToolsWidget.py index 91bbe1c..35a48ae 100644 --- a/silx/gui/plot/_BaseMaskToolsWidget.py +++ b/silx/gui/plot/_BaseMaskToolsWidget.py @@ -27,17 +27,19 @@ """ from __future__ import division - __authors__ = ["T. Vincent", "P. Knobel"] __license__ = "MIT" -__date__ = "20/04/2017" +__date__ = "02/10/2017" import os import numpy from silx.gui import qt, icons +from silx.gui.widgets.FloatEdit import FloatEdit +from silx.gui.plot.Colormap import Colormap from silx.gui.plot.Colors import rgba +from .actions.mode import PanModeAction class BaseMask(qt.QObject): @@ -353,24 +355,38 @@ class BaseMaskToolsWidget(qt.QWidget): sigMaskChanged = qt.Signal() _maxLevelNumber = 255 - def __init__(self, parent=None, plot=None): + def __init__(self, parent=None, plot=None, mask=None): + """ + + :param parent: Parent QWidget + :param plot: Plot widget on which to operate + :param mask: Instance of subclass of :class:`BaseMask` + (e.g. :class:`ImageMask`) + """ + super(BaseMaskToolsWidget, self).__init__(parent) # register if the user as force a color for the corresponding mask level self._defaultColors = numpy.ones((self._maxLevelNumber + 1), dtype=numpy.bool) # overlays colors set by the user self._overlayColors = numpy.zeros((self._maxLevelNumber + 1, 3), dtype=numpy.float32) + # as parent have to be the first argument of the widget to fit + # QtDesigner need but here plot can't be None by default. + assert plot is not None self._plot = plot self._maskName = '__MASK_TOOLS_%d' % id(self) # Legend of the mask - self._colormap = { - 'name': None, - 'normalization': 'linear', - 'autoscale': False, - 'vmin': 0, 'vmax': self._maxLevelNumber, - 'colors': None} + self._colormap = Colormap(name="", + normalization='linear', + vmin=0, + vmax=self._maxLevelNumber, + colors=None) self._defaultOverlayColor = rgba('gray') # Color of the mask self._setMaskColors(1, 0.5) + if not isinstance(mask, BaseMask): + raise TypeError("mask is not an instance of BaseMask") + self._mask = mask + self._mask.sigChanged.connect(self._updatePlotMask) self._mask.sigChanged.connect(self._emitSigMaskChanged) @@ -378,12 +394,12 @@ class BaseMaskToolsWidget(qt.QWidget): self._lastPencilPos = None self._multipleMasks = 'exclusive' - super(BaseMaskToolsWidget, self).__init__(parent) - self._maskFileDir = qt.QDir.home().absolutePath() self.plot.sigInteractiveModeChanged.connect( self._interactiveModeChanged) + self._initWidgets() + def _emitSigMaskChanged(self): """Notify mask changes""" self.sigMaskChanged.emit() @@ -570,17 +586,10 @@ class BaseMaskToolsWidget(qt.QWidget): """Init drawing tools widgets""" layout = qt.QVBoxLayout() - # Draw tools - self.browseAction = qt.QAction( - icons.getQIcon('normal'), 'Browse', None) - self.browseAction.setShortcut(qt.QKeySequence(qt.Qt.Key_B)) - self.browseAction.setToolTip( - 'Disables drawing tools, enables zooming interaction mode' - ' <b>B</b>') - self.browseAction.setCheckable(True) - self.browseAction.triggered.connect(self._activeBrowseMode) + self.browseAction = PanModeAction(self.plot, self.plot) self.addAction(self.browseAction) + # Draw tools self.rectAction = qt.QAction( icons.getQIcon('shape-rectangle'), 'Rectangle selection', None) self.rectAction.setToolTip( @@ -608,23 +617,22 @@ class BaseMaskToolsWidget(qt.QWidget): 'Pencil tool: (Un)Mask using a pencil <b>P</b>') self.pencilAction.setCheckable(True) self.pencilAction.triggered.connect(self._activePencilMode) - self.addAction(self.polygonAction) + self.addAction(self.pencilAction) self.drawActionGroup = qt.QActionGroup(self) self.drawActionGroup.setExclusive(True) - self.drawActionGroup.addAction(self.browseAction) self.drawActionGroup.addAction(self.rectAction) self.drawActionGroup.addAction(self.polygonAction) self.drawActionGroup.addAction(self.pencilAction) - self.browseAction.setChecked(True) - - self.drawButtons = {} - for action in self.drawActionGroup.actions(): + actions = (self.browseAction, self.rectAction, + self.polygonAction, self.pencilAction) + drawButtons = [] + for action in actions: btn = qt.QToolButton() btn.setDefaultAction(action) - self.drawButtons[action.text()] = btn - container = self._hboxWidget(*self.drawButtons.values()) + drawButtons.append(btn) + container = self._hboxWidget(*drawButtons) layout.addWidget(container) # Mask/Unmask radio buttons @@ -644,10 +652,7 @@ class BaseMaskToolsWidget(qt.QWidget): self.maskStateWidget = self._hboxWidget(maskRadioBtn, unmaskRadioBtn) layout.addWidget(self.maskStateWidget) - # Connect mask state widget visibility with browse action - self.maskStateWidget.setHidden(self.browseAction.isChecked()) - self.browseAction.toggled[bool].connect( - self.maskStateWidget.setHidden) + self.maskStateWidget.setHidden(True) # Pencil settings self.pencilSetting = self._createPencilSettings(None) @@ -752,15 +757,11 @@ class BaseMaskToolsWidget(qt.QWidget): form = qt.QFormLayout() - self.minLineEdit = qt.QLineEdit() - self.minLineEdit.setText('0') - self.minLineEdit.setValidator(qt.QDoubleValidator()) + self.minLineEdit = FloatEdit(self, value=0) self.minLineEdit.setEnabled(False) form.addRow('Min:', self.minLineEdit) - self.maxLineEdit = qt.QLineEdit() - self.maxLineEdit.setText('0') - self.maxLineEdit.setValidator(qt.QDoubleValidator()) + self.maxLineEdit = FloatEdit(self, value=0) self.maxLineEdit.setEnabled(False) form.addRow('Max:', self.maxLineEdit) @@ -790,8 +791,9 @@ class BaseMaskToolsWidget(qt.QWidget): """Reset drawing action when disabling widget""" if (event.type() == qt.QEvent.EnabledChange and not self.isEnabled() and - not self.browseAction.isChecked()): - self.browseAction.trigger() # Disable drawing tool + self.drawActionGroup.checkedAction()): + # Disable drawing tool by setting interaction to zoom + self.browseAction.trigger() def save(self, filename, kind): """Save current mask in a file @@ -839,7 +841,7 @@ class BaseMaskToolsWidget(qt.QWidget): # Set no mask level colors[0] = (0., 0., 0., 0.) - self._colormap['colors'] = colors + self._colormap.setColormapLUT(colors) def resetMaskColors(self, level=None): """Reset the mask color at the given level to be defaultColors @@ -928,10 +930,11 @@ class BaseMaskToolsWidget(qt.QWidget): If changed from elsewhere, disable drawing tool """ if source is not self: - # Do not trigger browseAction to avoid to call - # self.plot.setInteractiveMode - self.browseAction.setChecked(True) + self.pencilAction.setChecked(False) + self.rectAction.setChecked(False) + self.polygonAction.setChecked(False) self._releaseDrawingMode() + self._updateDrawingModeWidgets() def _releaseDrawingMode(self): """Release the drawing mode if is was used""" @@ -940,16 +943,6 @@ class BaseMaskToolsWidget(qt.QWidget): self.plot.sigPlotSignal.disconnect(self._plotDrawEvent) self._drawingMode = None - def _activeBrowseMode(self): - """Handle browse action mode triggered by user. - - Set plot interactive mode only when - the user is triggering the browse action. - """ - self._releaseDrawingMode() - self.plot.setInteractiveMode('zoom', source=self) - self._updateDrawingModeWidgets() - def _activeRectMode(self): """Handle rect action mode triggering""" self._releaseDrawingMode() @@ -981,6 +974,7 @@ class BaseMaskToolsWidget(qt.QWidget): self._updateDrawingModeWidgets() def _updateDrawingModeWidgets(self): + self.maskStateWidget.setVisible(self._drawingMode is not None) self.pencilSetting.setVisible(self._drawingMode == 'pencil') # Handle plot drawing events @@ -1032,20 +1026,20 @@ class BaseMaskToolsWidget(qt.QWidget): if self.belowThresholdAction.isChecked(): if self.minLineEdit.text(): self._mask.updateBelowThreshold(self.levelSpinBox.value(), - float(self.minLineEdit.text())) + self.minLineEdit.value()) self._mask.commit() elif self.betweenThresholdAction.isChecked(): if self.minLineEdit.text() and self.maxLineEdit.text(): - min_ = float(self.minLineEdit.text()) - max_ = float(self.maxLineEdit.text()) + min_ = self.minLineEdit.value() + max_ = self.maxLineEdit.value() self._mask.updateBetweenThresholds(self.levelSpinBox.value(), min_, max_) self._mask.commit() elif self.aboveThresholdAction.isChecked(): if self.maxLineEdit.text(): - max_ = float(self.maxLineEdit.text()) + max_ = float(self.maxLineEdit.value()) self._mask.updateAboveThreshold(self.levelSpinBox.value(), max_) self._mask.commit() @@ -1059,7 +1053,7 @@ class BaseMaskToolsWidget(qt.QWidget): class BaseMaskToolsDockWidget(qt.QDockWidget): """Base class for :class:`MaskToolsWidget` and - :class:`ScatterMaskToolsWidget` + :class:`ScatterMaskToolsWidget`. For integration in a :class:`PlotWindow`. @@ -1069,10 +1063,15 @@ class BaseMaskToolsDockWidget(qt.QDockWidget): sigMaskChanged = qt.Signal() - def __init__(self, parent=None, name='Mask'): + def __init__(self, parent=None, name='Mask', widget=None): super(BaseMaskToolsDockWidget, self).__init__(parent) self.setWindowTitle(name) + if not isinstance(widget, BaseMaskToolsWidget): + raise TypeError("BaseMaskToolsDockWidget requires a MaskToolsWidget") + self.setWidget(widget) + self.widget().sigMaskChanged.connect(self._emitSigMaskChanged) + self.layout().setContentsMargins(0, 0, 0, 0) self.dockLocationChanged.connect(self._dockLocationChanged) self.topLevelChanged.connect(self._topLevelChanged) @@ -1107,6 +1106,11 @@ class BaseMaskToolsDockWidget(qt.QDockWidget): """ return self.widget().setSelectionMask(mask, copy=copy) + def resetSelectionMask(self): + """Reset the mask to an array of zeros with the shape of the + current data.""" + self.widget().resetSelectionMask() + def toggleViewAction(self): """Returns a checkable action that shows or closes this widget. |