summaryrefslogtreecommitdiff
path: root/silx/gui/plot/ImageView.py
diff options
context:
space:
mode:
authorPicca Frédéric-Emmanuel <picca@debian.org>2017-10-07 07:59:01 +0200
committerPicca Frédéric-Emmanuel <picca@debian.org>2017-10-07 07:59:01 +0200
commitbfa4dba15485b4192f8bbe13345e9658c97ecf76 (patch)
treefb9c6e5860881fbde902f7cbdbd41dc4a3a9fb5d /silx/gui/plot/ImageView.py
parentf7bdc2acff3c13a6d632c28c4569690ab106eed7 (diff)
New upstream version 0.6.0+dfsg
Diffstat (limited to 'silx/gui/plot/ImageView.py')
-rw-r--r--silx/gui/plot/ImageView.py157
1 files changed, 82 insertions, 75 deletions
diff --git a/silx/gui/plot/ImageView.py b/silx/gui/plot/ImageView.py
index 780215e..803a2fc 100644
--- a/silx/gui/plot/ImageView.py
+++ b/silx/gui/plot/ImageView.py
@@ -34,12 +34,7 @@ Basic usage of :class:`ImageView` is through the following methods:
default colormap to use and update the currently displayed image.
- :meth:`ImageView.setImage` to update the displayed image.
-The :class:`ImageView` uses :class:`PlotWindow` and also
-exposes :class:`silx.gui.plot.Plot` API for further control
-(plot title, axes labels, adding other images, ...).
-
-For an example of use, see the implementation of :class:`ImageViewMainWindow`,
-and `example/imageview.py`.
+For an example of use, see `imageview.py` in :ref:`sample-code`.
"""
from __future__ import division
@@ -47,7 +42,7 @@ from __future__ import division
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "13/10/2016"
+__date__ = "17/08/2017"
import logging
@@ -55,7 +50,8 @@ import numpy
from .. import qt
-from . import items, PlotWindow, PlotWidget, PlotActions
+from . import items, PlotWindow, PlotWidget, actions
+from .Colormap import Colormap
from .Colors import cursorColorForColormap
from .PlotTools import LimitsToolBar
from .Profile import ProfileToolBar
@@ -253,9 +249,13 @@ class ImageView(PlotWindow):
Use :meth:`setImage` to control the displayed image.
This class also provides the :class:`silx.gui.plot.Plot` API.
+ The :class:`ImageView` inherits from :class:`.PlotWindow` (which provides
+ the toolbars) and also exposes :class:`.PlotWidget` API for further
+ plot control (plot title, axes labels, aspect ratio, ...).
+
: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`
"""
@@ -318,7 +318,7 @@ class ImageView(PlotWindow):
self._histoHPlot = PlotWidget(backend=backend)
self._histoHPlot.setInteractiveMode('zoom')
- self._histoHPlot.setCallback(self._histoHPlotCB)
+ self._histoHPlot.sigPlotSignal.connect(self._histoHPlotCB)
self._histoHPlot.getWidgetHandle().sizeHint = sizeHint
self._histoHPlot.getWidgetHandle().minimumSizeHint = sizeHint
@@ -326,39 +326,39 @@ class ImageView(PlotWindow):
self.setInteractiveMode('zoom') # Color set in setColormap
self.sigPlotSignal.connect(self._imagePlotCB)
- self.sigSetYAxisInverted.connect(self._updateYAxisInverted)
+ self.getYAxis().sigInvertedChanged.connect(self._updateYAxisInverted)
self.sigActiveImageChanged.connect(self._activeImageChangedSlot)
self._histoVPlot = PlotWidget(backend=backend)
self._histoVPlot.setInteractiveMode('zoom')
- self._histoVPlot.setCallback(self._histoVPlotCB)
+ self._histoVPlot.sigPlotSignal.connect(self._histoVPlotCB)
self._histoVPlot.getWidgetHandle().sizeHint = sizeHint
self._histoVPlot.getWidgetHandle().minimumSizeHint = sizeHint
self._radarView = RadarView()
self._radarView.visibleRectDragged.connect(self._radarViewCB)
- self._layout = qt.QGridLayout()
- self._layout.addWidget(self.getWidgetHandle(), 0, 0)
- self._layout.addWidget(self._histoVPlot.getWidgetHandle(), 0, 1)
- self._layout.addWidget(self._histoHPlot.getWidgetHandle(), 1, 0)
- self._layout.addWidget(self._radarView, 1, 1)
+ layout = qt.QGridLayout()
+ layout.addWidget(self.getWidgetHandle(), 0, 0)
+ layout.addWidget(self._histoVPlot.getWidgetHandle(), 0, 1)
+ layout.addWidget(self._histoHPlot.getWidgetHandle(), 1, 0)
+ layout.addWidget(self._radarView, 1, 1)
- self._layout.setColumnMinimumWidth(0, self.IMAGE_MIN_SIZE)
- self._layout.setColumnStretch(0, 1)
- self._layout.setColumnMinimumWidth(1, self.HISTOGRAMS_HEIGHT)
- self._layout.setColumnStretch(1, 0)
+ layout.setColumnMinimumWidth(0, self.IMAGE_MIN_SIZE)
+ layout.setColumnStretch(0, 1)
+ layout.setColumnMinimumWidth(1, self.HISTOGRAMS_HEIGHT)
+ layout.setColumnStretch(1, 0)
- self._layout.setRowMinimumHeight(0, self.IMAGE_MIN_SIZE)
- self._layout.setRowStretch(0, 1)
- self._layout.setRowMinimumHeight(1, self.HISTOGRAMS_HEIGHT)
- self._layout.setRowStretch(1, 0)
+ layout.setRowMinimumHeight(0, self.IMAGE_MIN_SIZE)
+ layout.setRowStretch(0, 1)
+ layout.setRowMinimumHeight(1, self.HISTOGRAMS_HEIGHT)
+ layout.setRowStretch(1, 0)
- self._layout.setSpacing(0)
- self._layout.setContentsMargins(0, 0, 0, 0)
+ layout.setSpacing(0)
+ layout.setContentsMargins(0, 0, 0, 0)
centralWidget = qt.QWidget()
- centralWidget.setLayout(self._layout)
+ centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
def _dirtyCache(self):
@@ -376,8 +376,8 @@ class ImageView(PlotWindow):
scale = activeImage.getScale()
height, width = data.shape
- xMin, xMax = self.getGraphXLimits()
- yMin, yMax = self.getGraphYLimits()
+ xMin, xMax = self.getXAxis().getLimits()
+ yMin, yMax = self.getYAxis().getLimits()
# Convert plot area limits to image coordinates
# and work in image coordinates (i.e., in pixels)
@@ -440,8 +440,8 @@ class ImageView(PlotWindow):
vOffset = 0.1 * (vMax - vMin)
if vOffset == 0.:
vOffset = 1.
- self._histoHPlot.setGraphYLimits(vMin - vOffset,
- vMax + vOffset)
+ self._histoHPlot.getYAxis().setLimits(vMin - vOffset,
+ vMax + vOffset)
coords = numpy.arange(2 * histoVVisibleData.size)
yCoords = (coords + 1) // 2 + subsetYMin
@@ -458,8 +458,8 @@ class ImageView(PlotWindow):
vOffset = 0.1 * (vMax - vMin)
if vOffset == 0.:
vOffset = 1.
- self._histoVPlot.setGraphXLimits(vMin - vOffset,
- vMax + vOffset)
+ self._histoVPlot.getXAxis().setLimits(vMin - vOffset,
+ vMax + vOffset)
else:
self._dirtyCache()
self._histoHPlot.remove(kind='curve')
@@ -472,8 +472,8 @@ class ImageView(PlotWindow):
Takes care of y coordinate conversion.
"""
- xMin, xMax = self.getGraphXLimits()
- yMin, yMax = self.getGraphYLimits()
+ xMin, xMax = self.getXAxis().getLimits()
+ yMin, yMax = self.getYAxis().getLimits()
self._radarView.setVisibleRect(xMin, yMin, xMax - xMin, yMax - yMin)
# Plots event listeners
@@ -499,6 +499,9 @@ class ImageView(PlotWindow):
data[y][x])
elif eventDict['event'] == 'limitsChanged':
+ self._updateHistogramsLimits()
+
+ def _updateHistogramsLimits(self):
# Do not handle histograms limitsChanged while
# updating their limits from here.
self._updatingLimits = True
@@ -506,15 +509,14 @@ class ImageView(PlotWindow):
# Refresh histograms
self._updateHistograms()
- # could use eventDict['xdata'], eventDict['ydata'] instead
- xMin, xMax = self.getGraphXLimits()
- yMin, yMax = self.getGraphYLimits()
+ xMin, xMax = self.getXAxis().getLimits()
+ yMin, yMax = self.getYAxis().getLimits()
# Set horizontal histo limits
- self._histoHPlot.setGraphXLimits(xMin, xMax)
+ self._histoHPlot.getXAxis().setLimits(xMin, xMax)
# Set vertical histo limits
- self._histoVPlot.setGraphYLimits(yMin, yMax)
+ self._histoVPlot.getYAxis().setLimits(yMin, yMax)
self._updateRadarView()
@@ -542,9 +544,9 @@ class ImageView(PlotWindow):
elif eventDict['event'] == 'limitsChanged':
if (not self._updatingLimits and
- eventDict['xdata'] != self.getGraphXLimits()):
+ eventDict['xdata'] != self.getXAxis().getLimits()):
xMin, xMax = eventDict['xdata']
- self.setGraphXLimits(xMin, xMax)
+ self.getXAxis().setLimits(xMin, xMax)
def _histoVPlotCB(self, eventDict):
"""Callback for vertical histogram plot events."""
@@ -568,9 +570,9 @@ class ImageView(PlotWindow):
elif eventDict['event'] == 'limitsChanged':
if (not self._updatingLimits and
- eventDict['ydata'] != self.getGraphYLimits()):
+ eventDict['ydata'] != self.getYAxis().getLimits()):
yMin, yMax = eventDict['ydata']
- self.setGraphYLimits(yMin, yMax)
+ self.getYAxis().setLimits(yMin, yMax)
def _radarViewCB(self, left, top, width, height):
"""Slot for radar view visible rectangle changes."""
@@ -582,9 +584,9 @@ class ImageView(PlotWindow):
"""Sync image, vertical histogram and radar view axis orientation."""
if inverted is None:
# Do not perform this when called from plot signal
- inverted = self.isYAxisInverted()
+ inverted = self.getYAxis().isInverted()
- self._histoVPlot.setYAxisInverted(inverted)
+ self._histoVPlot.getYAxis().setInverted(inverted)
# Use scale to invert radarView
# RadarView default Y direction is from top to bottom
@@ -643,7 +645,7 @@ class ImageView(PlotWindow):
self._radarView.visibleRectDragged.disconnect(self._radarViewCB)
self._radarView = radarView
self._radarView.visibleRectDragged.connect(self._radarViewCB)
- self._layout.addWidget(self._radarView, 1, 1)
+ self.centralWidget().layout().addWidget(self._radarView, 1, 1)
self._updateYAxisInverted()
@@ -693,42 +695,46 @@ class ImageView(PlotWindow):
:param numpy.ndarray colors: Only used if name is None.
Custom colormap colors as Nx3 or Nx4 RGB or RGBA arrays
"""
- cmapDict = self.getDefaultColormap()
+ cmap = self.getDefaultColormap()
+
+ if isinstance(colormap, Colormap):
+ # Replace colormap
+ cmap = colormap
+
+ self.setDefaultColormap(cmap)
+
+ # Update active image colormap
+ activeImage = self.getActiveImage()
+ if isinstance(activeImage, items.ColormapMixIn):
+ activeImage.setColormap(cmap)
- if isinstance(colormap, dict):
+ elif isinstance(colormap, dict):
# Support colormap parameter as a dict
assert normalization is None
assert autoscale is None
assert vmin is None
assert vmax is None
assert colors is None
- for key, value in colormap.items():
- cmapDict[key] = value
+ cmap._setFromDict(colormap)
else:
if colormap is not None:
- cmapDict['name'] = colormap
+ cmap.setName(colormap)
if normalization is not None:
- cmapDict['normalization'] = normalization
- if autoscale is not None:
- cmapDict['autoscale'] = autoscale
- if vmin is not None:
- cmapDict['vmin'] = vmin
- if vmax is not None:
- cmapDict['vmax'] = vmax
+ cmap.setNormalization(normalization)
+ if autoscale:
+ cmap.setVRange(None, None)
+ else:
+ if vmin is not None:
+ cmap.setVMin(vmin)
+ if vmax is not None:
+ cmap.setVMax(vmax)
if colors is not None:
- cmapDict['colors'] = colors
+ cmap.setColormapLUT(colors)
- cursorColor = cursorColorForColormap(cmapDict['name'])
+ cursorColor = cursorColorForColormap(cmap.getName())
self.setInteractiveMode('zoom', color=cursorColor)
- self.setDefaultColormap(cmapDict)
-
- # Update active image colormap
- activeImage = self.getActiveImage()
- if isinstance(activeImage, items.ColormapMixIn):
- activeImage.setColormap(self.getColormap())
-
def setImage(self, image, origin=(0, 0), scale=(1., 1.),
copy=True, reset=True):
"""Set the image to display.
@@ -768,7 +774,7 @@ class ImageView(PlotWindow):
legend=self._imageLegend,
origin=origin, scale=scale,
colormap=self.getColormap(),
- replace=False)
+ replace=False, resetzoom=False)
self.setActiveImage(self._imageLegend)
self._updateHistograms()
@@ -779,6 +785,8 @@ class ImageView(PlotWindow):
if reset:
self.resetZoom()
+ else:
+ self._updateHistogramsLimits()
# ImageViewMainWindow #########################################################
@@ -793,8 +801,8 @@ class ImageViewMainWindow(ImageView):
super(ImageViewMainWindow, self).__init__(parent, backend)
self.setWindowFlags(qt.Qt.Window)
- self.setGraphXLabel('X')
- self.setGraphYLabel('Y')
+ self.getXAxis().setLabel('X')
+ self.getYAxis().setLabel('Y')
self.setGraphTitle('Image')
# Add toolbars and status bar
@@ -814,11 +822,10 @@ class ImageViewMainWindow(ImageView):
menu.addSeparator()
menu.addAction(self.resetZoomAction)
menu.addAction(self.colormapAction)
- menu.addAction(PlotActions.KeepAspectRatioAction(self, self))
- menu.addAction(PlotActions.YAxisInvertedAction(self, self))
+ menu.addAction(actions.control.KeepAspectRatioAction(self, self))
+ menu.addAction(actions.control.YAxisInvertedAction(self, self))
menu = self.menuBar().addMenu('Profile')
- menu.addAction(self.profile.browseAction)
menu.addAction(self.profile.hLineAction)
menu.addAction(self.profile.vLineAction)
menu.addAction(self.profile.lineAction)