summaryrefslogtreecommitdiff
path: root/silx/gui/plot/items/core.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/items/core.py')
-rw-r--r--silx/gui/plot/items/core.py162
1 files changed, 162 insertions, 0 deletions
diff --git a/silx/gui/plot/items/core.py b/silx/gui/plot/items/core.py
index e7342b0..6d6575b 100644
--- a/silx/gui/plot/items/core.py
+++ b/silx/gui/plot/items/core.py
@@ -47,6 +47,7 @@ from ....utils.enum import Enum as _Enum
from ... import qt
from ... import colors
from ...colors import Colormap
+from ._pick import PickingResult
from silx import config
@@ -136,6 +137,12 @@ class ItemChangedType(enum.Enum):
COMPLEX_MODE = 'complexModeChanged'
"""Item's complex data visualization mode changed flag."""
+ NAME = 'nameChanged'
+ """Item's name changed flag."""
+
+ EDITABLE = 'editableChanged'
+ """Item's editable state changed flags."""
+
class Item(qt.QObject):
"""Description of an item of the plot"""
@@ -330,6 +337,26 @@ class Item(qt.QObject):
backend.remove(self._backendRenderer)
self._backendRenderer = None
+ def pick(self, x, y):
+ """Run picking test on this item
+
+ :param float x: The x pixel coord where to pick.
+ :param float y: The y pixel coord where to pick.
+ :return: None if not picked, else the picked position information
+ :rtype: Union[None,PickingResult]
+ """
+ if not self.isVisible() or self._backendRenderer is None:
+ return None
+ plot = self.getPlot()
+ if plot is None:
+ return None
+
+ indices = plot._backend.pickItem(x, y, self._backendRenderer)
+ if indices is None:
+ return None
+ else:
+ return PickingResult(self, indices if len(indices) != 0 else None)
+
# Mix-in classes ##############################################################
@@ -471,6 +498,17 @@ class SymbolMixIn(ItemMixInBase):
('x', 'Cross'),
('.', 'Point'),
(',', 'Pixel'),
+ ('|', 'Vertical line'),
+ ('_', 'Horizontal line'),
+ ('tickleft', 'Tick left'),
+ ('tickright', 'Tick right'),
+ ('tickup', 'Tick up'),
+ ('tickdown', 'Tick down'),
+ ('caretleft', 'Caret left'),
+ ('caretright', 'Caret right'),
+ ('caretup', 'Caret up'),
+ ('caretdown', 'Caret down'),
+ (u'\u2665', 'Heart'),
('', 'None')))
"""Dict of supported symbols"""
@@ -781,6 +819,7 @@ class ComplexMixIn(ItemMixInBase):
class ComplexMode(_Enum):
"""Identify available display mode for complex"""
+ NONE = 'none'
ABSOLUTE = 'amplitude'
PHASE = 'phase'
REAL = 'real'
@@ -884,8 +923,54 @@ class ScatterVisualizationMixIn(ItemMixInBase):
This is based on Delaunay triangulation
"""
+ REGULAR_GRID = 'regular_grid'
+ """Display scatter plot as an image.
+
+ It expects the points to be the intersection of a regular grid,
+ and the order of points following that of an image.
+ First line, then second one, and always in the same direction
+ (either all lines from left to right or all from right to left).
+ """
+
+ IRREGULAR_GRID = 'irregular_grid'
+ """Display scatter plot as contiguous quadrilaterals.
+
+ It expects the points to be the intersection of an irregular grid,
+ and the order of points following that of an image.
+ First line, then second one, and always in the same direction
+ (either all lines from left to right or all from right to left).
+ """
+
+ @enum.unique
+ class VisualizationParameter(_Enum):
+ """Different parameter names for scatter plot visualizations"""
+
+ GRID_MAJOR_ORDER = 'grid_major_order'
+ """The major order of points in the regular grid.
+
+ Either 'row' (row-major, fast X) or 'column' (column-major, fast Y).
+ """
+
+ GRID_BOUNDS = 'grid_bounds'
+ """The expected range in data coordinates of the regular grid.
+
+ A 2-tuple of 2-tuple: (begin (x, y), end (x, y)).
+ This provides the data coordinates of the first point and the expected
+ last on.
+ As for `GRID_SHAPE`, this can be wider than the current data.
+ """
+
+ GRID_SHAPE = 'grid_shape'
+ """The expected size of the regular grid (height, width).
+
+ The given shape can be wider than the number of points,
+ in which case the grid is not fully filled.
+ """
+
def __init__(self):
self.__visualization = self.Visualization.POINTS
+ self.__parameters = dict( # Init parameters to None
+ (parameter, None) for parameter in self.VisualizationParameter)
@classmethod
def supportedVisualizations(cls):
@@ -929,6 +1014,54 @@ class ScatterVisualizationMixIn(ItemMixInBase):
"""
return self.__visualization
+ def setVisualizationParameter(self, parameter, value=None):
+ """Set the given visualization parameter.
+
+ :param Union[str,VisualizationParameter] parameter:
+ The name of the parameter to set
+ :param value: The value to use for this parameter
+ Set to None to automatically set the parameter
+ :raises ValueError: If parameter is not supported
+ :return: True if parameter was set, False if is was already set
+ :rtype: bool
+ """
+ parameter = self.VisualizationParameter.from_value(parameter)
+
+ if self.__parameters[parameter] != value:
+ self.__parameters[parameter] = value
+ self._updated(ItemChangedType.VISUALIZATION_MODE)
+ return True
+ return False
+
+ def getVisualizationParameter(self, parameter):
+ """Returns the value of the given visualization parameter.
+
+ This method returns the parameter as set by
+ :meth:`setVisualizationParameter`.
+
+ :param parameter: The name of the parameter to retrieve
+ :returns: The value previously set or None if automatically set
+ :raises ValueError: If parameter is not supported
+ """
+ if parameter not in self.VisualizationParameter:
+ raise ValueError("parameter not supported: %s", parameter)
+
+ return self.__parameters[parameter]
+
+ def getCurrentVisualizationParameter(self, parameter):
+ """Returns the current value of the given visualization parameter.
+
+ If the parameter was set by :meth:`setVisualizationParameter` to
+ a value that is not None, this value is returned;
+ else the current value that is automatically computed is returned.
+
+ :param parameter: The name of the parameter to retrieve
+ :returns: The current value (either set or automatically computed)
+ :raises ValueError: If parameter is not supported
+ """
+ # Override in subclass to provide automatically computed parameters
+ return self.getVisualizationParameter(parameter)
+
class PointsBase(Item, SymbolMixIn, AlphaMixIn):
"""Base class for :class:`Curve` and :class:`Scatter`"""
@@ -1224,3 +1357,32 @@ class PointsBase(Item, SymbolMixIn, AlphaMixIn):
if plot is not None:
plot._invalidateDataRange()
self._updated(ItemChangedType.DATA)
+
+
+class BaselineMixIn(object):
+ """Base class for Baseline mix-in"""
+ def __init__(self, baseline=None):
+ self._baseline = baseline
+
+ def _setBaseline(self, baseline):
+ """
+ Set baseline value
+
+ :param baseline: baseline value(s)
+ :type: Union[None,float,numpy.ndarray]
+ """
+ if (isinstance(baseline, abc.Iterable)):
+ baseline = numpy.array(baseline)
+ self._baseline = baseline
+
+ def getBaseline(self, copy=True):
+ """
+
+ :param bool copy:
+ :return: histogram baseline
+ :rtype: Union[None,float,numpy.ndarray]
+ """
+ if isinstance(self._baseline, numpy.ndarray):
+ return numpy.array(self._baseline, copy=True)
+ else:
+ return self._baseline