summaryrefslogtreecommitdiff
path: root/silx/math/combo.pyx
diff options
context:
space:
mode:
Diffstat (limited to 'silx/math/combo.pyx')
-rw-r--r--silx/math/combo.pyx329
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)