summaryrefslogtreecommitdiff
path: root/silx/gui/plot/backends
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/backends')
-rw-r--r--silx/gui/plot/backends/BackendBase.py17
-rw-r--r--silx/gui/plot/backends/BackendMatplotlib.py28
-rw-r--r--silx/gui/plot/backends/BackendOpenGL.py17
-rw-r--r--silx/gui/plot/backends/glutils/GLText.py46
4 files changed, 85 insertions, 23 deletions
diff --git a/silx/gui/plot/backends/BackendBase.py b/silx/gui/plot/backends/BackendBase.py
index 8352ea0..7fb8be0 100644
--- a/silx/gui/plot/backends/BackendBase.py
+++ b/silx/gui/plot/backends/BackendBase.py
@@ -163,9 +163,8 @@ class BackendBase(object):
:param int z: Layer on which to draw the image
:param bool selectable: indicate if the image can be selected
:param bool draggable: indicate if the image can be moved
- :param colormap: :class:`.Colormap` describing the colormap to use.
- Ignored if data is RGB(A).
- :type colormap: :class:`.Colormap`
+ :param ~silx.gui.colors.Colormap colormap: Colormap object to use.
+ Ignored if data is RGB(A).
:param float alpha: Opacity of the image, as a float in range [0, 1].
:returns: The handle used by the backend to univocally access the image
"""
@@ -189,7 +188,7 @@ class BackendBase(object):
def addMarker(self, x, y, legend, text, color,
selectable, draggable,
- symbol, constraint):
+ symbol, linestyle, linewidth, constraint):
"""Add a point, vertical line or horizontal line marker to the plot.
:param float x: Horizontal position of the marker in graph coordinates.
@@ -212,7 +211,17 @@ class BackendBase(object):
- 'x' x-cross
- 'd' diamond
- 's' square
+ :param str linestyle: Style of the line.
+ Only relevant for line markers where X or Y is None.
+ Value in:
+ - ' ' no line
+ - '-' solid line
+ - '--' dashed line
+ - '-.' dash-dot line
+ - ':' dotted line
+ :param float linewidth: Width of the line.
+ Only relevant for line markers where X or Y is None.
:param constraint: A function filtering marker displacement by
dragging operations or None for no filter.
This function is called each time a marker is
diff --git a/silx/gui/plot/backends/BackendMatplotlib.py b/silx/gui/plot/backends/BackendMatplotlib.py
index 49c4540..3b1d6dd 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/10/2017"
+__date__ = "01/08/2018"
import logging
@@ -56,8 +56,7 @@ from matplotlib.collections import PathCollection, LineCollection
from matplotlib.ticker import Formatter, ScalarFormatter, Locator
-
-from ..matplotlib.ModestImage import ModestImage
+from ....third_party.modest_image import ModestImage
from . import BackendBase
from .._utils import FLOAT32_MINPOS
from .._utils.dtime_ticklayout import calcTicks, bestFormatString, timestamp
@@ -520,7 +519,7 @@ class BackendMatplotlib(BackendBase.BackendBase):
def addMarker(self, x, y, legend, text, color,
selectable, draggable,
- symbol, constraint):
+ symbol, linestyle, linewidth, constraint):
legend = "__MARKER__" + legend
textArtist = None
@@ -548,7 +547,11 @@ class BackendMatplotlib(BackendBase.BackendBase):
verticalalignment=valign)
elif x is not None:
- line = self.ax.axvline(x, label=legend, color=color)
+ line = self.ax.axvline(x,
+ label=legend,
+ color=color,
+ linewidth=linewidth,
+ linestyle=linestyle)
if text is not None:
# Y position will be updated in updateMarkerText call
textArtist = self.ax.text(x, 1., " " + text,
@@ -557,7 +560,11 @@ class BackendMatplotlib(BackendBase.BackendBase):
verticalalignment='top')
elif y is not None:
- line = self.ax.axhline(y, label=legend, color=color)
+ line = self.ax.axhline(y,
+ label=legend,
+ color=color,
+ linewidth=linewidth,
+ linestyle=linestyle)
if text is not None:
# X position will be updated in updateMarkerText call
@@ -1117,7 +1124,6 @@ class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
# cursor
_QT_CURSORS = {
- None: qt.Qt.ArrowCursor,
BackendBase.CURSOR_DEFAULT: qt.Qt.ArrowCursor,
BackendBase.CURSOR_POINTING: qt.Qt.PointingHandCursor,
BackendBase.CURSOR_SIZE_HOR: qt.Qt.SizeHorCursor,
@@ -1126,6 +1132,8 @@ class BackendMatplotlibQt(FigureCanvasQTAgg, BackendMatplotlib):
}
def setGraphCursorShape(self, cursor):
- cursor = self._QT_CURSORS[cursor]
-
- FigureCanvasQTAgg.setCursor(self, qt.QCursor(cursor))
+ if cursor is None:
+ FigureCanvasQTAgg.unsetCursor(self)
+ else:
+ cursor = self._QT_CURSORS[cursor]
+ FigureCanvasQTAgg.setCursor(self, qt.QCursor(cursor))
diff --git a/silx/gui/plot/backends/BackendOpenGL.py b/silx/gui/plot/backends/BackendOpenGL.py
index 0001bb9..9e2cb73 100644
--- a/silx/gui/plot/backends/BackendOpenGL.py
+++ b/silx/gui/plot/backends/BackendOpenGL.py
@@ -28,7 +28,7 @@ from __future__ import division
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "24/04/2018"
+__date__ = "01/08/2018"
from collections import OrderedDict, namedtuple
from ctypes import c_void_p
@@ -1161,11 +1161,15 @@ class BackendOpenGL(BackendBase.BackendBase, glu.OpenGLWidget):
def addMarker(self, x, y, legend, text, color,
selectable, draggable,
- symbol, constraint):
+ symbol, linestyle, linewidth, constraint):
if symbol is None:
symbol = '+'
+ if linestyle != '-' or linewidth != 1:
+ _logger.warning(
+ 'OpenGL backend does not support marker line style and width.')
+
behaviors = set()
if selectable:
behaviors.add('selectable')
@@ -1223,7 +1227,6 @@ class BackendOpenGL(BackendBase.BackendBase, glu.OpenGLWidget):
# Interaction methods
_QT_CURSORS = {
- None: qt.Qt.ArrowCursor,
BackendBase.CURSOR_DEFAULT: qt.Qt.ArrowCursor,
BackendBase.CURSOR_POINTING: qt.Qt.PointingHandCursor,
BackendBase.CURSOR_SIZE_HOR: qt.Qt.SizeHorCursor,
@@ -1232,9 +1235,11 @@ class BackendOpenGL(BackendBase.BackendBase, glu.OpenGLWidget):
}
def setGraphCursorShape(self, cursor):
- cursor = self._QT_CURSORS[cursor]
-
- super(BackendOpenGL, self).setCursor(qt.QCursor(cursor))
+ if cursor is None:
+ super(BackendOpenGL, self).unsetCursor()
+ else:
+ cursor = self._QT_CURSORS[cursor]
+ super(BackendOpenGL, self).setCursor(qt.QCursor(cursor))
def setGraphCursor(self, flag, color, linewidth, linestyle):
if linestyle is not '-':
diff --git a/silx/gui/plot/backends/glutils/GLText.py b/silx/gui/plot/backends/glutils/GLText.py
index 1540e26..3d262bc 100644
--- a/silx/gui/plot/backends/glutils/GLText.py
+++ b/silx/gui/plot/backends/glutils/GLText.py
@@ -32,6 +32,7 @@ __license__ = "MIT"
__date__ = "03/04/2017"
+from collections import OrderedDict
import numpy
from ...._glutils import font, gl, getGLContext, Program, Texture
@@ -41,6 +42,45 @@ from .GLSupport import mat4Translate
# TODO: Font should be configurable by the main program: using mpl.rcParams?
+class _Cache(object):
+ """LRU (Least Recent Used) cache.
+
+ :param int maxsize: Maximum number of (key, value) pairs in the cache
+ :param callable callback:
+ Called when a (key, value) pair is removed from the cache.
+ It must take 2 arguments: key and value.
+ """
+
+ def __init__(self, maxsize=128, callback=None):
+ self._maxsize = int(maxsize)
+ self._callback = callback
+ self._cache = OrderedDict()
+
+ def __contains__(self, item):
+ return item in self._cache
+
+ def __getitem__(self, key):
+ if key in self._cache:
+ # Remove/add key from ordered dict to store last access info
+ value = self._cache.pop(key)
+ self._cache[key] = value
+ return value
+ else:
+ raise KeyError
+
+ def __setitem__(self, key, value):
+ """Add a key, value pair to the cache.
+
+ :param key: The key to set
+ :param value: The corresponding value
+ """
+ if key not in self._cache and len(self._cache) >= self._maxsize:
+ removedKey, removedValue = self._cache.popitem(last=False)
+ if self._callback is not None:
+ self._callback(removedKey, removedValue)
+ self._cache[key] = value
+
+
# Text2D ######################################################################
LEFT, CENTER, RIGHT = 'left', 'center', 'right'
@@ -87,11 +127,11 @@ class Text2D(object):
_SHADERS['fragment'],
attrib0='position')
- _textures = {}
+ # Discard texture objects when removed from the cache
+ _textures = _Cache(callback=lambda key, value: value[0].discard())
"""Cache already created textures"""
- # TODO limit cache size and discard least recent used
- _sizes = {}
+ _sizes = _Cache()
"""Cache already computed sizes"""
def __init__(self, text, x=0, y=0,