diff options
Diffstat (limited to 'silx/gui/plot/items/shape.py')
-rw-r--r-- | silx/gui/plot/items/shape.py | 288 |
1 files changed, 0 insertions, 288 deletions
diff --git a/silx/gui/plot/items/shape.py b/silx/gui/plot/items/shape.py deleted file mode 100644 index 955dfe3..0000000 --- a/silx/gui/plot/items/shape.py +++ /dev/null @@ -1,288 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2017-2020 European Synchrotron Radiation Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ###########################################################################*/ -"""This module provides the :class:`Shape` item of the :class:`Plot`. -""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "21/12/2018" - - -import logging - -import numpy -import six - -from ... import colors -from .core import ( - Item, DataItem, - ColorMixIn, FillMixIn, ItemChangedType, LineMixIn, YAxisMixIn) - - -_logger = logging.getLogger(__name__) - - -# TODO probably make one class for each kind of shape -# TODO check fill:polygon/polyline + fill = duplicated -class Shape(Item, ColorMixIn, FillMixIn, LineMixIn): - """Description of a shape item - - :param str type_: The type of shape in: - 'hline', 'polygon', 'rectangle', 'vline', 'polylines' - """ - - def __init__(self, type_): - Item.__init__(self) - ColorMixIn.__init__(self) - FillMixIn.__init__(self) - LineMixIn.__init__(self) - self._overlay = False - assert type_ in ('hline', 'polygon', 'rectangle', 'vline', 'polylines') - self._type = type_ - self._points = () - self._lineBgColor = None - - self._handle = None - - def _addBackendRenderer(self, backend): - """Update backend renderer""" - points = self.getPoints(copy=False) - x, y = points.T[0], points.T[1] - return backend.addShape(x, - y, - shape=self.getType(), - color=self.getColor(), - fill=self.isFill(), - overlay=self.isOverlay(), - linestyle=self.getLineStyle(), - linewidth=self.getLineWidth(), - linebgcolor=self.getLineBgColor()) - - def isOverlay(self): - """Return true if shape is drawn as an overlay - - :rtype: bool - """ - return self._overlay - - def setOverlay(self, overlay): - """Set the overlay state of the shape - - :param bool overlay: True to make it an overlay - """ - overlay = bool(overlay) - if overlay != self._overlay: - self._overlay = overlay - self._updated(ItemChangedType.OVERLAY) - - def getType(self): - """Returns the type of shape to draw. - - One of: 'hline', 'polygon', 'rectangle', 'vline', 'polylines' - - :rtype: str - """ - return self._type - - def getPoints(self, copy=True): - """Get the control points of the shape. - - :param bool copy: True (Default) to get a copy, - False to use internal representation (do not modify!) - :return: Array of point coordinates - :rtype: numpy.ndarray with 2 dimensions - """ - return numpy.array(self._points, copy=copy) - - def setPoints(self, points, copy=True): - """Set the point coordinates - - :param numpy.ndarray points: Array of point coordinates - :param bool copy: True (Default) to get a copy, - False to use internal representation (do not modify!) - :return: - """ - self._points = numpy.array(points, copy=copy) - self._updated(ItemChangedType.DATA) - - def getLineBgColor(self): - """Returns the RGBA color of the item - :rtype: 4-tuple of float in [0, 1] or array of colors - """ - return self._lineBgColor - - def setLineBgColor(self, color, copy=True): - """Set item color - :param color: color(s) to be used - :type color: str ("#RRGGBB") or (npoints, 4) unsigned byte array or - one of the predefined color names defined in colors.py - :param bool copy: True (Default) to get a copy, - False to use internal representation (do not modify!) - """ - if color is not None: - if isinstance(color, six.string_types): - color = colors.rgba(color) - else: - color = numpy.array(color, copy=copy) - # TODO more checks + improve color array support - if color.ndim == 1: # Single RGBA color - color = colors.rgba(color) - else: # Array of colors - assert color.ndim == 2 - - self._lineBgColor = color - self._updated(ItemChangedType.LINE_BG_COLOR) - - -class BoundingRect(DataItem, YAxisMixIn): - """An invisible shape which enforce the plot view to display the defined - space on autoscale. - - This item do not display anything. But if the visible property is true, - this bounding box is used by the plot, if not, the bounding box is - ignored. That's the default behaviour for plot items. - - It can be applied on the "left" or "right" axes. Not both at the same time. - """ - - def __init__(self): - DataItem.__init__(self) - YAxisMixIn.__init__(self) - self.__bounds = None - - def setBounds(self, rect): - """Set the bounding box of this item in data coordinates - - :param Union[None,List[float]] rect: (xmin, xmax, ymin, ymax) or None - """ - if rect is not None: - rect = float(rect[0]), float(rect[1]), float(rect[2]), float(rect[3]) - assert rect[0] <= rect[1] - assert rect[2] <= rect[3] - - if rect != self.__bounds: - self.__bounds = rect - self._boundsChanged() - self._updated(ItemChangedType.DATA) - - def _getBounds(self): - if self.__bounds is None: - return None - plot = self.getPlot() - if plot is not None: - xPositive = plot.getXAxis()._isLogarithmic() - yPositive = plot.getYAxis()._isLogarithmic() - if xPositive or yPositive: - bounds = list(self.__bounds) - if xPositive and bounds[1] <= 0: - return None - if xPositive and bounds[0] <= 0: - bounds[0] = bounds[1] - if yPositive and bounds[3] <= 0: - return None - if yPositive and bounds[2] <= 0: - bounds[2] = bounds[3] - return tuple(bounds) - - return self.__bounds - - -class _BaseExtent(DataItem): - """Base class for :class:`XAxisExtent` and :class:`YAxisExtent`. - - :param str axis: Either 'x' or 'y'. - """ - - def __init__(self, axis='x'): - assert axis in ('x', 'y') - DataItem.__init__(self) - self.__axis = axis - self.__range = 1., 100. - - def setRange(self, min_, max_): - """Set the range of the extent of this item in data coordinates. - - :param float min_: Lower bound of the extent - :param float max_: Upper bound of the extent - :raises ValueError: If min > max or not finite bounds - """ - range_ = float(min_), float(max_) - if not numpy.all(numpy.isfinite(range_)): - raise ValueError("min_ and max_ must be finite numbers.") - if range_[0] > range_[1]: - raise ValueError("min_ must be lesser or equal to max_") - - if range_ != self.__range: - self.__range = range_ - self._boundsChanged() - self._updated(ItemChangedType.DATA) - - def getRange(self): - """Returns the range (min, max) of the extent in data coordinates. - - :rtype: List[float] - """ - return self.__range - - def _getBounds(self): - min_, max_ = self.getRange() - - plot = self.getPlot() - if plot is not None: - axis = plot.getXAxis() if self.__axis == 'x' else plot.getYAxis() - if axis._isLogarithmic(): - if max_ <= 0: - return None - if min_ <= 0: - min_ = max_ - - if self.__axis == 'x': - return min_, max_, float('nan'), float('nan') - else: - return float('nan'), float('nan'), min_, max_ - - -class XAxisExtent(_BaseExtent): - """Invisible item with a settable horizontal data extent. - - This item do not display anything, but it behaves as a data - item with a horizontal extent regarding plot data bounds, i.e., - :meth:`PlotWidget.resetZoom` will take this horizontal extent into account. - """ - def __init__(self): - _BaseExtent.__init__(self, axis='x') - - -class YAxisExtent(_BaseExtent, YAxisMixIn): - """Invisible item with a settable vertical data extent. - - This item do not display anything, but it behaves as a data - item with a vertical extent regarding plot data bounds, i.e., - :meth:`PlotWidget.resetZoom` will take this vertical extent into account. - """ - - def __init__(self): - _BaseExtent.__init__(self, axis='y') - YAxisMixIn.__init__(self) |