diff options
Diffstat (limited to 'silx/gui/plot/items/core.py')
-rw-r--r-- | silx/gui/plot/items/core.py | 162 |
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 |