diff options
author | Picca Frédéric-Emmanuel <picca@debian.org> | 2022-02-02 14:19:58 +0100 |
---|---|---|
committer | Picca Frédéric-Emmanuel <picca@debian.org> | 2022-02-02 14:19:58 +0100 |
commit | 4e774db12d5ebe7a20eded6dd434a289e27999e5 (patch) | |
tree | a9822974ba45196f1e3740995ab157d6eb214a04 /silx/math/combo.pyx | |
parent | d3194b1a9c4404ba93afac43d97172ab24c57098 (diff) |
New upstream version 1.0.0+dfsg
Diffstat (limited to 'silx/math/combo.pyx')
-rw-r--r-- | silx/math/combo.pyx | 329 |
1 files changed, 0 insertions, 329 deletions
diff --git a/silx/math/combo.pyx b/silx/math/combo.pyx deleted file mode 100644 index e24edda..0000000 --- a/silx/math/combo.pyx +++ /dev/null @@ -1,329 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2016-2018 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 combination of statistics as single operation. - -For now it provides min/max (and optionally positive min) and indices -of first occurrences (i.e., argmin/argmax) in a single pass. -""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "24/04/2018" - -cimport cython -from .math_compatibility cimport isnan, isfinite, INFINITY - - -import numpy - - -# All supported types -ctypedef fused _number: - float - double - long double - signed char - signed short - signed int - signed long - signed long long - unsigned char - unsigned short - unsigned int - unsigned long - unsigned long long - -# All supported floating types: -# cython.floating + long double -ctypedef fused _floating: - float - double - long double - - -class _MinMaxResult(object): - """Object storing result from :func:`min_max`""" - - def __init__(self, minimum, min_pos, maximum, - argmin, argmin_pos, argmax): - self._minimum = minimum - self._min_positive = min_pos - self._maximum = maximum - - self._argmin = argmin - self._argmin_positive = argmin_pos - self._argmax = argmax - - minimum = property( - lambda self: self._minimum, - doc="Minimum value of the array") - maximum = property( - lambda self: self._maximum, - doc="Maximum value of the array") - - argmin = property( - lambda self: self._argmin, - doc="Index of the first occurrence of the minimum value") - argmax = property( - lambda self: self._argmax, - doc="Index of the first occurrence of the maximum value") - - min_positive = property( - lambda self: self._min_positive, - doc="""Strictly positive minimum value - - It is None if no value is strictly positive. - """) - argmin_positive = property( - lambda self: self._argmin_positive, - doc="""Index of the strictly positive minimum value. - - It is None if no value is strictly positive. - It is the index of the first occurrence.""") - - def __getitem__(self, key): - if key == 0: - return self.minimum - elif key == 1: - return self.maximum - else: - raise IndexError("Index out of range") - - -@cython.initializedcheck(False) -@cython.boundscheck(False) -@cython.wraparound(False) -def _min_max(_number[::1] data, bint min_positive=False): - """:func:`min_max` implementation including infinite values - - See :func:`min_max` for documentation. - """ - cdef: - _number value, minimum, min_pos, maximum - unsigned int length - unsigned int index = 0 - unsigned int min_index = 0 - unsigned int min_pos_index = 0 - unsigned int max_index = 0 - - length = len(data) - - if length == 0: - raise ValueError('Zero-size array') - - with nogil: - # Init starting values - value = data[0] - minimum = value - maximum = value - if min_positive and value > 0: - min_pos = value - else: - min_pos = 0 - - if _number in _floating: - # For floating, loop until first not NaN value - for index in range(length): - value = data[index] - if not isnan(value): - minimum = value - min_index = index - maximum = value - max_index = index - break - - if not min_positive: - for index in range(index, length): - value = data[index] - if value > maximum: - maximum = value - max_index = index - elif value < minimum: - minimum = value - min_index = index - - else: - # Loop until min_pos is defined - for index in range(index, length): - value = data[index] - if value > maximum: - maximum = value - max_index = index - elif value < minimum: - minimum = value - min_index = index - - if value > 0: - min_pos = value - min_pos_index = index - break - - # Loop until the end - for index in range(index + 1, length): - value = data[index] - if value > maximum: - maximum = value - max_index = index - else: - if value < minimum: - minimum = value - min_index = index - - if 0 < value < min_pos: - min_pos = value - min_pos_index = index - - return _MinMaxResult(minimum, - min_pos if min_pos > 0 else None, - maximum, - min_index, - min_pos_index if min_pos > 0 else None, - max_index) - - -@cython.initializedcheck(False) -@cython.boundscheck(False) -@cython.wraparound(False) -def _finite_min_max(_floating[::1] data, bint min_positive=False): - """:func:`min_max` implementation for floats skipping infinite values - - See :func:`min_max` for documentation. - """ - cdef: - _floating value, minimum, min_pos, maximum - unsigned int length - unsigned int index = 0 - unsigned int min_index = 0 - unsigned int min_pos_index = 0 - unsigned int max_index = 0 - - length = len(data) - - if length == 0: - raise ValueError('Zero-size array') - - with nogil: - minimum = INFINITY - maximum = -INFINITY - min_pos = INFINITY - - if not min_positive: - for index in range(length): - value = data[index] - if isfinite(value): - if value > maximum: - maximum = value - max_index = index - if value < minimum: - minimum = value - min_index = index - - else: - for index in range(index, length): - value = data[index] - if isfinite(value): - if value > maximum: - maximum = value - max_index = index - if value < minimum: - minimum = value - min_index = index - - if 0. < value < min_pos: - min_pos = value - min_pos_index = index - - return _MinMaxResult(minimum if isfinite(minimum) else None, - min_pos if isfinite(min_pos) else None, - maximum if isfinite(maximum) else None, - min_index if isfinite(minimum) else None, - min_pos_index if isfinite(min_pos) else None, - max_index if isfinite(maximum) else None) - - -def min_max(data not None, bint min_positive=False, bint finite=False): - """Returns min, max and optionally strictly positive min of data. - - It also computes the indices of first occurrence of min/max. - - NaNs are ignored while computing min/max unless all data is NaNs, - in which case returned min/max are NaNs. - - The result data type is that of the input data, except for the following cases. - For input using non-native bytes order, the result is returned as native - floating-point or integers. For input using 16-bits floating-point, - the result is returned as 32-bits floating-point. - - Examples: - - >>> import numpy - >>> data = numpy.arange(10) - - Usage as a function returning min and max: - - >>> min_, max_ = min_max(data) - - Usage as a function returning a result object to access all information: - - >>> result = min_max(data) # Do not get positive min - >>> result.minimum, result.argmin - 0, 0 - >>> result.maximum, result.argmax - 9, 10 - >>> result.min_positive, result.argmin_positive # Not computed - None, None - - Getting strictly positive min information: - - >>> result = min_max(data, min_positive=True) - >>> result.min_positive, result.argmin_positive # Computed - 1, 1 - - If *finite* is True, min/max information is computed only from finite data. - Then, all result fields (include minimum and maximum) can be None - when all data is infinity or NaN. - - :param data: Array-like dataset - :param bool min_positive: True to compute the positive min and argmin - Default: False. - :param bool finite: True to compute min/max from finite data only - Default: False. - :returns: An object with minimum, maximum and min_positive attributes - and the indices of first occurrence in the flattened data: - argmin, argmax and argmin_positive attributes. - If all data is <= 0 or min_positive argument is False, then - min_positive and argmin_positive are None. - :raises: ValueError if data is empty - """ - data = numpy.array(data, copy=False) - native_endian_dtype = data.dtype.newbyteorder('N') - if native_endian_dtype.kind == 'f' and native_endian_dtype.itemsize == 2: - # Use native float32 instead of float16 - native_endian_dtype = "=f4" - data = numpy.ascontiguousarray(data, dtype=native_endian_dtype).ravel() - if finite and data.dtype.kind == 'f': - return _finite_min_max(data, min_positive) - else: - return _min_max(data, min_positive) |