Skip to content
Snippets Groups Projects
Forked from FSL / fslpy
1396 commits behind the upstream repository.
naninfrange.py 1.61 KiB
#!/usr/bin/env python
#
# naninfrange.py - The naninfrange function.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""This module provides the :func:`naninfrange` function, which calculates
the range of a numpy array, ignoring infinite and nan values.
"""


import warnings

import numpy as np


def naninfrange(data):
    """Returns the minimum and maximum values in the given ``numpy`` array,
    ignoring ``nan`` and ``inf`` values.

    The ``numpy.nanmin``/``numpy.nanmax`` functions do not handle
    positive/negative infinity, so if such values are in the data, we need to
    use an alternate approach to calculating the minimum/maximum.
    """

    if not np.issubdtype(data.dtype, np.floating):
        return data.min(), data.max()

    # But np.nanmin/nanmax are substantially
    # faster than the alternate, so we try it
    # first.
    with warnings.catch_warnings():
        warnings.filterwarnings('ignore')
        dmin = np.nanmin(data)
        dmax = np.nanmax(data)

    # If there are no nans/infs in the data,
    # we can just use nanmin/nanmax
    if np.isfinite(dmin) and np.isfinite(dmax):
        return dmin, dmax

    # The entire array contains nans
    if np.isnan(dmin):
        return dmin, dmin

    # Otherwise we need to calculate min/max
    # only on finite values. This is the slow
    # option.

    # Find all finite values
    finite = np.isfinite(data)

    # Try to calculate min/max on those values.
    # An error will be raised if there are no
    # finite values in the array
    try:
        return data[finite].min(), data[finite].max()
    except Exception:
        return np.nan, np.nan