# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2017 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:`Curve` item of the :class:`Plot`.
"""
__authors__ = ["T. Vincent"]
__license__ = "MIT"
__date__ = "06/03/2017"
import logging
import numpy
from .. import Colors
from .core import (Points, LabelsMixIn, ColorMixIn, YAxisMixIn,
FillMixIn, LineMixIn, ItemChangedType)
_logger = logging.getLogger(__name__)
[docs]class Curve(Points, ColorMixIn, YAxisMixIn, FillMixIn, LabelsMixIn, LineMixIn):
"""Description of a curve"""
_DEFAULT_Z_LAYER = 1
"""Default overlay layer for curves"""
_DEFAULT_SELECTABLE = True
"""Default selectable state for curves"""
_DEFAULT_LINEWIDTH = 1.
"""Default line width of the curve"""
_DEFAULT_LINESTYLE = '-'
"""Default line style of the curve"""
_DEFAULT_HIGHLIGHT_COLOR = (0, 0, 0, 255)
"""Default highlight color of the item"""
def __init__(self):
Points.__init__(self)
ColorMixIn.__init__(self)
YAxisMixIn.__init__(self)
FillMixIn.__init__(self)
LabelsMixIn.__init__(self)
LineMixIn.__init__(self)
self._highlightColor = self._DEFAULT_HIGHLIGHT_COLOR
self._highlighted = False
def _addBackendRenderer(self, backend):
"""Update backend renderer"""
# Filter-out values <= 0
xFiltered, yFiltered, xerror, yerror = self.getData(
copy=False, displayed=True)
if len(xFiltered) == 0 or not numpy.any(numpy.isfinite(xFiltered)):
return None # No data to display, do not add renderer to backend
return backend.addCurve(xFiltered, yFiltered, self.getLegend(),
color=self.getCurrentColor(),
symbol=self.getSymbol(),
linestyle=self.getLineStyle(),
linewidth=self.getLineWidth(),
yaxis=self.getYAxis(),
xerror=xerror,
yerror=yerror,
z=self.getZValue(),
selectable=self.isSelectable(),
fill=self.isFill(),
alpha=self.getAlpha(),
symbolsize=self.getSymbolSize())
def __getitem__(self, item):
"""Compatibility with PyMca and silx <= 0.4.0"""
if isinstance(item, slice):
return [self[index] for index in range(*item.indices(5))]
elif item == 0:
return self.getXData(copy=False)
elif item == 1:
return self.getYData(copy=False)
elif item == 2:
return self.getLegend()
elif item == 3:
info = self.getInfo(copy=False)
return {} if info is None else info
elif item == 4:
params = {
'info': self.getInfo(),
'color': self.getColor(),
'symbol': self.getSymbol(),
'linewidth': self.getLineWidth(),
'linestyle': self.getLineStyle(),
'xlabel': self.getXLabel(),
'ylabel': self.getYLabel(),
'yaxis': self.getYAxis(),
'xerror': self.getXErrorData(copy=False),
'yerror': self.getYErrorData(copy=False),
'z': self.getZValue(),
'selectable': self.isSelectable(),
'fill': self.isFill()
}
return params
else:
raise IndexError("Index out of range: %s", str(item))
def setVisible(self, visible):
"""Set visibility of item.
:param bool visible: True to display it, False otherwise
"""
visible = bool(visible)
# TODO hackish data range implementation
if self.isVisible() != visible:
plot = self.getPlot()
if plot is not None:
plot._invalidateDataRange()
super(Curve, self).setVisible(visible)
[docs] def isHighlighted(self):
"""Returns True if curve is highlighted.
:rtype: bool
"""
return self._highlighted
[docs] def setHighlighted(self, highlighted):
"""Set the highlight state of the curve
:param bool highlighted:
"""
highlighted = bool(highlighted)
if highlighted != self._highlighted:
self._highlighted = highlighted
# TODO inefficient: better to use backend's setCurveColor
self._updated(ItemChangedType.HIGHLIGHTED)
[docs] def getHighlightedColor(self):
"""Returns the RGBA highlight color of the item
:rtype: 4-tuple of int in [0, 255]
"""
return self._highlightColor
[docs] def setHighlightedColor(self, color):
"""Set the color to use when highlighted
:param color: color(s) to be used for highlight
:type color: str ("#RRGGBB") or (npoints, 4) unsigned byte array or
one of the predefined color names defined in Colors.py
"""
color = Colors.rgba(color)
if color != self._highlightColor:
self._highlightColor = color
self._updated(ItemChangedType.HIGHLIGHTED_COLOR)
[docs] def getCurrentColor(self):
"""Returns the current color of the curve.
This color is either the color of the curve or the highlighted color,
depending on the highlight state.
:rtype: 4-tuple of int in [0, 255]
"""
if self.isHighlighted():
return self.getHighlightedColor()
else:
return self.getColor()