summaryrefslogtreecommitdiff
path: root/silx/gui/plot/PlotWindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/PlotWindow.py')
-rw-r--r--silx/gui/plot/PlotWindow.py193
1 files changed, 126 insertions, 67 deletions
diff --git a/silx/gui/plot/PlotWindow.py b/silx/gui/plot/PlotWindow.py
index ae25cfd..a23db04 100644
--- a/silx/gui/plot/PlotWindow.py
+++ b/silx/gui/plot/PlotWindow.py
@@ -25,26 +25,30 @@
"""A :class:`.PlotWidget` with additional toolbars.
The :class:`PlotWindow` is a subclass of :class:`.PlotWidget`.
-It provides the plot API fully defined in :class:`.Plot`.
"""
__authors__ = ["V.A. Sole", "T. Vincent"]
__license__ = "MIT"
-__date__ = "27/04/2017"
+__date__ = "17/08/2017"
import collections
import logging
-from silx.utils.decorators import deprecated
+from silx.utils.deprecation import deprecated
from . import PlotWidget
-from . import PlotActions
+from . import actions
+from . import items
+from .actions import medfilt as actions_medfilt
+from .actions import fit as actions_fit
+from .actions import histogram as actions_histogram
from . import PlotToolButtons
from .PlotTools import PositionInfo
from .Profile import ProfileToolBar
from .LegendSelector import LegendsDockWidget
from .CurvesROIWidget import CurvesROIDockWidget
from .MaskToolsWidget import MaskToolsDockWidget
+from .ColorBar import ColorBarWidget
try:
from ..console import IPythonDockWidget
except ImportError:
@@ -65,7 +69,7 @@ class PlotWindow(PlotWidget):
:param parent: The parent of this widget or None.
:param backend: The backend to use for the plot (default: matplotlib).
- See :class:`.Plot` for the list of supported backend.
+ See :class:`.PlotWidget` for the list of supported backend.
:type backend: str or :class:`BackendBase.BackendBase`
:param bool resetzoom: Toggle visibility of reset zoom action.
:param bool autoScale: Toggle visibility of axes autoscale actions.
@@ -113,46 +117,54 @@ class PlotWindow(PlotWidget):
self.group = qt.QActionGroup(self)
self.group.setExclusive(False)
- self.resetZoomAction = self.group.addAction(PlotActions.ResetZoomAction(self))
+ self.zoomModeAction = self.group.addAction(
+ actions.mode.ZoomModeAction(self))
+ self.panModeAction = self.group.addAction(
+ actions.mode.PanModeAction(self))
+
+ self.resetZoomAction = self.group.addAction(
+ actions.control.ResetZoomAction(self))
self.resetZoomAction.setVisible(resetzoom)
self.addAction(self.resetZoomAction)
- self.zoomInAction = PlotActions.ZoomInAction(self)
+ self.zoomInAction = actions.control.ZoomInAction(self)
self.addAction(self.zoomInAction)
- self.zoomOutAction = PlotActions.ZoomOutAction(self)
+ self.zoomOutAction = actions.control.ZoomOutAction(self)
self.addAction(self.zoomOutAction)
self.xAxisAutoScaleAction = self.group.addAction(
- PlotActions.XAxisAutoScaleAction(self))
+ actions.control.XAxisAutoScaleAction(self))
self.xAxisAutoScaleAction.setVisible(autoScale)
self.addAction(self.xAxisAutoScaleAction)
self.yAxisAutoScaleAction = self.group.addAction(
- PlotActions.YAxisAutoScaleAction(self))
+ actions.control.YAxisAutoScaleAction(self))
self.yAxisAutoScaleAction.setVisible(autoScale)
self.addAction(self.yAxisAutoScaleAction)
self.xAxisLogarithmicAction = self.group.addAction(
- PlotActions.XAxisLogarithmicAction(self))
+ actions.control.XAxisLogarithmicAction(self))
self.xAxisLogarithmicAction.setVisible(logScale)
self.addAction(self.xAxisLogarithmicAction)
self.yAxisLogarithmicAction = self.group.addAction(
- PlotActions.YAxisLogarithmicAction(self))
+ actions.control.YAxisLogarithmicAction(self))
self.yAxisLogarithmicAction.setVisible(logScale)
self.addAction(self.yAxisLogarithmicAction)
self.gridAction = self.group.addAction(
- PlotActions.GridAction(self, gridMode='both'))
+ actions.control.GridAction(self, gridMode='both'))
self.gridAction.setVisible(grid)
self.addAction(self.gridAction)
- self.curveStyleAction = self.group.addAction(PlotActions.CurveStyleAction(self))
+ self.curveStyleAction = self.group.addAction(
+ actions.control.CurveStyleAction(self))
self.curveStyleAction.setVisible(curveStyle)
self.addAction(self.curveStyleAction)
- self.colormapAction = self.group.addAction(PlotActions.ColormapAction(self))
+ self.colormapAction = self.group.addAction(
+ actions.control.ColormapAction(self))
self.colormapAction.setVisible(colormap)
self.addAction(self.colormapAction)
@@ -171,34 +183,34 @@ class PlotWindow(PlotWidget):
self.getMaskAction().setVisible(mask)
self._intensityHistoAction = self.group.addAction(
- PlotActions.PixelIntensitiesHistoAction(self))
+ actions_histogram.PixelIntensitiesHistoAction(self))
self._intensityHistoAction.setVisible(False)
self._medianFilter2DAction = self.group.addAction(
- PlotActions.MedianFilter2DAction(self))
+ actions_medfilt.MedianFilter2DAction(self))
self._medianFilter2DAction.setVisible(False)
self._medianFilter1DAction = self.group.addAction(
- PlotActions.MedianFilter1DAction(self))
+ actions_medfilt.MedianFilter1DAction(self))
self._medianFilter1DAction.setVisible(False)
self._separator = qt.QAction('separator', self)
self._separator.setSeparator(True)
self.group.addAction(self._separator)
- self.copyAction = self.group.addAction(PlotActions.CopyAction(self))
+ self.copyAction = self.group.addAction(actions.io.CopyAction(self))
self.copyAction.setVisible(copy)
self.addAction(self.copyAction)
- self.saveAction = self.group.addAction(PlotActions.SaveAction(self))
+ self.saveAction = self.group.addAction(actions.io.SaveAction(self))
self.saveAction.setVisible(save)
self.addAction(self.saveAction)
- self.printAction = self.group.addAction(PlotActions.PrintAction(self))
+ self.printAction = self.group.addAction(actions.io.PrintAction(self))
self.printAction.setVisible(print_)
self.addAction(self.printAction)
- self.fitAction = self.group.addAction(PlotActions.FitAction(self))
+ self.fitAction = self.group.addAction(actions_fit.FitAction(self))
self.fitAction.setVisible(fit)
self.addAction(self.fitAction)
@@ -207,6 +219,28 @@ class PlotWindow(PlotWidget):
self._panWithArrowKeysAction = None
self._crosshairAction = None
+ # Create color bar, hidden by default for backward compatibility
+ self._colorbar = ColorBarWidget(parent=self, plot=self)
+ self._colorbar.setVisible(False)
+
+ # Make colorbar background white
+ self._colorbar.setAutoFillBackground(True)
+ palette = self._colorbar.palette()
+ palette.setColor(qt.QPalette.Background, qt.Qt.white)
+ palette.setColor(qt.QPalette.Window, qt.Qt.white)
+ self._colorbar.setPalette(palette)
+
+ gridLayout = qt.QGridLayout()
+ gridLayout.setSpacing(0)
+ gridLayout.setContentsMargins(0, 0, 0, 0)
+ gridLayout.addWidget(self.getWidgetHandle(), 0, 0)
+ gridLayout.addWidget(self._colorbar, 0, 1)
+ gridLayout.setRowStretch(0, 1)
+ gridLayout.setColumnStretch(0, 1)
+ centralWidget = qt.QWidget()
+ centralWidget.setLayout(gridLayout)
+ self.setCentralWidget(centralWidget)
+
if control or position:
hbox = qt.QHBoxLayout()
hbox.setContentsMargins(0, 0, 0, 0)
@@ -239,16 +273,7 @@ class PlotWindow(PlotWidget):
bottomBar = qt.QWidget()
bottomBar.setLayout(hbox)
- layout = qt.QVBoxLayout()
- layout.setSpacing(0)
- layout.setContentsMargins(0, 0, 0, 0)
- layout.addWidget(self.getWidgetHandle())
- layout.addWidget(bottomBar)
- layout.setStretch(0, 1)
-
- centralWidget = qt.QWidget()
- centralWidget.setLayout(layout)
- self.setCentralWidget(centralWidget)
+ gridLayout.addWidget(bottomBar, 1, 0, 1, -1)
# Creating the toolbar also create actions for toolbuttons
self._toolbar = self._createToolBar(title='Plot', parent=None)
@@ -322,6 +347,8 @@ class PlotWindow(PlotWidget):
self.yAxisInvertedAction = toolbar.addWidget(obj)
else:
raise RuntimeError()
+ if obj is self.panModeAction:
+ toolbar.addSeparator()
return toolbar
def toolBar(self):
@@ -378,6 +405,13 @@ class PlotWindow(PlotWidget):
self.tabifyDockWidget(self._dockWidgets[0],
dock_widget)
+ def getColorBarWidget(self):
+ """Returns the embedded :class:`ColorBarWidget` widget.
+
+ :rtype: ColorBarWidget
+ """
+ return self._colorbar
+
# getters for dock widgets
@property
@deprecated(replacement="getLegendsDockWidget()", since_version="0.4.0")
@@ -464,10 +498,10 @@ class PlotWindow(PlotWidget):
def getCrosshairAction(self):
"""Action toggling crosshair cursor mode.
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
if self._crosshairAction is None:
- self._crosshairAction = PlotActions.CrosshairAction(self, color='red')
+ self._crosshairAction = actions.control.CrosshairAction(self, color='red')
return self._crosshairAction
@property
@@ -491,10 +525,10 @@ class PlotWindow(PlotWidget):
def getPanWithArrowKeysAction(self):
"""Action toggling pan with arrow keys.
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
if self._panWithArrowKeysAction is None:
- self._panWithArrowKeysAction = PlotActions.PanWithArrowKeysAction(self)
+ self._panWithArrowKeysAction = actions.control.PanWithArrowKeysAction(self)
return self._panWithArrowKeysAction
@property
@@ -512,63 +546,63 @@ class PlotWindow(PlotWidget):
def getResetZoomAction(self):
"""Action resetting the zoom
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.resetZoomAction
def getZoomInAction(self):
"""Action to zoom in
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.zoomInAction
def getZoomOutAction(self):
"""Action to zoom out
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.zoomOutAction
def getXAxisAutoScaleAction(self):
"""Action to toggle the X axis autoscale on zoom reset
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.xAxisAutoScaleAction
def getYAxisAutoScaleAction(self):
"""Action to toggle the Y axis autoscale on zoom reset
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.yAxisAutoScaleAction
def getXAxisLogarithmicAction(self):
"""Action to toggle logarithmic X axis
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.xAxisLogarithmicAction
def getYAxisLogarithmicAction(self):
"""Action to toggle logarithmic Y axis
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.yAxisLogarithmicAction
def getGridAction(self):
"""Action to toggle the grid visibility in the plot
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.gridAction
def getCurveStyleAction(self):
"""Action to change curve line and markers styles
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.curveStyleAction
@@ -576,7 +610,7 @@ class PlotWindow(PlotWidget):
"""Action open a colormap dialog to change active image
and default colormap.
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.colormapAction
@@ -592,7 +626,7 @@ class PlotWindow(PlotWidget):
Use this to change the visibility of keepDataAspectRatioButton in the
toolbar (See :meth:`QToolBar.addWidget` documentation).
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.keepDataAspectRatioButton
@@ -608,56 +642,56 @@ class PlotWindow(PlotWidget):
Use this to change the visibility yAxisInvertedButton in the toolbar.
(See :meth:`QToolBar.addWidget` documentation).
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.yAxisInvertedAction
def getIntensityHistogramAction(self):
"""Action toggling the histogram intensity Plot widget
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self._intensityHistoAction
def getCopyAction(self):
"""Action to copy plot snapshot to clipboard
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.copyAction
def getSaveAction(self):
"""Action to save plot
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.saveAction
def getPrintAction(self):
"""Action to print plot
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.printAction
def getFitAction(self):
"""Action to fit selected curve
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self.fitAction
def getMedianFilter1DAction(self):
"""Action toggling the 1D median filter
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self._medianFilter1DAction
def getMedianFilter2DAction(self):
"""Action toggling the 2D median filter
- :rtype: PlotActions.PlotAction
+ :rtype: actions.PlotAction
"""
return self._medianFilter2DAction
@@ -669,7 +703,7 @@ class Plot1D(PlotWindow):
:param parent: The parent of this widget
:param backend: The backend to use for the plot (default: matplotlib).
- See :class:`.Plot` for the list of supported backend.
+ See :class:`.PlotWidget` for the list of supported backend.
:type backend: str or :class:`BackendBase.BackendBase`
"""
@@ -684,8 +718,8 @@ class Plot1D(PlotWindow):
roi=True, mask=False, fit=True)
if parent is None:
self.setWindowTitle('Plot1D')
- self.setGraphXLabel('X')
- self.setGraphYLabel('Y')
+ self.getXAxis().setLabel('X')
+ self.getYAxis().setLabel('Y')
class Plot2D(PlotWindow):
@@ -695,7 +729,7 @@ class Plot2D(PlotWindow):
:param parent: The parent of this widget
:param backend: The backend to use for the plot (default: matplotlib).
- See :class:`.Plot` for the list of supported backend.
+ See :class:`.PlotWidget` for the list of supported backend.
:type backend: str or :class:`BackendBase.BackendBase`
"""
@@ -716,26 +750,44 @@ class Plot2D(PlotWindow):
roi=False, mask=True)
if parent is None:
self.setWindowTitle('Plot2D')
- self.setGraphXLabel('Columns')
- self.setGraphYLabel('Rows')
+ self.getXAxis().setLabel('Columns')
+ self.getYAxis().setLabel('Rows')
self.profile = ProfileToolBar(plot=self)
-
self.addToolBar(self.profile)
+ self.getColorBarWidget().setVisible(True)
+
+ # Put colorbar action after colormap action
+ actions = self.toolBar().actions()
+ for index, action in enumerate(actions):
+ if action is self.getColormapAction():
+ break
+ self.toolBar().insertAction(
+ actions[index + 1],
+ self.getColorBarWidget().getToggleViewAction())
+
def _getImageValue(self, x, y):
- """Get value of top most image at position (x, y)
+ """Get status bar value of top most image at position (x, y)
:param float x: X position in plot coordinates
:param float y: Y position in plot coordinates
:return: The value at that point or '-'
"""
value = '-'
- valueZ = - float('inf')
+ valueZ = -float('inf')
+ mask = 0
+ maskZ = -float('inf')
for image in self.getAllImages():
data = image.getData(copy=False)
- if image.getZValue() >= valueZ: # This image is over the previous one
+ isMask = isinstance(image, items.MaskImageData)
+ if isMask:
+ zIndex = maskZ
+ else:
+ zIndex = valueZ
+ if image.getZValue() >= zIndex:
+ # This image is over the previous one
ox, oy = image.getOrigin()
sx, sy = image.getScale()
row, col = (y - oy) / sy, (x - ox) / sx
@@ -743,8 +795,15 @@ class Plot2D(PlotWindow):
# Test positive before cast otherwise issue with int(-0.5) = 0
row, col = int(row), int(col)
if (row < data.shape[0] and col < data.shape[1]):
- value = data[row, col]
- valueZ = image.getZValue()
+ v, z = data[row, col], image.getZValue()
+ if not isMask:
+ value = v
+ valueZ = z
+ else:
+ mask = v
+ maskZ = z
+ if maskZ > valueZ and mask > 0:
+ return value, "Masked"
return value
def getProfileToolbar(self):