summaryrefslogtreecommitdiff
path: root/silx/gui/plot/items/histogram.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/items/histogram.py')
-rw-r--r--silx/gui/plot/items/histogram.py332
1 files changed, 0 insertions, 332 deletions
diff --git a/silx/gui/plot/items/histogram.py b/silx/gui/plot/items/histogram.py
deleted file mode 100644
index 389e8a6..0000000
--- a/silx/gui/plot/items/histogram.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# 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:`Histogram` item of the :class:`Plot`.
-"""
-
-__authors__ = ["H. Payno", "T. Vincent"]
-__license__ = "MIT"
-__date__ = "28/08/2018"
-
-import logging
-
-import numpy
-
-from .core import (Item, AlphaMixIn, ColorMixIn, FillMixIn,
- LineMixIn, YAxisMixIn, ItemChangedType)
-
-_logger = logging.getLogger(__name__)
-
-
-def _computeEdges(x, histogramType):
- """Compute the edges from a set of xs and a rule to generate the edges
-
- :param x: the x value of the curve to transform into an histogram
- :param histogramType: the type of histogram we wan't to generate.
- This define the way to center the histogram values compared to the
- curve value. Possible values can be::
-
- - 'left'
- - 'right'
- - 'center'
-
- :return: the edges for the given x and the histogramType
- """
- # for now we consider that the spaces between xs are constant
- edges = x.copy()
- if histogramType is 'left':
- width = 1
- if len(x) > 1:
- width = x[1] - x[0]
- edges = numpy.append(x[0] - width, edges)
- if histogramType is 'center':
- edges = _computeEdges(edges, 'right')
- widths = (edges[1:] - edges[0:-1]) / 2.0
- widths = numpy.append(widths, widths[-1])
- edges = edges - widths
- if histogramType is 'right':
- width = 1
- if len(x) > 1:
- width = x[-1] - x[-2]
- edges = numpy.append(edges, x[-1] + width)
-
- return edges
-
-
-def _getHistogramCurve(histogram, edges):
- """Returns the x and y value of a curve corresponding to the histogram
-
- :param numpy.ndarray histogram: The values of the histogram
- :param numpy.ndarray edges: The bin edges of the histogram
- :return: a tuple(x, y) which contains the value of the curve to use
- to display the histogram
- """
- assert len(histogram) + 1 == len(edges)
- x = numpy.empty(len(histogram) * 2, dtype=edges.dtype)
- y = numpy.empty(len(histogram) * 2, dtype=histogram.dtype)
- # Make a curve with stairs
- x[:-1:2] = edges[:-1]
- x[1::2] = edges[1:]
- y[:-1:2] = histogram
- y[1::2] = histogram
-
- return x, y
-
-
-# TODO: Yerror, test log scale
-class Histogram(Item, AlphaMixIn, ColorMixIn, FillMixIn,
- LineMixIn, YAxisMixIn):
- """Description of an histogram"""
-
- _DEFAULT_Z_LAYER = 1
- """Default overlay layer for histograms"""
-
- _DEFAULT_SELECTABLE = False
- """Default selectable state for histograms"""
-
- _DEFAULT_LINEWIDTH = 1.
- """Default line width of the histogram"""
-
- _DEFAULT_LINESTYLE = '-'
- """Default line style of the histogram"""
-
- def __init__(self):
- Item.__init__(self)
- AlphaMixIn.__init__(self)
- ColorMixIn.__init__(self)
- FillMixIn.__init__(self)
- LineMixIn.__init__(self)
- YAxisMixIn.__init__(self)
-
- self._histogram = ()
- self._edges = ()
-
- def _addBackendRenderer(self, backend):
- """Update backend renderer"""
- values, edges = self.getData(copy=False)
-
- if values.size == 0:
- return None # No data to display, do not add renderer
-
- if values.size == 0:
- return None # No data to display, do not add renderer to backend
-
- x, y = _getHistogramCurve(values, edges)
-
- # Filter-out values <= 0
- plot = self.getPlot()
- if plot is not None:
- xPositive = plot.getXAxis()._isLogarithmic()
- yPositive = plot.getYAxis()._isLogarithmic()
- else:
- xPositive = False
- yPositive = False
-
- if xPositive or yPositive:
- clipped = numpy.logical_or(
- (x <= 0) if xPositive else False,
- (y <= 0) if yPositive else False)
- # Make a copy and replace negative points by NaN
- x = numpy.array(x, dtype=numpy.float)
- y = numpy.array(y, dtype=numpy.float)
- x[clipped] = numpy.nan
- y[clipped] = numpy.nan
-
- return backend.addCurve(x, y, self.getLegend(),
- color=self.getColor(),
- symbol='',
- linestyle=self.getLineStyle(),
- linewidth=self.getLineWidth(),
- yaxis=self.getYAxis(),
- xerror=None,
- yerror=None,
- z=self.getZValue(),
- selectable=self.isSelectable(),
- fill=self.isFill(),
- alpha=self.getAlpha(),
- symbolsize=1)
-
- def _getBounds(self):
- values, edges = self.getData(copy=False)
-
- plot = self.getPlot()
- if plot is not None:
- xPositive = plot.getXAxis()._isLogarithmic()
- yPositive = plot.getYAxis()._isLogarithmic()
- else:
- xPositive = False
- yPositive = False
-
- if xPositive or yPositive:
- values = numpy.array(values, copy=True, dtype=numpy.float)
-
- if xPositive:
- # Replace edges <= 0 by NaN and corresponding values by NaN
- clipped_edges = (edges <= 0)
- edges = numpy.array(edges, copy=True, dtype=numpy.float)
- edges[clipped_edges] = numpy.nan
- clipped_values = numpy.logical_or(clipped_edges[:-1],
- clipped_edges[1:])
- else:
- clipped_values = numpy.zeros_like(values, dtype=numpy.bool)
-
- if yPositive:
- # Replace values <= 0 by NaN, do not modify edges
- clipped_values = numpy.logical_or(clipped_values, values <= 0)
-
- values[clipped_values] = numpy.nan
-
- if xPositive or yPositive:
- return (numpy.nanmin(edges),
- numpy.nanmax(edges),
- numpy.nanmin(values),
- numpy.nanmax(values))
-
- else: # No log scale, include 0 in bounds
- return (numpy.nanmin(edges),
- numpy.nanmax(edges),
- min(0, numpy.nanmin(values)),
- max(0, numpy.nanmax(values)))
-
- 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(Histogram, self).setVisible(visible)
-
- def getValueData(self, copy=True):
- """The values of the histogram
-
- :param copy: True (Default) to get a copy,
- False to use internal representation (do not modify!)
- :returns: The bin edges of the histogram
- :rtype: numpy.ndarray
- """
- return numpy.array(self._histogram, copy=copy)
-
- def getBinEdgesData(self, copy=True):
- """The bin edges of the histogram (number of histogram values + 1)
-
- :param copy: True (Default) to get a copy,
- False to use internal representation (do not modify!)
- :returns: The bin edges of the histogram
- :rtype: numpy.ndarray
- """
- return numpy.array(self._edges, copy=copy)
-
- def getData(self, copy=True):
- """Return the histogram values and the bin edges
-
- :param copy: True (Default) to get a copy,
- False to use internal representation (do not modify!)
- :returns: (N histogram value, N+1 bin edges)
- :rtype: 2-tuple of numpy.nadarray
- """
- return self.getValueData(copy), self.getBinEdgesData(copy)
-
- def setData(self, histogram, edges, align='center', copy=True):
- """Set the histogram values and bin edges.
-
- :param numpy.ndarray histogram: The values of the histogram.
- :param numpy.ndarray edges:
- The bin edges of the histogram.
- If histogram and edges have the same length, the bin edges
- are computed according to the align parameter.
- :param str align:
- In case histogram values and edges have the same length N,
- the N+1 bin edges are computed according to the alignment in:
- 'center' (default), 'left', 'right'.
- :param bool copy: True make a copy of the data (default),
- False to use provided arrays.
- """
- histogram = numpy.array(histogram, copy=copy)
- edges = numpy.array(edges, copy=copy)
-
- assert histogram.ndim == 1
- assert edges.ndim == 1
- assert edges.size in (histogram.size, histogram.size + 1)
- assert align in ('center', 'left', 'right')
-
- if histogram.size == 0: # No data
- self._histogram = ()
- self._edges = ()
- else:
- if edges.size == histogram.size: # Compute true bin edges
- edges = _computeEdges(edges, align)
-
- # Check that bin edges are monotonic
- edgesDiff = numpy.diff(edges)
- assert numpy.all(edgesDiff >= 0) or numpy.all(edgesDiff <= 0)
-
- self._histogram = histogram
- self._edges = edges
- self._alignement = align
-
- if self.isVisible():
- plot = self.getPlot()
- if plot is not None:
- plot._invalidateDataRange()
-
- self._updated(ItemChangedType.DATA)
-
- def getAlignment(self):
- """
-
- :return: histogram alignement. Value in ('center', 'left', 'right').
- """
- return self._alignement
-
- def _revertComputeEdges(self, x, histogramType):
- """Compute the edges from a set of xs and a rule to generate the edges
-
- :param x: the x value of the curve to transform into an histogram
- :param histogramType: the type of histogram we wan't to generate.
- This define the way to center the histogram values compared to the
- curve value. Possible values can be::
-
- - 'left'
- - 'right'
- - 'center'
-
- :return: the edges for the given x and the histogramType
- """
- # for now we consider that the spaces between xs are constant
- edges = x.copy()
- if histogramType is 'left':
- return edges[1:]
- if histogramType is 'center':
- edges = (edges[1:] + edges[:-1]) / 2.0
- if histogramType is 'right':
- width = 1
- if len(x) > 1:
- width = x[-1] + x[-2]
- edges = edges[:-1]
- return edges