summaryrefslogtreecommitdiff
path: root/silx/gui/plot/backends/BackendMatplotlib.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/backends/BackendMatplotlib.py')
-rw-r--r--silx/gui/plot/backends/BackendMatplotlib.py104
1 files changed, 78 insertions, 26 deletions
diff --git a/silx/gui/plot/backends/BackendMatplotlib.py b/silx/gui/plot/backends/BackendMatplotlib.py
index f9e60d5..59e753e 100644
--- a/silx/gui/plot/backends/BackendMatplotlib.py
+++ b/silx/gui/plot/backends/BackendMatplotlib.py
@@ -28,7 +28,7 @@ from __future__ import division
__authors__ = ["V.A. Sole", "T. Vincent, H. Payno"]
__license__ = "MIT"
-__date__ = "18/01/2017"
+__date__ = "16/08/2017"
import logging
@@ -41,7 +41,9 @@ _logger = logging.getLogger(__name__)
from ... import qt
-from ._matplotlib import FigureCanvasQTAgg
+# First of all init matplotlib and set its backend
+from ..matplotlib import Colormap as MPLColormap
+from ..matplotlib import FigureCanvasQTAgg
import matplotlib
from matplotlib.container import Container
from matplotlib.figure import Figure
@@ -51,9 +53,8 @@ from matplotlib.backend_bases import MouseEvent
from matplotlib.lines import Line2D
from matplotlib.collections import PathCollection, LineCollection
-from .ModestImage import ModestImage
+from ..matplotlib.ModestImage import ModestImage
from . import BackendBase
-from .. import Colors
from .._utils import FLOAT32_MINPOS
@@ -75,6 +76,7 @@ class BackendMatplotlib(BackendBase.BackendBase):
# This attribute is used to ensure consistent values returned
# when getting the limits at the expense of a replot
self._dirtyLimits = True
+ self._axesDisplayed = True
self.fig = Figure()
self.fig.set_facecolor("w")
@@ -83,6 +85,16 @@ class BackendMatplotlib(BackendBase.BackendBase):
self.ax2 = self.ax.twinx()
self.ax2.set_label("right")
+ # disable the use of offsets
+ try:
+ self.ax.get_yaxis().get_major_formatter().set_useOffset(False)
+ self.ax.get_xaxis().get_major_formatter().set_useOffset(False)
+ self.ax2.get_yaxis().get_major_formatter().set_useOffset(False)
+ self.ax2.get_xaxis().get_major_formatter().set_useOffset(False)
+ except:
+ _logger.warning('Cannot disabled axes offsets in %s ' \
+ % matplotlib.__version__)
+
# critical for picking!!!!
self.ax2.set_zorder(0)
self.ax2.set_autoscaley_on(True)
@@ -102,10 +114,6 @@ class BackendMatplotlib(BackendBase.BackendBase):
self._graphCursor = tuple()
self.matplotlibVersion = matplotlib.__version__
- self.setGraphXLimits(0., 100.)
- self.setGraphYLimits(0., 100., axis='right')
- self.setGraphYLimits(0., 100., axis='left')
-
self._enableAxis('right', False)
# Add methods
@@ -142,7 +150,7 @@ class BackendMatplotlib(BackendBase.BackendBase):
errorbarColor = color
# On Debian 7 at least, Nx1 array yerr does not seems supported
- if (yerror is not None and yerror.ndim == 2 and
+ if (isinstance(yerror, numpy.ndarray) and yerror.ndim == 2 and
yerror.shape[1] == 1 and len(x) != 1):
yerror = numpy.ravel(yerror)
@@ -226,17 +234,17 @@ class BackendMatplotlib(BackendBase.BackendBase):
# Add support for transparent colormap for uint8 data with
# colormap with 256 colors, linear norm, [0, 255] range
if matplotlib.__version__ < '1.2.0':
- if (len(data.shape) == 2 and colormap['name'] is None and
- 'colors' in colormap):
- colors = numpy.array(colormap['colors'], copy=False)
+ if (len(data.shape) == 2 and colormap.getName() is None and
+ colormap.getColormapLUT() is not None):
+ colors = colormap.getColormapLUT()
if (colors.shape[-1] == 4 and
not numpy.all(numpy.equal(colors[3], 255))):
# This is a transparent colormap
if (colors.shape == (256, 4) and
- colormap['normalization'] == 'linear' and
- not colormap['autoscale'] and
- colormap['vmin'] == 0 and
- colormap['vmax'] == 255 and
+ colormap.getNormalization() == 'linear' and
+ not colormap.isAutoscale() and
+ colormap.getVMin() == 0 and
+ colormap.getVMax() == 255 and
data.dtype == numpy.uint8):
# Supported case, convert data to RGBA
data = colors[data.reshape(-1)].reshape(
@@ -264,7 +272,7 @@ class BackendMatplotlib(BackendBase.BackendBase):
else:
# Convert colormap argument to matplotlib colormap
- scalarMappable = Colors.getMPLScalarMappable(colormap, data)
+ scalarMappable = MPLColormap.getScalarMappable(colormap, data)
# try as data
image = imageClass(self.ax,
@@ -440,7 +448,10 @@ class BackendMatplotlib(BackendBase.BackendBase):
item._infoText.remove()
item._infoText = None
self._overlays.discard(item)
- item.remove()
+ try:
+ item.remove()
+ except ValueError:
+ pass # Already removed e.g., in set[X|Y]AxisLogarithmic
# Interaction methods
@@ -591,10 +602,16 @@ class BackendMatplotlib(BackendBase.BackendBase):
# Graph axes
def setXAxisLogarithmic(self, flag):
+ if matplotlib.__version__ >= "2.0.0":
+ self.ax.cla()
+ self.ax2.cla()
self.ax2.set_xscale('log' if flag else 'linear')
self.ax.set_xscale('log' if flag else 'linear')
def setYAxisLogarithmic(self, flag):
+ if matplotlib.__version__ >= "2.0.0":
+ self.ax.cla()
+ self.ax2.cla()
self.ax2.set_yscale('log' if flag else 'linear')
self.ax.set_yscale('log' if flag else 'linear')
@@ -649,6 +666,29 @@ class BackendMatplotlib(BackendBase.BackendBase):
return (bbox.bounds[0] * dpi, bbox.bounds[1] * dpi,
bbox.bounds[2] * dpi, bbox.bounds[3] * dpi)
+ def setAxesDisplayed(self, displayed):
+ """Display or not the axes.
+
+ :param bool displayed: If `True` axes are displayed. If `False` axes
+ are not anymore visible and the margin used for them is removed.
+ """
+ BackendBase.BackendBase.setAxesDisplayed(self, displayed)
+ if displayed:
+ # show axes and viewbox rect
+ self.ax.set_axis_on()
+ self.ax2.set_axis_on()
+ # set the default margins
+ self.ax.set_position([.15, .15, .75, .75])
+ self.ax2.set_position([.15, .15, .75, .75])
+ else:
+ # hide axes and viewbox rect
+ self.ax.set_axis_off()
+ self.ax2.set_axis_off()
+ # remove external margins
+ self.ax.set_position([0, 0, 1, 1])
+ self.ax2.set_position([0, 0, 1, 1])
+ self._plot._setDirtyPlot()
+
class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
"""QWidget matplotlib backend using a QtAgg canvas.
@@ -682,6 +722,11 @@ class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
self.mpl_connect('motion_notify_event', self._onMouseMove)
self.mpl_connect('scroll_event', self._onMouseWheel)
+ def contextMenuEvent(self, event):
+ """Override QWidget.contextMenuEvent to implement the context menu"""
+ # Makes sure it is overridden (issue with PySide)
+ BackendBase.BackendBase.contextMenuEvent(self, event)
+
def postRedisplay(self):
self._sigPostRedisplay.emit()
@@ -738,18 +783,12 @@ class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
self._picked.append({'kind': 'image', 'legend': label[9:]})
else: # it's a curve, item have no picker for now
- if isinstance(event.artist, PathCollection):
- data = event.artist.get_offsets()[event.ind, :]
- xdata, ydata = data[:, 0], data[:, 1]
- elif isinstance(event.artist, Line2D):
- xdata = event.artist.get_xdata()[event.ind]
- ydata = event.artist.get_ydata()[event.ind]
- else:
+ if not isinstance(event.artist, (PathCollection, Line2D)):
_logger.info('Unsupported artist, ignored')
return
self._picked.append({'kind': 'curve', 'legend': label,
- 'xdata': xdata, 'ydata': ydata})
+ 'indices': event.ind})
def pickItems(self, x, y):
self._picked = []
@@ -776,9 +815,22 @@ class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
def draw(self):
"""Override canvas draw method to support faster draw of overlays."""
if self._plot._getDirtyPlot(): # Need a full redraw
+ # Store previous limits
+ xLimits = self.ax.get_xbound()
+ yLimits = self.ax.get_ybound()
+ yRightLimits = self.ax2.get_ybound()
+
FigureCanvasQTAgg.draw(self)
self._background = None # Any saved background is dirty
+ # Check if limits changed due to a resize of the widget
+ if xLimits != self.ax.get_xbound():
+ self._plot.getXAxis()._emitLimitsChanged()
+ if yLimits != self.ax.get_ybound():
+ self._plot.getYAxis(axis='left')._emitLimitsChanged()
+ if yRightLimits != self.ax2.get_ybound():
+ self._plot.getYAxis(axis='left')._emitLimitsChanged()
+
if (self._overlays or self._graphCursor or
self._plot._getDirtyPlot() == 'overlay'):
# There are overlays or crosshair, or they is just no more overlays