You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							2046 lines
						
					
					
						
							60 KiB
						
					
					
				
			
		
		
	
	
							2046 lines
						
					
					
						
							60 KiB
						
					
					
				"""
 | 
						|
Masked arrays add-ons.
 | 
						|
 | 
						|
A collection of utilities for `numpy.ma`.
 | 
						|
 | 
						|
:author: Pierre Gerard-Marchant
 | 
						|
:contact: pierregm_at_uga_dot_edu
 | 
						|
:version: $Id: extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $
 | 
						|
 | 
						|
"""
 | 
						|
__all__ = [
 | 
						|
    'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d',
 | 
						|
    'atleast_3d', 'average', 'clump_masked', 'clump_unmasked', 'column_stack',
 | 
						|
    'compress_cols', 'compress_nd', 'compress_rowcols', 'compress_rows',
 | 
						|
    'count_masked', 'corrcoef', 'cov', 'diagflat', 'dot', 'dstack', 'ediff1d',
 | 
						|
    'flatnotmasked_contiguous', 'flatnotmasked_edges', 'hsplit', 'hstack',
 | 
						|
    'isin', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', 'mask_rows',
 | 
						|
    'masked_all', 'masked_all_like', 'median', 'mr_', 'ndenumerate',
 | 
						|
    'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack',
 | 
						|
    'setdiff1d', 'setxor1d', 'stack', 'unique', 'union1d', 'vander', 'vstack',
 | 
						|
    ]
 | 
						|
 | 
						|
import itertools
 | 
						|
import warnings
 | 
						|
 | 
						|
from . import core as ma
 | 
						|
from .core import (
 | 
						|
    MaskedArray, MAError, add, array, asarray, concatenate, filled, count,
 | 
						|
    getmask, getmaskarray, make_mask_descr, masked, masked_array, mask_or,
 | 
						|
    nomask, ones, sort, zeros, getdata, get_masked_subclass, dot,
 | 
						|
    mask_rowcols
 | 
						|
    )
 | 
						|
 | 
						|
import numpy as np
 | 
						|
from numpy import ndarray, array as nxarray
 | 
						|
from numpy.core.multiarray import normalize_axis_index
 | 
						|
from numpy.core.numeric import normalize_axis_tuple
 | 
						|
from numpy.lib.function_base import _ureduce
 | 
						|
from numpy.lib.index_tricks import AxisConcatenator
 | 
						|
 | 
						|
 | 
						|
def issequence(seq):
 | 
						|
    """
 | 
						|
    Is seq a sequence (ndarray, list or tuple)?
 | 
						|
 | 
						|
    """
 | 
						|
    return isinstance(seq, (ndarray, tuple, list))
 | 
						|
 | 
						|
 | 
						|
def count_masked(arr, axis=None):
 | 
						|
    """
 | 
						|
    Count the number of masked elements along the given axis.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    arr : array_like
 | 
						|
        An array with (possibly) masked elements.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which to count. If None (default), a flattened
 | 
						|
        version of the array is used.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    count : int, ndarray
 | 
						|
        The total number of masked elements (axis=None) or the number
 | 
						|
        of masked elements along each slice of the given axis.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    MaskedArray.count : Count non-masked elements.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> a = np.arange(9).reshape((3,3))
 | 
						|
    >>> a = ma.array(a)
 | 
						|
    >>> a[1, 0] = ma.masked
 | 
						|
    >>> a[1, 2] = ma.masked
 | 
						|
    >>> a[2, 1] = ma.masked
 | 
						|
    >>> a
 | 
						|
    masked_array(
 | 
						|
      data=[[0, 1, 2],
 | 
						|
            [--, 4, --],
 | 
						|
            [6, --, 8]],
 | 
						|
      mask=[[False, False, False],
 | 
						|
            [ True, False,  True],
 | 
						|
            [False,  True, False]],
 | 
						|
      fill_value=999999)
 | 
						|
    >>> ma.count_masked(a)
 | 
						|
    3
 | 
						|
 | 
						|
    When the `axis` keyword is used an array is returned.
 | 
						|
 | 
						|
    >>> ma.count_masked(a, axis=0)
 | 
						|
    array([1, 1, 1])
 | 
						|
    >>> ma.count_masked(a, axis=1)
 | 
						|
    array([0, 2, 1])
 | 
						|
 | 
						|
    """
 | 
						|
    m = getmaskarray(arr)
 | 
						|
    return m.sum(axis)
 | 
						|
 | 
						|
 | 
						|
def masked_all(shape, dtype=float):
 | 
						|
    """
 | 
						|
    Empty masked array with all elements masked.
 | 
						|
 | 
						|
    Return an empty masked array of the given shape and dtype, where all the
 | 
						|
    data are masked.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    shape : int or tuple of ints
 | 
						|
        Shape of the required MaskedArray, e.g., ``(2, 3)`` or ``2``.
 | 
						|
    dtype : dtype, optional
 | 
						|
        Data type of the output.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    a : MaskedArray
 | 
						|
        A masked array with all data masked.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    masked_all_like : Empty masked array modelled on an existing array.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> ma.masked_all((3, 3))
 | 
						|
    masked_array(
 | 
						|
      data=[[--, --, --],
 | 
						|
            [--, --, --],
 | 
						|
            [--, --, --]],
 | 
						|
      mask=[[ True,  True,  True],
 | 
						|
            [ True,  True,  True],
 | 
						|
            [ True,  True,  True]],
 | 
						|
      fill_value=1e+20,
 | 
						|
      dtype=float64)
 | 
						|
 | 
						|
    The `dtype` parameter defines the underlying data type.
 | 
						|
 | 
						|
    >>> a = ma.masked_all((3, 3))
 | 
						|
    >>> a.dtype
 | 
						|
    dtype('float64')
 | 
						|
    >>> a = ma.masked_all((3, 3), dtype=np.int32)
 | 
						|
    >>> a.dtype
 | 
						|
    dtype('int32')
 | 
						|
 | 
						|
    """
 | 
						|
    a = masked_array(np.empty(shape, dtype),
 | 
						|
                     mask=np.ones(shape, make_mask_descr(dtype)))
 | 
						|
    return a
 | 
						|
 | 
						|
 | 
						|
def masked_all_like(arr):
 | 
						|
    """
 | 
						|
    Empty masked array with the properties of an existing array.
 | 
						|
 | 
						|
    Return an empty masked array of the same shape and dtype as
 | 
						|
    the array `arr`, where all the data are masked.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    arr : ndarray
 | 
						|
        An array describing the shape and dtype of the required MaskedArray.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    a : MaskedArray
 | 
						|
        A masked array with all data masked.
 | 
						|
 | 
						|
    Raises
 | 
						|
    ------
 | 
						|
    AttributeError
 | 
						|
        If `arr` doesn't have a shape attribute (i.e. not an ndarray)
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    masked_all : Empty masked array with all elements masked.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> arr = np.zeros((2, 3), dtype=np.float32)
 | 
						|
    >>> arr
 | 
						|
    array([[0., 0., 0.],
 | 
						|
           [0., 0., 0.]], dtype=float32)
 | 
						|
    >>> ma.masked_all_like(arr)
 | 
						|
    masked_array(
 | 
						|
      data=[[--, --, --],
 | 
						|
            [--, --, --]],
 | 
						|
      mask=[[ True,  True,  True],
 | 
						|
            [ True,  True,  True]],
 | 
						|
      fill_value=1e+20,
 | 
						|
      dtype=float32)
 | 
						|
 | 
						|
    The dtype of the masked array matches the dtype of `arr`.
 | 
						|
 | 
						|
    >>> arr.dtype
 | 
						|
    dtype('float32')
 | 
						|
    >>> ma.masked_all_like(arr).dtype
 | 
						|
    dtype('float32')
 | 
						|
 | 
						|
    """
 | 
						|
    a = np.empty_like(arr).view(MaskedArray)
 | 
						|
    a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype))
 | 
						|
    return a
 | 
						|
 | 
						|
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
#---- --- Standard functions ---
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
class _fromnxfunction:
 | 
						|
    """
 | 
						|
    Defines a wrapper to adapt NumPy functions to masked arrays.
 | 
						|
 | 
						|
 | 
						|
    An instance of `_fromnxfunction` can be called with the same parameters
 | 
						|
    as the wrapped NumPy function. The docstring of `newfunc` is adapted from
 | 
						|
    the wrapped function as well, see `getdoc`.
 | 
						|
 | 
						|
    This class should not be used directly. Instead, one of its extensions that
 | 
						|
    provides support for a specific type of input should be used.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    funcname : str
 | 
						|
        The name of the function to be adapted. The function should be
 | 
						|
        in the NumPy namespace (i.e. ``np.funcname``).
 | 
						|
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, funcname):
 | 
						|
        self.__name__ = funcname
 | 
						|
        self.__doc__ = self.getdoc()
 | 
						|
 | 
						|
    def getdoc(self):
 | 
						|
        """
 | 
						|
        Retrieve the docstring and signature from the function.
 | 
						|
 | 
						|
        The ``__doc__`` attribute of the function is used as the docstring for
 | 
						|
        the new masked array version of the function. A note on application
 | 
						|
        of the function to the mask is appended.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        None
 | 
						|
 | 
						|
        """
 | 
						|
        npfunc = getattr(np, self.__name__, None)
 | 
						|
        doc = getattr(npfunc, '__doc__', None)
 | 
						|
        if doc:
 | 
						|
            sig = self.__name__ + ma.get_object_signature(npfunc)
 | 
						|
            doc = ma.doc_note(doc, "The function is applied to both the _data "
 | 
						|
                                   "and the _mask, if any.")
 | 
						|
            return '\n\n'.join((sig, doc))
 | 
						|
        return
 | 
						|
 | 
						|
    def __call__(self, *args, **params):
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
class _fromnxfunction_single(_fromnxfunction):
 | 
						|
    """
 | 
						|
    A version of `_fromnxfunction` that is called with a single array
 | 
						|
    argument followed by auxiliary args that are passed verbatim for
 | 
						|
    both the data and mask calls.
 | 
						|
    """
 | 
						|
    def __call__(self, x, *args, **params):
 | 
						|
        func = getattr(np, self.__name__)
 | 
						|
        if isinstance(x, ndarray):
 | 
						|
            _d = func(x.__array__(), *args, **params)
 | 
						|
            _m = func(getmaskarray(x), *args, **params)
 | 
						|
            return masked_array(_d, mask=_m)
 | 
						|
        else:
 | 
						|
            _d = func(np.asarray(x), *args, **params)
 | 
						|
            _m = func(getmaskarray(x), *args, **params)
 | 
						|
            return masked_array(_d, mask=_m)
 | 
						|
 | 
						|
 | 
						|
class _fromnxfunction_seq(_fromnxfunction):
 | 
						|
    """
 | 
						|
    A version of `_fromnxfunction` that is called with a single sequence
 | 
						|
    of arrays followed by auxiliary args that are passed verbatim for
 | 
						|
    both the data and mask calls.
 | 
						|
    """
 | 
						|
    def __call__(self, x, *args, **params):
 | 
						|
        func = getattr(np, self.__name__)
 | 
						|
        _d = func(tuple([np.asarray(a) for a in x]), *args, **params)
 | 
						|
        _m = func(tuple([getmaskarray(a) for a in x]), *args, **params)
 | 
						|
        return masked_array(_d, mask=_m)
 | 
						|
 | 
						|
 | 
						|
class _fromnxfunction_args(_fromnxfunction):
 | 
						|
    """
 | 
						|
    A version of `_fromnxfunction` that is called with multiple array
 | 
						|
    arguments. The first non-array-like input marks the beginning of the
 | 
						|
    arguments that are passed verbatim for both the data and mask calls.
 | 
						|
    Array arguments are processed independently and the results are
 | 
						|
    returned in a list. If only one array is found, the return value is
 | 
						|
    just the processed array instead of a list.
 | 
						|
    """
 | 
						|
    def __call__(self, *args, **params):
 | 
						|
        func = getattr(np, self.__name__)
 | 
						|
        arrays = []
 | 
						|
        args = list(args)
 | 
						|
        while len(args) > 0 and issequence(args[0]):
 | 
						|
            arrays.append(args.pop(0))
 | 
						|
        res = []
 | 
						|
        for x in arrays:
 | 
						|
            _d = func(np.asarray(x), *args, **params)
 | 
						|
            _m = func(getmaskarray(x), *args, **params)
 | 
						|
            res.append(masked_array(_d, mask=_m))
 | 
						|
        if len(arrays) == 1:
 | 
						|
            return res[0]
 | 
						|
        return res
 | 
						|
 | 
						|
 | 
						|
class _fromnxfunction_allargs(_fromnxfunction):
 | 
						|
    """
 | 
						|
    A version of `_fromnxfunction` that is called with multiple array
 | 
						|
    arguments. Similar to `_fromnxfunction_args` except that all args
 | 
						|
    are converted to arrays even if they are not so already. This makes
 | 
						|
    it possible to process scalars as 1-D arrays. Only keyword arguments
 | 
						|
    are passed through verbatim for the data and mask calls. Arrays
 | 
						|
    arguments are processed independently and the results are returned
 | 
						|
    in a list. If only one arg is present, the return value is just the
 | 
						|
    processed array instead of a list.
 | 
						|
    """
 | 
						|
    def __call__(self, *args, **params):
 | 
						|
        func = getattr(np, self.__name__)
 | 
						|
        res = []
 | 
						|
        for x in args:
 | 
						|
            _d = func(np.asarray(x), **params)
 | 
						|
            _m = func(getmaskarray(x), **params)
 | 
						|
            res.append(masked_array(_d, mask=_m))
 | 
						|
        if len(args) == 1:
 | 
						|
            return res[0]
 | 
						|
        return res
 | 
						|
 | 
						|
 | 
						|
atleast_1d = _fromnxfunction_allargs('atleast_1d')
 | 
						|
atleast_2d = _fromnxfunction_allargs('atleast_2d')
 | 
						|
atleast_3d = _fromnxfunction_allargs('atleast_3d')
 | 
						|
 | 
						|
vstack = row_stack = _fromnxfunction_seq('vstack')
 | 
						|
hstack = _fromnxfunction_seq('hstack')
 | 
						|
column_stack = _fromnxfunction_seq('column_stack')
 | 
						|
dstack = _fromnxfunction_seq('dstack')
 | 
						|
stack = _fromnxfunction_seq('stack')
 | 
						|
 | 
						|
hsplit = _fromnxfunction_single('hsplit')
 | 
						|
 | 
						|
diagflat = _fromnxfunction_single('diagflat')
 | 
						|
 | 
						|
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
#----
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
def flatten_inplace(seq):
 | 
						|
    """Flatten a sequence in place."""
 | 
						|
    k = 0
 | 
						|
    while (k != len(seq)):
 | 
						|
        while hasattr(seq[k], '__iter__'):
 | 
						|
            seq[k:(k + 1)] = seq[k]
 | 
						|
        k += 1
 | 
						|
    return seq
 | 
						|
 | 
						|
 | 
						|
def apply_along_axis(func1d, axis, arr, *args, **kwargs):
 | 
						|
    """
 | 
						|
    (This docstring should be overwritten)
 | 
						|
    """
 | 
						|
    arr = array(arr, copy=False, subok=True)
 | 
						|
    nd = arr.ndim
 | 
						|
    axis = normalize_axis_index(axis, nd)
 | 
						|
    ind = [0] * (nd - 1)
 | 
						|
    i = np.zeros(nd, 'O')
 | 
						|
    indlist = list(range(nd))
 | 
						|
    indlist.remove(axis)
 | 
						|
    i[axis] = slice(None, None)
 | 
						|
    outshape = np.asarray(arr.shape).take(indlist)
 | 
						|
    i.put(indlist, ind)
 | 
						|
    res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
 | 
						|
    #  if res is a number, then we have a smaller output array
 | 
						|
    asscalar = np.isscalar(res)
 | 
						|
    if not asscalar:
 | 
						|
        try:
 | 
						|
            len(res)
 | 
						|
        except TypeError:
 | 
						|
            asscalar = True
 | 
						|
    # Note: we shouldn't set the dtype of the output from the first result
 | 
						|
    # so we force the type to object, and build a list of dtypes.  We'll
 | 
						|
    # just take the largest, to avoid some downcasting
 | 
						|
    dtypes = []
 | 
						|
    if asscalar:
 | 
						|
        dtypes.append(np.asarray(res).dtype)
 | 
						|
        outarr = zeros(outshape, object)
 | 
						|
        outarr[tuple(ind)] = res
 | 
						|
        Ntot = np.product(outshape)
 | 
						|
        k = 1
 | 
						|
        while k < Ntot:
 | 
						|
            # increment the index
 | 
						|
            ind[-1] += 1
 | 
						|
            n = -1
 | 
						|
            while (ind[n] >= outshape[n]) and (n > (1 - nd)):
 | 
						|
                ind[n - 1] += 1
 | 
						|
                ind[n] = 0
 | 
						|
                n -= 1
 | 
						|
            i.put(indlist, ind)
 | 
						|
            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
 | 
						|
            outarr[tuple(ind)] = res
 | 
						|
            dtypes.append(asarray(res).dtype)
 | 
						|
            k += 1
 | 
						|
    else:
 | 
						|
        res = array(res, copy=False, subok=True)
 | 
						|
        j = i.copy()
 | 
						|
        j[axis] = ([slice(None, None)] * res.ndim)
 | 
						|
        j.put(indlist, ind)
 | 
						|
        Ntot = np.product(outshape)
 | 
						|
        holdshape = outshape
 | 
						|
        outshape = list(arr.shape)
 | 
						|
        outshape[axis] = res.shape
 | 
						|
        dtypes.append(asarray(res).dtype)
 | 
						|
        outshape = flatten_inplace(outshape)
 | 
						|
        outarr = zeros(outshape, object)
 | 
						|
        outarr[tuple(flatten_inplace(j.tolist()))] = res
 | 
						|
        k = 1
 | 
						|
        while k < Ntot:
 | 
						|
            # increment the index
 | 
						|
            ind[-1] += 1
 | 
						|
            n = -1
 | 
						|
            while (ind[n] >= holdshape[n]) and (n > (1 - nd)):
 | 
						|
                ind[n - 1] += 1
 | 
						|
                ind[n] = 0
 | 
						|
                n -= 1
 | 
						|
            i.put(indlist, ind)
 | 
						|
            j.put(indlist, ind)
 | 
						|
            res = func1d(arr[tuple(i.tolist())], *args, **kwargs)
 | 
						|
            outarr[tuple(flatten_inplace(j.tolist()))] = res
 | 
						|
            dtypes.append(asarray(res).dtype)
 | 
						|
            k += 1
 | 
						|
    max_dtypes = np.dtype(np.asarray(dtypes).max())
 | 
						|
    if not hasattr(arr, '_mask'):
 | 
						|
        result = np.asarray(outarr, dtype=max_dtypes)
 | 
						|
    else:
 | 
						|
        result = asarray(outarr, dtype=max_dtypes)
 | 
						|
        result.fill_value = ma.default_fill_value(result)
 | 
						|
    return result
 | 
						|
apply_along_axis.__doc__ = np.apply_along_axis.__doc__
 | 
						|
 | 
						|
 | 
						|
def apply_over_axes(func, a, axes):
 | 
						|
    """
 | 
						|
    (This docstring will be overwritten)
 | 
						|
    """
 | 
						|
    val = asarray(a)
 | 
						|
    N = a.ndim
 | 
						|
    if array(axes).ndim == 0:
 | 
						|
        axes = (axes,)
 | 
						|
    for axis in axes:
 | 
						|
        if axis < 0:
 | 
						|
            axis = N + axis
 | 
						|
        args = (val, axis)
 | 
						|
        res = func(*args)
 | 
						|
        if res.ndim == val.ndim:
 | 
						|
            val = res
 | 
						|
        else:
 | 
						|
            res = ma.expand_dims(res, axis)
 | 
						|
            if res.ndim == val.ndim:
 | 
						|
                val = res
 | 
						|
            else:
 | 
						|
                raise ValueError("function is not returning "
 | 
						|
                        "an array of the correct shape")
 | 
						|
    return val
 | 
						|
 | 
						|
 | 
						|
if apply_over_axes.__doc__ is not None:
 | 
						|
    apply_over_axes.__doc__ = np.apply_over_axes.__doc__[
 | 
						|
        :np.apply_over_axes.__doc__.find('Notes')].rstrip() + \
 | 
						|
    """
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.arange(24).reshape(2,3,4)
 | 
						|
    >>> a[:,0,1] = np.ma.masked
 | 
						|
    >>> a[:,1,:] = np.ma.masked
 | 
						|
    >>> a
 | 
						|
    masked_array(
 | 
						|
      data=[[[0, --, 2, 3],
 | 
						|
             [--, --, --, --],
 | 
						|
             [8, 9, 10, 11]],
 | 
						|
            [[12, --, 14, 15],
 | 
						|
             [--, --, --, --],
 | 
						|
             [20, 21, 22, 23]]],
 | 
						|
      mask=[[[False,  True, False, False],
 | 
						|
             [ True,  True,  True,  True],
 | 
						|
             [False, False, False, False]],
 | 
						|
            [[False,  True, False, False],
 | 
						|
             [ True,  True,  True,  True],
 | 
						|
             [False, False, False, False]]],
 | 
						|
      fill_value=999999)
 | 
						|
    >>> np.ma.apply_over_axes(np.ma.sum, a, [0,2])
 | 
						|
    masked_array(
 | 
						|
      data=[[[46],
 | 
						|
             [--],
 | 
						|
             [124]]],
 | 
						|
      mask=[[[False],
 | 
						|
             [ True],
 | 
						|
             [False]]],
 | 
						|
      fill_value=999999)
 | 
						|
 | 
						|
    Tuple axis arguments to ufuncs are equivalent:
 | 
						|
 | 
						|
    >>> np.ma.sum(a, axis=(0,2)).reshape((1,-1,1))
 | 
						|
    masked_array(
 | 
						|
      data=[[[46],
 | 
						|
             [--],
 | 
						|
             [124]]],
 | 
						|
      mask=[[[False],
 | 
						|
             [ True],
 | 
						|
             [False]]],
 | 
						|
      fill_value=999999)
 | 
						|
    """
 | 
						|
 | 
						|
 | 
						|
def average(a, axis=None, weights=None, returned=False, *,
 | 
						|
            keepdims=np._NoValue):
 | 
						|
    """
 | 
						|
    Return the weighted average of array over the given axis.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        Data to be averaged.
 | 
						|
        Masked entries are not taken into account in the computation.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which to average `a`. If None, averaging is done over
 | 
						|
        the flattened array.
 | 
						|
    weights : array_like, optional
 | 
						|
        The importance that each element has in the computation of the average.
 | 
						|
        The weights array can either be 1-D (in which case its length must be
 | 
						|
        the size of `a` along the given axis) or of the same shape as `a`.
 | 
						|
        If ``weights=None``, then all data in `a` are assumed to have a
 | 
						|
        weight equal to one.  The 1-D calculation is::
 | 
						|
 | 
						|
            avg = sum(a * weights) / sum(weights)
 | 
						|
 | 
						|
        The only constraint on `weights` is that `sum(weights)` must not be 0.
 | 
						|
    returned : bool, optional
 | 
						|
        Flag indicating whether a tuple ``(result, sum of weights)``
 | 
						|
        should be returned as output (True), or just the result (False).
 | 
						|
        Default is False.
 | 
						|
    keepdims : bool, optional
 | 
						|
        If this is set to True, the axes which are reduced are left
 | 
						|
        in the result as dimensions with size one. With this option,
 | 
						|
        the result will broadcast correctly against the original `a`.
 | 
						|
        *Note:* `keepdims` will not work with instances of `numpy.matrix`
 | 
						|
        or other classes whose methods do not support `keepdims`.
 | 
						|
 | 
						|
        .. versionadded:: 1.23.0
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    average, [sum_of_weights] : (tuple of) scalar or MaskedArray
 | 
						|
        The average along the specified axis. When returned is `True`,
 | 
						|
        return a tuple with the average as the first element and the sum
 | 
						|
        of the weights as the second element. The return type is `np.float64`
 | 
						|
        if `a` is of integer type and floats smaller than `float64`, or the
 | 
						|
        input data-type, otherwise. If returned, `sum_of_weights` is always
 | 
						|
        `float64`.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.array([1., 2., 3., 4.], mask=[False, False, True, True])
 | 
						|
    >>> np.ma.average(a, weights=[3, 1, 0, 0])
 | 
						|
    1.25
 | 
						|
 | 
						|
    >>> x = np.ma.arange(6.).reshape(3, 2)
 | 
						|
    >>> x
 | 
						|
    masked_array(
 | 
						|
      data=[[0., 1.],
 | 
						|
            [2., 3.],
 | 
						|
            [4., 5.]],
 | 
						|
      mask=False,
 | 
						|
      fill_value=1e+20)
 | 
						|
    >>> avg, sumweights = np.ma.average(x, axis=0, weights=[1, 2, 3],
 | 
						|
    ...                                 returned=True)
 | 
						|
    >>> avg
 | 
						|
    masked_array(data=[2.6666666666666665, 3.6666666666666665],
 | 
						|
                 mask=[False, False],
 | 
						|
           fill_value=1e+20)
 | 
						|
 | 
						|
    With ``keepdims=True``, the following result has shape (3, 1).
 | 
						|
 | 
						|
    >>> np.ma.average(x, axis=1, keepdims=True)
 | 
						|
    masked_array(
 | 
						|
      data=[[0.5],
 | 
						|
            [2.5],
 | 
						|
            [4.5]],
 | 
						|
      mask=False,
 | 
						|
      fill_value=1e+20)
 | 
						|
    """
 | 
						|
    a = asarray(a)
 | 
						|
    m = getmask(a)
 | 
						|
 | 
						|
    # inspired by 'average' in numpy/lib/function_base.py
 | 
						|
 | 
						|
    if keepdims is np._NoValue:
 | 
						|
        # Don't pass on the keepdims argument if one wasn't given.
 | 
						|
        keepdims_kw = {}
 | 
						|
    else:
 | 
						|
        keepdims_kw = {'keepdims': keepdims}
 | 
						|
 | 
						|
    if weights is None:
 | 
						|
        avg = a.mean(axis, **keepdims_kw)
 | 
						|
        scl = avg.dtype.type(a.count(axis))
 | 
						|
    else:
 | 
						|
        wgt = asarray(weights)
 | 
						|
 | 
						|
        if issubclass(a.dtype.type, (np.integer, np.bool_)):
 | 
						|
            result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')
 | 
						|
        else:
 | 
						|
            result_dtype = np.result_type(a.dtype, wgt.dtype)
 | 
						|
 | 
						|
        # Sanity checks
 | 
						|
        if a.shape != wgt.shape:
 | 
						|
            if axis is None:
 | 
						|
                raise TypeError(
 | 
						|
                    "Axis must be specified when shapes of a and weights "
 | 
						|
                    "differ.")
 | 
						|
            if wgt.ndim != 1:
 | 
						|
                raise TypeError(
 | 
						|
                    "1D weights expected when shapes of a and weights differ.")
 | 
						|
            if wgt.shape[0] != a.shape[axis]:
 | 
						|
                raise ValueError(
 | 
						|
                    "Length of weights not compatible with specified axis.")
 | 
						|
 | 
						|
            # setup wgt to broadcast along axis
 | 
						|
            wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape, subok=True)
 | 
						|
            wgt = wgt.swapaxes(-1, axis)
 | 
						|
 | 
						|
        if m is not nomask:
 | 
						|
            wgt = wgt*(~a.mask)
 | 
						|
            wgt.mask |= a.mask
 | 
						|
 | 
						|
        scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw)
 | 
						|
        avg = np.multiply(a, wgt,
 | 
						|
                          dtype=result_dtype).sum(axis, **keepdims_kw) / scl
 | 
						|
 | 
						|
    if returned:
 | 
						|
        if scl.shape != avg.shape:
 | 
						|
            scl = np.broadcast_to(scl, avg.shape).copy()
 | 
						|
        return avg, scl
 | 
						|
    else:
 | 
						|
        return avg
 | 
						|
 | 
						|
 | 
						|
def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
 | 
						|
    """
 | 
						|
    Compute the median along the specified axis.
 | 
						|
 | 
						|
    Returns the median of the array elements.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        Input array or object that can be converted to an array.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which the medians are computed. The default (None) is
 | 
						|
        to compute the median along a flattened version of the array.
 | 
						|
    out : ndarray, optional
 | 
						|
        Alternative output array in which to place the result. It must
 | 
						|
        have the same shape and buffer length as the expected output
 | 
						|
        but the type will be cast if necessary.
 | 
						|
    overwrite_input : bool, optional
 | 
						|
        If True, then allow use of memory of input array (a) for
 | 
						|
        calculations. The input array will be modified by the call to
 | 
						|
        median. This will save memory when you do not need to preserve
 | 
						|
        the contents of the input array. Treat the input as undefined,
 | 
						|
        but it will probably be fully or partially sorted. Default is
 | 
						|
        False. Note that, if `overwrite_input` is True, and the input
 | 
						|
        is not already an `ndarray`, an error will be raised.
 | 
						|
    keepdims : bool, optional
 | 
						|
        If this is set to True, the axes which are reduced are left
 | 
						|
        in the result as dimensions with size one. With this option,
 | 
						|
        the result will broadcast correctly against the input array.
 | 
						|
 | 
						|
        .. versionadded:: 1.10.0
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    median : ndarray
 | 
						|
        A new array holding the result is returned unless out is
 | 
						|
        specified, in which case a reference to out is returned.
 | 
						|
        Return data-type is `float64` for integers and floats smaller than
 | 
						|
        `float64`, or the input data-type, otherwise.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    mean
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    Given a vector ``V`` with ``N`` non masked values, the median of ``V``
 | 
						|
    is the middle value of a sorted copy of ``V`` (``Vs``) - i.e.
 | 
						|
    ``Vs[(N-1)/2]``, when ``N`` is odd, or ``{Vs[N/2 - 1] + Vs[N/2]}/2``
 | 
						|
    when ``N`` is even.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> x = np.ma.array(np.arange(8), mask=[0]*4 + [1]*4)
 | 
						|
    >>> np.ma.median(x)
 | 
						|
    1.5
 | 
						|
 | 
						|
    >>> x = np.ma.array(np.arange(10).reshape(2, 5), mask=[0]*6 + [1]*4)
 | 
						|
    >>> np.ma.median(x)
 | 
						|
    2.5
 | 
						|
    >>> np.ma.median(x, axis=-1, overwrite_input=True)
 | 
						|
    masked_array(data=[2.0, 5.0],
 | 
						|
                 mask=[False, False],
 | 
						|
           fill_value=1e+20)
 | 
						|
 | 
						|
    """
 | 
						|
    if not hasattr(a, 'mask'):
 | 
						|
        m = np.median(getdata(a, subok=True), axis=axis,
 | 
						|
                      out=out, overwrite_input=overwrite_input,
 | 
						|
                      keepdims=keepdims)
 | 
						|
        if isinstance(m, np.ndarray) and 1 <= m.ndim:
 | 
						|
            return masked_array(m, copy=False)
 | 
						|
        else:
 | 
						|
            return m
 | 
						|
 | 
						|
    return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out,
 | 
						|
                    overwrite_input=overwrite_input)
 | 
						|
 | 
						|
 | 
						|
def _median(a, axis=None, out=None, overwrite_input=False):
 | 
						|
    # when an unmasked NaN is present return it, so we need to sort the NaN
 | 
						|
    # values behind the mask
 | 
						|
    if np.issubdtype(a.dtype, np.inexact):
 | 
						|
        fill_value = np.inf
 | 
						|
    else:
 | 
						|
        fill_value = None
 | 
						|
    if overwrite_input:
 | 
						|
        if axis is None:
 | 
						|
            asorted = a.ravel()
 | 
						|
            asorted.sort(fill_value=fill_value)
 | 
						|
        else:
 | 
						|
            a.sort(axis=axis, fill_value=fill_value)
 | 
						|
            asorted = a
 | 
						|
    else:
 | 
						|
        asorted = sort(a, axis=axis, fill_value=fill_value)
 | 
						|
 | 
						|
    if axis is None:
 | 
						|
        axis = 0
 | 
						|
    else:
 | 
						|
        axis = normalize_axis_index(axis, asorted.ndim)
 | 
						|
 | 
						|
    if asorted.shape[axis] == 0:
 | 
						|
        # for empty axis integer indices fail so use slicing to get same result
 | 
						|
        # as median (which is mean of empty slice = nan)
 | 
						|
        indexer = [slice(None)] * asorted.ndim
 | 
						|
        indexer[axis] = slice(0, 0)
 | 
						|
        indexer = tuple(indexer)
 | 
						|
        return np.ma.mean(asorted[indexer], axis=axis, out=out)
 | 
						|
 | 
						|
    if asorted.ndim == 1:
 | 
						|
        idx, odd = divmod(count(asorted), 2)
 | 
						|
        mid = asorted[idx + odd - 1:idx + 1]
 | 
						|
        if np.issubdtype(asorted.dtype, np.inexact) and asorted.size > 0:
 | 
						|
            # avoid inf / x = masked
 | 
						|
            s = mid.sum(out=out)
 | 
						|
            if not odd:
 | 
						|
                s = np.true_divide(s, 2., casting='safe', out=out)
 | 
						|
            s = np.lib.utils._median_nancheck(asorted, s, axis)
 | 
						|
        else:
 | 
						|
            s = mid.mean(out=out)
 | 
						|
 | 
						|
        # if result is masked either the input contained enough
 | 
						|
        # minimum_fill_value so that it would be the median or all values
 | 
						|
        # masked
 | 
						|
        if np.ma.is_masked(s) and not np.all(asorted.mask):
 | 
						|
            return np.ma.minimum_fill_value(asorted)
 | 
						|
        return s
 | 
						|
 | 
						|
    counts = count(asorted, axis=axis, keepdims=True)
 | 
						|
    h = counts // 2
 | 
						|
 | 
						|
    # duplicate high if odd number of elements so mean does nothing
 | 
						|
    odd = counts % 2 == 1
 | 
						|
    l = np.where(odd, h, h-1)
 | 
						|
 | 
						|
    lh = np.concatenate([l,h], axis=axis)
 | 
						|
 | 
						|
    # get low and high median
 | 
						|
    low_high = np.take_along_axis(asorted, lh, axis=axis)
 | 
						|
 | 
						|
    def replace_masked(s):
 | 
						|
        # Replace masked entries with minimum_full_value unless it all values
 | 
						|
        # are masked. This is required as the sort order of values equal or
 | 
						|
        # larger than the fill value is undefined and a valid value placed
 | 
						|
        # elsewhere, e.g. [4, --, inf].
 | 
						|
        if np.ma.is_masked(s):
 | 
						|
            rep = (~np.all(asorted.mask, axis=axis, keepdims=True)) & s.mask
 | 
						|
            s.data[rep] = np.ma.minimum_fill_value(asorted)
 | 
						|
            s.mask[rep] = False
 | 
						|
 | 
						|
    replace_masked(low_high)
 | 
						|
 | 
						|
    if np.issubdtype(asorted.dtype, np.inexact):
 | 
						|
        # avoid inf / x = masked
 | 
						|
        s = np.ma.sum(low_high, axis=axis, out=out)
 | 
						|
        np.true_divide(s.data, 2., casting='unsafe', out=s.data)
 | 
						|
 | 
						|
        s = np.lib.utils._median_nancheck(asorted, s, axis)
 | 
						|
    else:
 | 
						|
        s = np.ma.mean(low_high, axis=axis, out=out)
 | 
						|
 | 
						|
    return s
 | 
						|
 | 
						|
 | 
						|
def compress_nd(x, axis=None):
 | 
						|
    """Suppress slices from multiple dimensions which contain masked values.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    x : array_like, MaskedArray
 | 
						|
        The array to operate on. If not a MaskedArray instance (or if no array
 | 
						|
        elements are masked), `x` is interpreted as a MaskedArray with `mask`
 | 
						|
        set to `nomask`.
 | 
						|
    axis : tuple of ints or int, optional
 | 
						|
        Which dimensions to suppress slices from can be configured with this
 | 
						|
        parameter.
 | 
						|
        - If axis is a tuple of ints, those are the axes to suppress slices from.
 | 
						|
        - If axis is an int, then that is the only axis to suppress slices from.
 | 
						|
        - If axis is None, all axis are selected.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    compress_array : ndarray
 | 
						|
        The compressed array.
 | 
						|
    """
 | 
						|
    x = asarray(x)
 | 
						|
    m = getmask(x)
 | 
						|
    # Set axis to tuple of ints
 | 
						|
    if axis is None:
 | 
						|
        axis = tuple(range(x.ndim))
 | 
						|
    else:
 | 
						|
        axis = normalize_axis_tuple(axis, x.ndim)
 | 
						|
 | 
						|
    # Nothing is masked: return x
 | 
						|
    if m is nomask or not m.any():
 | 
						|
        return x._data
 | 
						|
    # All is masked: return empty
 | 
						|
    if m.all():
 | 
						|
        return nxarray([])
 | 
						|
    # Filter elements through boolean indexing
 | 
						|
    data = x._data
 | 
						|
    for ax in axis:
 | 
						|
        axes = tuple(list(range(ax)) + list(range(ax + 1, x.ndim)))
 | 
						|
        data = data[(slice(None),)*ax + (~m.any(axis=axes),)]
 | 
						|
    return data
 | 
						|
 | 
						|
 | 
						|
def compress_rowcols(x, axis=None):
 | 
						|
    """
 | 
						|
    Suppress the rows and/or columns of a 2-D array that contain
 | 
						|
    masked values.
 | 
						|
 | 
						|
    The suppression behavior is selected with the `axis` parameter.
 | 
						|
 | 
						|
    - If axis is None, both rows and columns are suppressed.
 | 
						|
    - If axis is 0, only rows are suppressed.
 | 
						|
    - If axis is 1 or -1, only columns are suppressed.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    x : array_like, MaskedArray
 | 
						|
        The array to operate on.  If not a MaskedArray instance (or if no array
 | 
						|
        elements are masked), `x` is interpreted as a MaskedArray with
 | 
						|
        `mask` set to `nomask`. Must be a 2D array.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which to perform the operation. Default is None.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    compressed_array : ndarray
 | 
						|
        The compressed array.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> x = np.ma.array(np.arange(9).reshape(3, 3), mask=[[1, 0, 0],
 | 
						|
    ...                                                   [1, 0, 0],
 | 
						|
    ...                                                   [0, 0, 0]])
 | 
						|
    >>> x
 | 
						|
    masked_array(
 | 
						|
      data=[[--, 1, 2],
 | 
						|
            [--, 4, 5],
 | 
						|
            [6, 7, 8]],
 | 
						|
      mask=[[ True, False, False],
 | 
						|
            [ True, False, False],
 | 
						|
            [False, False, False]],
 | 
						|
      fill_value=999999)
 | 
						|
 | 
						|
    >>> np.ma.compress_rowcols(x)
 | 
						|
    array([[7, 8]])
 | 
						|
    >>> np.ma.compress_rowcols(x, 0)
 | 
						|
    array([[6, 7, 8]])
 | 
						|
    >>> np.ma.compress_rowcols(x, 1)
 | 
						|
    array([[1, 2],
 | 
						|
           [4, 5],
 | 
						|
           [7, 8]])
 | 
						|
 | 
						|
    """
 | 
						|
    if asarray(x).ndim != 2:
 | 
						|
        raise NotImplementedError("compress_rowcols works for 2D arrays only.")
 | 
						|
    return compress_nd(x, axis=axis)
 | 
						|
 | 
						|
 | 
						|
def compress_rows(a):
 | 
						|
    """
 | 
						|
    Suppress whole rows of a 2-D array that contain masked values.
 | 
						|
 | 
						|
    This is equivalent to ``np.ma.compress_rowcols(a, 0)``, see
 | 
						|
    `compress_rowcols` for details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    compress_rowcols
 | 
						|
 | 
						|
    """
 | 
						|
    a = asarray(a)
 | 
						|
    if a.ndim != 2:
 | 
						|
        raise NotImplementedError("compress_rows works for 2D arrays only.")
 | 
						|
    return compress_rowcols(a, 0)
 | 
						|
 | 
						|
 | 
						|
def compress_cols(a):
 | 
						|
    """
 | 
						|
    Suppress whole columns of a 2-D array that contain masked values.
 | 
						|
 | 
						|
    This is equivalent to ``np.ma.compress_rowcols(a, 1)``, see
 | 
						|
    `compress_rowcols` for details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    compress_rowcols
 | 
						|
 | 
						|
    """
 | 
						|
    a = asarray(a)
 | 
						|
    if a.ndim != 2:
 | 
						|
        raise NotImplementedError("compress_cols works for 2D arrays only.")
 | 
						|
    return compress_rowcols(a, 1)
 | 
						|
 | 
						|
 | 
						|
def mask_rows(a, axis=np._NoValue):
 | 
						|
    """
 | 
						|
    Mask rows of a 2D array that contain masked values.
 | 
						|
 | 
						|
    This function is a shortcut to ``mask_rowcols`` with `axis` equal to 0.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    mask_rowcols : Mask rows and/or columns of a 2D array.
 | 
						|
    masked_where : Mask where a condition is met.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> a = np.zeros((3, 3), dtype=int)
 | 
						|
    >>> a[1, 1] = 1
 | 
						|
    >>> a
 | 
						|
    array([[0, 0, 0],
 | 
						|
           [0, 1, 0],
 | 
						|
           [0, 0, 0]])
 | 
						|
    >>> a = ma.masked_equal(a, 1)
 | 
						|
    >>> a
 | 
						|
    masked_array(
 | 
						|
      data=[[0, 0, 0],
 | 
						|
            [0, --, 0],
 | 
						|
            [0, 0, 0]],
 | 
						|
      mask=[[False, False, False],
 | 
						|
            [False,  True, False],
 | 
						|
            [False, False, False]],
 | 
						|
      fill_value=1)
 | 
						|
 | 
						|
    >>> ma.mask_rows(a)
 | 
						|
    masked_array(
 | 
						|
      data=[[0, 0, 0],
 | 
						|
            [--, --, --],
 | 
						|
            [0, 0, 0]],
 | 
						|
      mask=[[False, False, False],
 | 
						|
            [ True,  True,  True],
 | 
						|
            [False, False, False]],
 | 
						|
      fill_value=1)
 | 
						|
 | 
						|
    """
 | 
						|
    if axis is not np._NoValue:
 | 
						|
        # remove the axis argument when this deprecation expires
 | 
						|
        # NumPy 1.18.0, 2019-11-28
 | 
						|
        warnings.warn(
 | 
						|
            "The axis argument has always been ignored, in future passing it "
 | 
						|
            "will raise TypeError", DeprecationWarning, stacklevel=2)
 | 
						|
    return mask_rowcols(a, 0)
 | 
						|
 | 
						|
 | 
						|
def mask_cols(a, axis=np._NoValue):
 | 
						|
    """
 | 
						|
    Mask columns of a 2D array that contain masked values.
 | 
						|
 | 
						|
    This function is a shortcut to ``mask_rowcols`` with `axis` equal to 1.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    mask_rowcols : Mask rows and/or columns of a 2D array.
 | 
						|
    masked_where : Mask where a condition is met.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> a = np.zeros((3, 3), dtype=int)
 | 
						|
    >>> a[1, 1] = 1
 | 
						|
    >>> a
 | 
						|
    array([[0, 0, 0],
 | 
						|
           [0, 1, 0],
 | 
						|
           [0, 0, 0]])
 | 
						|
    >>> a = ma.masked_equal(a, 1)
 | 
						|
    >>> a
 | 
						|
    masked_array(
 | 
						|
      data=[[0, 0, 0],
 | 
						|
            [0, --, 0],
 | 
						|
            [0, 0, 0]],
 | 
						|
      mask=[[False, False, False],
 | 
						|
            [False,  True, False],
 | 
						|
            [False, False, False]],
 | 
						|
      fill_value=1)
 | 
						|
    >>> ma.mask_cols(a)
 | 
						|
    masked_array(
 | 
						|
      data=[[0, --, 0],
 | 
						|
            [0, --, 0],
 | 
						|
            [0, --, 0]],
 | 
						|
      mask=[[False,  True, False],
 | 
						|
            [False,  True, False],
 | 
						|
            [False,  True, False]],
 | 
						|
      fill_value=1)
 | 
						|
 | 
						|
    """
 | 
						|
    if axis is not np._NoValue:
 | 
						|
        # remove the axis argument when this deprecation expires
 | 
						|
        # NumPy 1.18.0, 2019-11-28
 | 
						|
        warnings.warn(
 | 
						|
            "The axis argument has always been ignored, in future passing it "
 | 
						|
            "will raise TypeError", DeprecationWarning, stacklevel=2)
 | 
						|
    return mask_rowcols(a, 1)
 | 
						|
 | 
						|
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
#---- --- arraysetops ---
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
 | 
						|
def ediff1d(arr, to_end=None, to_begin=None):
 | 
						|
    """
 | 
						|
    Compute the differences between consecutive elements of an array.
 | 
						|
 | 
						|
    This function is the equivalent of `numpy.ediff1d` that takes masked
 | 
						|
    values into account, see `numpy.ediff1d` for details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.ediff1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    """
 | 
						|
    arr = ma.asanyarray(arr).flat
 | 
						|
    ed = arr[1:] - arr[:-1]
 | 
						|
    arrays = [ed]
 | 
						|
    #
 | 
						|
    if to_begin is not None:
 | 
						|
        arrays.insert(0, to_begin)
 | 
						|
    if to_end is not None:
 | 
						|
        arrays.append(to_end)
 | 
						|
    #
 | 
						|
    if len(arrays) != 1:
 | 
						|
        # We'll save ourselves a copy of a potentially large array in the common
 | 
						|
        # case where neither to_begin or to_end was given.
 | 
						|
        ed = hstack(arrays)
 | 
						|
    #
 | 
						|
    return ed
 | 
						|
 | 
						|
 | 
						|
def unique(ar1, return_index=False, return_inverse=False):
 | 
						|
    """
 | 
						|
    Finds the unique elements of an array.
 | 
						|
 | 
						|
    Masked values are considered the same element (masked). The output array
 | 
						|
    is always a masked array. See `numpy.unique` for more details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.unique : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> import numpy.ma as ma
 | 
						|
    >>> a = [1, 2, 1000, 2, 3]
 | 
						|
    >>> mask = [0, 0, 1, 0, 0]
 | 
						|
    >>> masked_a = ma.masked_array(a, mask)
 | 
						|
    >>> masked_a
 | 
						|
    masked_array(data=[1, 2, --, 2, 3],
 | 
						|
                mask=[False, False,  True, False, False],
 | 
						|
        fill_value=999999)
 | 
						|
    >>> ma.unique(masked_a)
 | 
						|
    masked_array(data=[1, 2, 3, --],
 | 
						|
                mask=[False, False, False,  True],
 | 
						|
        fill_value=999999)
 | 
						|
    >>> ma.unique(masked_a, return_index=True)
 | 
						|
    (masked_array(data=[1, 2, 3, --],
 | 
						|
                mask=[False, False, False,  True],
 | 
						|
        fill_value=999999), array([0, 1, 4, 2]))
 | 
						|
    >>> ma.unique(masked_a, return_inverse=True)
 | 
						|
    (masked_array(data=[1, 2, 3, --],
 | 
						|
                mask=[False, False, False,  True],
 | 
						|
        fill_value=999999), array([0, 1, 3, 1, 2]))
 | 
						|
    >>> ma.unique(masked_a, return_index=True, return_inverse=True)
 | 
						|
    (masked_array(data=[1, 2, 3, --],
 | 
						|
                mask=[False, False, False,  True],
 | 
						|
        fill_value=999999), array([0, 1, 4, 2]), array([0, 1, 3, 1, 2]))
 | 
						|
    """
 | 
						|
    output = np.unique(ar1,
 | 
						|
                       return_index=return_index,
 | 
						|
                       return_inverse=return_inverse)
 | 
						|
    if isinstance(output, tuple):
 | 
						|
        output = list(output)
 | 
						|
        output[0] = output[0].view(MaskedArray)
 | 
						|
        output = tuple(output)
 | 
						|
    else:
 | 
						|
        output = output.view(MaskedArray)
 | 
						|
    return output
 | 
						|
 | 
						|
 | 
						|
def intersect1d(ar1, ar2, assume_unique=False):
 | 
						|
    """
 | 
						|
    Returns the unique elements common to both arrays.
 | 
						|
 | 
						|
    Masked values are considered equal one to the other.
 | 
						|
    The output is always a masked array.
 | 
						|
 | 
						|
    See `numpy.intersect1d` for more details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.intersect1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> x = np.ma.array([1, 3, 3, 3], mask=[0, 0, 0, 1])
 | 
						|
    >>> y = np.ma.array([3, 1, 1, 1], mask=[0, 0, 0, 1])
 | 
						|
    >>> np.ma.intersect1d(x, y)
 | 
						|
    masked_array(data=[1, 3, --],
 | 
						|
                 mask=[False, False,  True],
 | 
						|
           fill_value=999999)
 | 
						|
 | 
						|
    """
 | 
						|
    if assume_unique:
 | 
						|
        aux = ma.concatenate((ar1, ar2))
 | 
						|
    else:
 | 
						|
        # Might be faster than unique( intersect1d( ar1, ar2 ) )?
 | 
						|
        aux = ma.concatenate((unique(ar1), unique(ar2)))
 | 
						|
    aux.sort()
 | 
						|
    return aux[:-1][aux[1:] == aux[:-1]]
 | 
						|
 | 
						|
 | 
						|
def setxor1d(ar1, ar2, assume_unique=False):
 | 
						|
    """
 | 
						|
    Set exclusive-or of 1-D arrays with unique elements.
 | 
						|
 | 
						|
    The output is always a masked array. See `numpy.setxor1d` for more details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.setxor1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    """
 | 
						|
    if not assume_unique:
 | 
						|
        ar1 = unique(ar1)
 | 
						|
        ar2 = unique(ar2)
 | 
						|
 | 
						|
    aux = ma.concatenate((ar1, ar2))
 | 
						|
    if aux.size == 0:
 | 
						|
        return aux
 | 
						|
    aux.sort()
 | 
						|
    auxf = aux.filled()
 | 
						|
#    flag = ediff1d( aux, to_end = 1, to_begin = 1 ) == 0
 | 
						|
    flag = ma.concatenate(([True], (auxf[1:] != auxf[:-1]), [True]))
 | 
						|
#    flag2 = ediff1d( flag ) == 0
 | 
						|
    flag2 = (flag[1:] == flag[:-1])
 | 
						|
    return aux[flag2]
 | 
						|
 | 
						|
 | 
						|
def in1d(ar1, ar2, assume_unique=False, invert=False):
 | 
						|
    """
 | 
						|
    Test whether each element of an array is also present in a second
 | 
						|
    array.
 | 
						|
 | 
						|
    The output is always a masked array. See `numpy.in1d` for more details.
 | 
						|
 | 
						|
    We recommend using :func:`isin` instead of `in1d` for new code.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    isin       : Version of this function that preserves the shape of ar1.
 | 
						|
    numpy.in1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    .. versionadded:: 1.4.0
 | 
						|
 | 
						|
    """
 | 
						|
    if not assume_unique:
 | 
						|
        ar1, rev_idx = unique(ar1, return_inverse=True)
 | 
						|
        ar2 = unique(ar2)
 | 
						|
 | 
						|
    ar = ma.concatenate((ar1, ar2))
 | 
						|
    # We need this to be a stable sort, so always use 'mergesort'
 | 
						|
    # here. The values from the first array should always come before
 | 
						|
    # the values from the second array.
 | 
						|
    order = ar.argsort(kind='mergesort')
 | 
						|
    sar = ar[order]
 | 
						|
    if invert:
 | 
						|
        bool_ar = (sar[1:] != sar[:-1])
 | 
						|
    else:
 | 
						|
        bool_ar = (sar[1:] == sar[:-1])
 | 
						|
    flag = ma.concatenate((bool_ar, [invert]))
 | 
						|
    indx = order.argsort(kind='mergesort')[:len(ar1)]
 | 
						|
 | 
						|
    if assume_unique:
 | 
						|
        return flag[indx]
 | 
						|
    else:
 | 
						|
        return flag[indx][rev_idx]
 | 
						|
 | 
						|
 | 
						|
def isin(element, test_elements, assume_unique=False, invert=False):
 | 
						|
    """
 | 
						|
    Calculates `element in test_elements`, broadcasting over
 | 
						|
    `element` only.
 | 
						|
 | 
						|
    The output is always a masked array of the same shape as `element`.
 | 
						|
    See `numpy.isin` for more details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    in1d       : Flattened version of this function.
 | 
						|
    numpy.isin : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    .. versionadded:: 1.13.0
 | 
						|
 | 
						|
    """
 | 
						|
    element = ma.asarray(element)
 | 
						|
    return in1d(element, test_elements, assume_unique=assume_unique,
 | 
						|
                invert=invert).reshape(element.shape)
 | 
						|
 | 
						|
 | 
						|
def union1d(ar1, ar2):
 | 
						|
    """
 | 
						|
    Union of two arrays.
 | 
						|
 | 
						|
    The output is always a masked array. See `numpy.union1d` for more details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.union1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    """
 | 
						|
    return unique(ma.concatenate((ar1, ar2), axis=None))
 | 
						|
 | 
						|
 | 
						|
def setdiff1d(ar1, ar2, assume_unique=False):
 | 
						|
    """
 | 
						|
    Set difference of 1D arrays with unique elements.
 | 
						|
 | 
						|
    The output is always a masked array. See `numpy.setdiff1d` for more
 | 
						|
    details.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.setdiff1d : Equivalent function for ndarrays.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> x = np.ma.array([1, 2, 3, 4], mask=[0, 1, 0, 1])
 | 
						|
    >>> np.ma.setdiff1d(x, [1, 2])
 | 
						|
    masked_array(data=[3, --],
 | 
						|
                 mask=[False,  True],
 | 
						|
           fill_value=999999)
 | 
						|
 | 
						|
    """
 | 
						|
    if assume_unique:
 | 
						|
        ar1 = ma.asarray(ar1).ravel()
 | 
						|
    else:
 | 
						|
        ar1 = unique(ar1)
 | 
						|
        ar2 = unique(ar2)
 | 
						|
    return ar1[in1d(ar1, ar2, assume_unique=True, invert=True)]
 | 
						|
 | 
						|
 | 
						|
###############################################################################
 | 
						|
#                                Covariance                                   #
 | 
						|
###############################################################################
 | 
						|
 | 
						|
 | 
						|
def _covhelper(x, y=None, rowvar=True, allow_masked=True):
 | 
						|
    """
 | 
						|
    Private function for the computation of covariance and correlation
 | 
						|
    coefficients.
 | 
						|
 | 
						|
    """
 | 
						|
    x = ma.array(x, ndmin=2, copy=True, dtype=float)
 | 
						|
    xmask = ma.getmaskarray(x)
 | 
						|
    # Quick exit if we can't process masked data
 | 
						|
    if not allow_masked and xmask.any():
 | 
						|
        raise ValueError("Cannot process masked data.")
 | 
						|
    #
 | 
						|
    if x.shape[0] == 1:
 | 
						|
        rowvar = True
 | 
						|
    # Make sure that rowvar is either 0 or 1
 | 
						|
    rowvar = int(bool(rowvar))
 | 
						|
    axis = 1 - rowvar
 | 
						|
    if rowvar:
 | 
						|
        tup = (slice(None), None)
 | 
						|
    else:
 | 
						|
        tup = (None, slice(None))
 | 
						|
    #
 | 
						|
    if y is None:
 | 
						|
        xnotmask = np.logical_not(xmask).astype(int)
 | 
						|
    else:
 | 
						|
        y = array(y, copy=False, ndmin=2, dtype=float)
 | 
						|
        ymask = ma.getmaskarray(y)
 | 
						|
        if not allow_masked and ymask.any():
 | 
						|
            raise ValueError("Cannot process masked data.")
 | 
						|
        if xmask.any() or ymask.any():
 | 
						|
            if y.shape == x.shape:
 | 
						|
                # Define some common mask
 | 
						|
                common_mask = np.logical_or(xmask, ymask)
 | 
						|
                if common_mask is not nomask:
 | 
						|
                    xmask = x._mask = y._mask = ymask = common_mask
 | 
						|
                    x._sharedmask = False
 | 
						|
                    y._sharedmask = False
 | 
						|
        x = ma.concatenate((x, y), axis)
 | 
						|
        xnotmask = np.logical_not(np.concatenate((xmask, ymask), axis)).astype(int)
 | 
						|
    x -= x.mean(axis=rowvar)[tup]
 | 
						|
    return (x, xnotmask, rowvar)
 | 
						|
 | 
						|
 | 
						|
def cov(x, y=None, rowvar=True, bias=False, allow_masked=True, ddof=None):
 | 
						|
    """
 | 
						|
    Estimate the covariance matrix.
 | 
						|
 | 
						|
    Except for the handling of missing data this function does the same as
 | 
						|
    `numpy.cov`. For more details and examples, see `numpy.cov`.
 | 
						|
 | 
						|
    By default, masked values are recognized as such. If `x` and `y` have the
 | 
						|
    same shape, a common mask is allocated: if ``x[i,j]`` is masked, then
 | 
						|
    ``y[i,j]`` will also be masked.
 | 
						|
    Setting `allow_masked` to False will raise an exception if values are
 | 
						|
    missing in either of the input arrays.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    x : array_like
 | 
						|
        A 1-D or 2-D array containing multiple variables and observations.
 | 
						|
        Each row of `x` represents a variable, and each column a single
 | 
						|
        observation of all those variables. Also see `rowvar` below.
 | 
						|
    y : array_like, optional
 | 
						|
        An additional set of variables and observations. `y` has the same
 | 
						|
        shape as `x`.
 | 
						|
    rowvar : bool, optional
 | 
						|
        If `rowvar` is True (default), then each row represents a
 | 
						|
        variable, with observations in the columns. Otherwise, the relationship
 | 
						|
        is transposed: each column represents a variable, while the rows
 | 
						|
        contain observations.
 | 
						|
    bias : bool, optional
 | 
						|
        Default normalization (False) is by ``(N-1)``, where ``N`` is the
 | 
						|
        number of observations given (unbiased estimate). If `bias` is True,
 | 
						|
        then normalization is by ``N``. This keyword can be overridden by
 | 
						|
        the keyword ``ddof`` in numpy versions >= 1.5.
 | 
						|
    allow_masked : bool, optional
 | 
						|
        If True, masked values are propagated pair-wise: if a value is masked
 | 
						|
        in `x`, the corresponding value is masked in `y`.
 | 
						|
        If False, raises a `ValueError` exception when some values are missing.
 | 
						|
    ddof : {None, int}, optional
 | 
						|
        If not ``None`` normalization is by ``(N - ddof)``, where ``N`` is
 | 
						|
        the number of observations; this overrides the value implied by
 | 
						|
        ``bias``. The default value is ``None``.
 | 
						|
 | 
						|
        .. versionadded:: 1.5
 | 
						|
 | 
						|
    Raises
 | 
						|
    ------
 | 
						|
    ValueError
 | 
						|
        Raised if some values are missing and `allow_masked` is False.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.cov
 | 
						|
 | 
						|
    """
 | 
						|
    # Check inputs
 | 
						|
    if ddof is not None and ddof != int(ddof):
 | 
						|
        raise ValueError("ddof must be an integer")
 | 
						|
    # Set up ddof
 | 
						|
    if ddof is None:
 | 
						|
        if bias:
 | 
						|
            ddof = 0
 | 
						|
        else:
 | 
						|
            ddof = 1
 | 
						|
 | 
						|
    (x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)
 | 
						|
    if not rowvar:
 | 
						|
        fact = np.dot(xnotmask.T, xnotmask) * 1. - ddof
 | 
						|
        result = (dot(x.T, x.conj(), strict=False) / fact).squeeze()
 | 
						|
    else:
 | 
						|
        fact = np.dot(xnotmask, xnotmask.T) * 1. - ddof
 | 
						|
        result = (dot(x, x.T.conj(), strict=False) / fact).squeeze()
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, allow_masked=True,
 | 
						|
             ddof=np._NoValue):
 | 
						|
    """
 | 
						|
    Return Pearson product-moment correlation coefficients.
 | 
						|
 | 
						|
    Except for the handling of missing data this function does the same as
 | 
						|
    `numpy.corrcoef`. For more details and examples, see `numpy.corrcoef`.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    x : array_like
 | 
						|
        A 1-D or 2-D array containing multiple variables and observations.
 | 
						|
        Each row of `x` represents a variable, and each column a single
 | 
						|
        observation of all those variables. Also see `rowvar` below.
 | 
						|
    y : array_like, optional
 | 
						|
        An additional set of variables and observations. `y` has the same
 | 
						|
        shape as `x`.
 | 
						|
    rowvar : bool, optional
 | 
						|
        If `rowvar` is True (default), then each row represents a
 | 
						|
        variable, with observations in the columns. Otherwise, the relationship
 | 
						|
        is transposed: each column represents a variable, while the rows
 | 
						|
        contain observations.
 | 
						|
    bias : _NoValue, optional
 | 
						|
        Has no effect, do not use.
 | 
						|
 | 
						|
        .. deprecated:: 1.10.0
 | 
						|
    allow_masked : bool, optional
 | 
						|
        If True, masked values are propagated pair-wise: if a value is masked
 | 
						|
        in `x`, the corresponding value is masked in `y`.
 | 
						|
        If False, raises an exception.  Because `bias` is deprecated, this
 | 
						|
        argument needs to be treated as keyword only to avoid a warning.
 | 
						|
    ddof : _NoValue, optional
 | 
						|
        Has no effect, do not use.
 | 
						|
 | 
						|
        .. deprecated:: 1.10.0
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.corrcoef : Equivalent function in top-level NumPy module.
 | 
						|
    cov : Estimate the covariance matrix.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    This function accepts but discards arguments `bias` and `ddof`.  This is
 | 
						|
    for backwards compatibility with previous versions of this function.  These
 | 
						|
    arguments had no effect on the return values of the function and can be
 | 
						|
    safely ignored in this and previous versions of numpy.
 | 
						|
    """
 | 
						|
    msg = 'bias and ddof have no effect and are deprecated'
 | 
						|
    if bias is not np._NoValue or ddof is not np._NoValue:
 | 
						|
        # 2015-03-15, 1.10
 | 
						|
        warnings.warn(msg, DeprecationWarning, stacklevel=2)
 | 
						|
    # Get the data
 | 
						|
    (x, xnotmask, rowvar) = _covhelper(x, y, rowvar, allow_masked)
 | 
						|
    # Compute the covariance matrix
 | 
						|
    if not rowvar:
 | 
						|
        fact = np.dot(xnotmask.T, xnotmask) * 1.
 | 
						|
        c = (dot(x.T, x.conj(), strict=False) / fact).squeeze()
 | 
						|
    else:
 | 
						|
        fact = np.dot(xnotmask, xnotmask.T) * 1.
 | 
						|
        c = (dot(x, x.T.conj(), strict=False) / fact).squeeze()
 | 
						|
    # Check whether we have a scalar
 | 
						|
    try:
 | 
						|
        diag = ma.diagonal(c)
 | 
						|
    except ValueError:
 | 
						|
        return 1
 | 
						|
    #
 | 
						|
    if xnotmask.all():
 | 
						|
        _denom = ma.sqrt(ma.multiply.outer(diag, diag))
 | 
						|
    else:
 | 
						|
        _denom = diagflat(diag)
 | 
						|
        _denom._sharedmask = False  # We know return is always a copy
 | 
						|
        n = x.shape[1 - rowvar]
 | 
						|
        if rowvar:
 | 
						|
            for i in range(n - 1):
 | 
						|
                for j in range(i + 1, n):
 | 
						|
                    _x = mask_cols(vstack((x[i], x[j]))).var(axis=1)
 | 
						|
                    _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
 | 
						|
        else:
 | 
						|
            for i in range(n - 1):
 | 
						|
                for j in range(i + 1, n):
 | 
						|
                    _x = mask_cols(
 | 
						|
                            vstack((x[:, i], x[:, j]))).var(axis=1)
 | 
						|
                    _denom[i, j] = _denom[j, i] = ma.sqrt(ma.multiply.reduce(_x))
 | 
						|
    return c / _denom
 | 
						|
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
#---- --- Concatenation helpers ---
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
 | 
						|
class MAxisConcatenator(AxisConcatenator):
 | 
						|
    """
 | 
						|
    Translate slice objects to concatenation along an axis.
 | 
						|
 | 
						|
    For documentation on usage, see `mr_class`.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    mr_class
 | 
						|
 | 
						|
    """
 | 
						|
    concatenate = staticmethod(concatenate)
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def makemat(cls, arr):
 | 
						|
        # There used to be a view as np.matrix here, but we may eventually
 | 
						|
        # deprecate that class. In preparation, we use the unmasked version
 | 
						|
        # to construct the matrix (with copy=False for backwards compatibility
 | 
						|
        # with the .view)
 | 
						|
        data = super().makemat(arr.data, copy=False)
 | 
						|
        return array(data, mask=arr.mask)
 | 
						|
 | 
						|
    def __getitem__(self, key):
 | 
						|
        # matrix builder syntax, like 'a, b; c, d'
 | 
						|
        if isinstance(key, str):
 | 
						|
            raise MAError("Unavailable for masked array.")
 | 
						|
 | 
						|
        return super().__getitem__(key)
 | 
						|
 | 
						|
 | 
						|
class mr_class(MAxisConcatenator):
 | 
						|
    """
 | 
						|
    Translate slice objects to concatenation along the first axis.
 | 
						|
 | 
						|
    This is the masked array version of `lib.index_tricks.RClass`.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    lib.index_tricks.RClass
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> np.ma.mr_[np.ma.array([1,2,3]), 0, 0, np.ma.array([4,5,6])]
 | 
						|
    masked_array(data=[1, 2, 3, ..., 4, 5, 6],
 | 
						|
                 mask=False,
 | 
						|
           fill_value=999999)
 | 
						|
 | 
						|
    """
 | 
						|
    def __init__(self):
 | 
						|
        MAxisConcatenator.__init__(self, 0)
 | 
						|
 | 
						|
mr_ = mr_class()
 | 
						|
 | 
						|
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
#---- Find unmasked data ---
 | 
						|
#####--------------------------------------------------------------------------
 | 
						|
 | 
						|
def ndenumerate(a, compressed=True):
 | 
						|
    """
 | 
						|
    Multidimensional index iterator.
 | 
						|
 | 
						|
    Return an iterator yielding pairs of array coordinates and values,
 | 
						|
    skipping elements that are masked. With `compressed=False`,
 | 
						|
    `ma.masked` is yielded as the value of masked elements. This
 | 
						|
    behavior differs from that of `numpy.ndenumerate`, which yields the
 | 
						|
    value of the underlying data array.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    .. versionadded:: 1.23.0
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        An array with (possibly) masked elements.
 | 
						|
    compressed : bool, optional
 | 
						|
        If True (default), masked elements are skipped.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    numpy.ndenumerate : Equivalent function ignoring any mask.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.arange(9).reshape((3, 3))
 | 
						|
    >>> a[1, 0] = np.ma.masked
 | 
						|
    >>> a[1, 2] = np.ma.masked
 | 
						|
    >>> a[2, 1] = np.ma.masked
 | 
						|
    >>> a
 | 
						|
    masked_array(
 | 
						|
      data=[[0, 1, 2],
 | 
						|
            [--, 4, --],
 | 
						|
            [6, --, 8]],
 | 
						|
      mask=[[False, False, False],
 | 
						|
            [ True, False,  True],
 | 
						|
            [False,  True, False]],
 | 
						|
      fill_value=999999)
 | 
						|
    >>> for index, x in np.ma.ndenumerate(a):
 | 
						|
    ...     print(index, x)
 | 
						|
    (0, 0) 0
 | 
						|
    (0, 1) 1
 | 
						|
    (0, 2) 2
 | 
						|
    (1, 1) 4
 | 
						|
    (2, 0) 6
 | 
						|
    (2, 2) 8
 | 
						|
 | 
						|
    >>> for index, x in np.ma.ndenumerate(a, compressed=False):
 | 
						|
    ...     print(index, x)
 | 
						|
    (0, 0) 0
 | 
						|
    (0, 1) 1
 | 
						|
    (0, 2) 2
 | 
						|
    (1, 0) --
 | 
						|
    (1, 1) 4
 | 
						|
    (1, 2) --
 | 
						|
    (2, 0) 6
 | 
						|
    (2, 1) --
 | 
						|
    (2, 2) 8
 | 
						|
    """
 | 
						|
    for it, mask in zip(np.ndenumerate(a), getmaskarray(a).flat):
 | 
						|
        if not mask:
 | 
						|
            yield it
 | 
						|
        elif not compressed:
 | 
						|
            yield it[0], masked
 | 
						|
 | 
						|
 | 
						|
def flatnotmasked_edges(a):
 | 
						|
    """
 | 
						|
    Find the indices of the first and last unmasked values.
 | 
						|
 | 
						|
    Expects a 1-D `MaskedArray`, returns None if all values are masked.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        Input 1-D `MaskedArray`
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    edges : ndarray or None
 | 
						|
        The indices of first and last non-masked value in the array.
 | 
						|
        Returns None if all values are masked.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges
 | 
						|
    clump_masked, clump_unmasked
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    Only accepts 1-D arrays.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.arange(10)
 | 
						|
    >>> np.ma.flatnotmasked_edges(a)
 | 
						|
    array([0, 9])
 | 
						|
 | 
						|
    >>> mask = (a < 3) | (a > 8) | (a == 5)
 | 
						|
    >>> a[mask] = np.ma.masked
 | 
						|
    >>> np.array(a[~a.mask])
 | 
						|
    array([3, 4, 6, 7, 8])
 | 
						|
 | 
						|
    >>> np.ma.flatnotmasked_edges(a)
 | 
						|
    array([3, 8])
 | 
						|
 | 
						|
    >>> a[:] = np.ma.masked
 | 
						|
    >>> print(np.ma.flatnotmasked_edges(a))
 | 
						|
    None
 | 
						|
 | 
						|
    """
 | 
						|
    m = getmask(a)
 | 
						|
    if m is nomask or not np.any(m):
 | 
						|
        return np.array([0, a.size - 1])
 | 
						|
    unmasked = np.flatnonzero(~m)
 | 
						|
    if len(unmasked) > 0:
 | 
						|
        return unmasked[[0, -1]]
 | 
						|
    else:
 | 
						|
        return None
 | 
						|
 | 
						|
 | 
						|
def notmasked_edges(a, axis=None):
 | 
						|
    """
 | 
						|
    Find the indices of the first and last unmasked values along an axis.
 | 
						|
 | 
						|
    If all values are masked, return None.  Otherwise, return a list
 | 
						|
    of two tuples, corresponding to the indices of the first and last
 | 
						|
    unmasked values respectively.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        The input array.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which to perform the operation.
 | 
						|
        If None (default), applies to a flattened version of the array.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    edges : ndarray or list
 | 
						|
        An array of start and end indexes if there are any masked data in
 | 
						|
        the array. If there are no masked data in the array, `edges` is a
 | 
						|
        list of the first and last index.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_contiguous, flatnotmasked_edges, notmasked_contiguous
 | 
						|
    clump_masked, clump_unmasked
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.arange(9).reshape((3, 3))
 | 
						|
    >>> m = np.zeros_like(a)
 | 
						|
    >>> m[1:, 1:] = 1
 | 
						|
 | 
						|
    >>> am = np.ma.array(a, mask=m)
 | 
						|
    >>> np.array(am[~am.mask])
 | 
						|
    array([0, 1, 2, 3, 6])
 | 
						|
 | 
						|
    >>> np.ma.notmasked_edges(am)
 | 
						|
    array([0, 6])
 | 
						|
 | 
						|
    """
 | 
						|
    a = asarray(a)
 | 
						|
    if axis is None or a.ndim == 1:
 | 
						|
        return flatnotmasked_edges(a)
 | 
						|
    m = getmaskarray(a)
 | 
						|
    idx = array(np.indices(a.shape), mask=np.asarray([m] * a.ndim))
 | 
						|
    return [tuple([idx[i].min(axis).compressed() for i in range(a.ndim)]),
 | 
						|
            tuple([idx[i].max(axis).compressed() for i in range(a.ndim)]), ]
 | 
						|
 | 
						|
 | 
						|
def flatnotmasked_contiguous(a):
 | 
						|
    """
 | 
						|
    Find contiguous unmasked data in a masked array.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        The input array.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    slice_list : list
 | 
						|
        A sorted sequence of `slice` objects (start index, end index).
 | 
						|
 | 
						|
        .. versionchanged:: 1.15.0
 | 
						|
            Now returns an empty list instead of None for a fully masked array
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_edges, notmasked_contiguous, notmasked_edges
 | 
						|
    clump_masked, clump_unmasked
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    Only accepts 2-D arrays at most.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.arange(10)
 | 
						|
    >>> np.ma.flatnotmasked_contiguous(a)
 | 
						|
    [slice(0, 10, None)]
 | 
						|
 | 
						|
    >>> mask = (a < 3) | (a > 8) | (a == 5)
 | 
						|
    >>> a[mask] = np.ma.masked
 | 
						|
    >>> np.array(a[~a.mask])
 | 
						|
    array([3, 4, 6, 7, 8])
 | 
						|
 | 
						|
    >>> np.ma.flatnotmasked_contiguous(a)
 | 
						|
    [slice(3, 5, None), slice(6, 9, None)]
 | 
						|
    >>> a[:] = np.ma.masked
 | 
						|
    >>> np.ma.flatnotmasked_contiguous(a)
 | 
						|
    []
 | 
						|
 | 
						|
    """
 | 
						|
    m = getmask(a)
 | 
						|
    if m is nomask:
 | 
						|
        return [slice(0, a.size)]
 | 
						|
    i = 0
 | 
						|
    result = []
 | 
						|
    for (k, g) in itertools.groupby(m.ravel()):
 | 
						|
        n = len(list(g))
 | 
						|
        if not k:
 | 
						|
            result.append(slice(i, i + n))
 | 
						|
        i += n
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def notmasked_contiguous(a, axis=None):
 | 
						|
    """
 | 
						|
    Find contiguous unmasked data in a masked array along the given axis.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : array_like
 | 
						|
        The input array.
 | 
						|
    axis : int, optional
 | 
						|
        Axis along which to perform the operation.
 | 
						|
        If None (default), applies to a flattened version of the array, and this
 | 
						|
        is the same as `flatnotmasked_contiguous`.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    endpoints : list
 | 
						|
        A list of slices (start and end indexes) of unmasked indexes
 | 
						|
        in the array.
 | 
						|
 | 
						|
        If the input is 2d and axis is specified, the result is a list of lists.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
 | 
						|
    clump_masked, clump_unmasked
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    Only accepts 2-D arrays at most.
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.arange(12).reshape((3, 4))
 | 
						|
    >>> mask = np.zeros_like(a)
 | 
						|
    >>> mask[1:, :-1] = 1; mask[0, 1] = 1; mask[-1, 0] = 0
 | 
						|
    >>> ma = np.ma.array(a, mask=mask)
 | 
						|
    >>> ma
 | 
						|
    masked_array(
 | 
						|
      data=[[0, --, 2, 3],
 | 
						|
            [--, --, --, 7],
 | 
						|
            [8, --, --, 11]],
 | 
						|
      mask=[[False,  True, False, False],
 | 
						|
            [ True,  True,  True, False],
 | 
						|
            [False,  True,  True, False]],
 | 
						|
      fill_value=999999)
 | 
						|
    >>> np.array(ma[~ma.mask])
 | 
						|
    array([ 0,  2,  3,  7, 8, 11])
 | 
						|
 | 
						|
    >>> np.ma.notmasked_contiguous(ma)
 | 
						|
    [slice(0, 1, None), slice(2, 4, None), slice(7, 9, None), slice(11, 12, None)]
 | 
						|
 | 
						|
    >>> np.ma.notmasked_contiguous(ma, axis=0)
 | 
						|
    [[slice(0, 1, None), slice(2, 3, None)], [], [slice(0, 1, None)], [slice(0, 3, None)]]
 | 
						|
 | 
						|
    >>> np.ma.notmasked_contiguous(ma, axis=1)
 | 
						|
    [[slice(0, 1, None), slice(2, 4, None)], [slice(3, 4, None)], [slice(0, 1, None), slice(3, 4, None)]]
 | 
						|
 | 
						|
    """
 | 
						|
    a = asarray(a)
 | 
						|
    nd = a.ndim
 | 
						|
    if nd > 2:
 | 
						|
        raise NotImplementedError("Currently limited to at most 2D array.")
 | 
						|
    if axis is None or nd == 1:
 | 
						|
        return flatnotmasked_contiguous(a)
 | 
						|
    #
 | 
						|
    result = []
 | 
						|
    #
 | 
						|
    other = (axis + 1) % 2
 | 
						|
    idx = [0, 0]
 | 
						|
    idx[axis] = slice(None, None)
 | 
						|
    #
 | 
						|
    for i in range(a.shape[other]):
 | 
						|
        idx[other] = i
 | 
						|
        result.append(flatnotmasked_contiguous(a[tuple(idx)]))
 | 
						|
    return result
 | 
						|
 | 
						|
 | 
						|
def _ezclump(mask):
 | 
						|
    """
 | 
						|
    Finds the clumps (groups of data with the same values) for a 1D bool array.
 | 
						|
 | 
						|
    Returns a series of slices.
 | 
						|
    """
 | 
						|
    if mask.ndim > 1:
 | 
						|
        mask = mask.ravel()
 | 
						|
    idx = (mask[1:] ^ mask[:-1]).nonzero()
 | 
						|
    idx = idx[0] + 1
 | 
						|
 | 
						|
    if mask[0]:
 | 
						|
        if len(idx) == 0:
 | 
						|
            return [slice(0, mask.size)]
 | 
						|
 | 
						|
        r = [slice(0, idx[0])]
 | 
						|
        r.extend((slice(left, right)
 | 
						|
                  for left, right in zip(idx[1:-1:2], idx[2::2])))
 | 
						|
    else:
 | 
						|
        if len(idx) == 0:
 | 
						|
            return []
 | 
						|
 | 
						|
        r = [slice(left, right) for left, right in zip(idx[:-1:2], idx[1::2])]
 | 
						|
 | 
						|
    if mask[-1]:
 | 
						|
        r.append(slice(idx[-1], mask.size))
 | 
						|
    return r
 | 
						|
 | 
						|
 | 
						|
def clump_unmasked(a):
 | 
						|
    """
 | 
						|
    Return list of slices corresponding to the unmasked clumps of a 1-D array.
 | 
						|
    (A "clump" is defined as a contiguous region of the array).
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : ndarray
 | 
						|
        A one-dimensional masked array.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    slices : list of slice
 | 
						|
        The list of slices, one for each continuous region of unmasked
 | 
						|
        elements in `a`.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    .. versionadded:: 1.4.0
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
 | 
						|
    notmasked_contiguous, clump_masked
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.masked_array(np.arange(10))
 | 
						|
    >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked
 | 
						|
    >>> np.ma.clump_unmasked(a)
 | 
						|
    [slice(3, 6, None), slice(7, 8, None)]
 | 
						|
 | 
						|
    """
 | 
						|
    mask = getattr(a, '_mask', nomask)
 | 
						|
    if mask is nomask:
 | 
						|
        return [slice(0, a.size)]
 | 
						|
    return _ezclump(~mask)
 | 
						|
 | 
						|
 | 
						|
def clump_masked(a):
 | 
						|
    """
 | 
						|
    Returns a list of slices corresponding to the masked clumps of a 1-D array.
 | 
						|
    (A "clump" is defined as a contiguous region of the array).
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    a : ndarray
 | 
						|
        A one-dimensional masked array.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    slices : list of slice
 | 
						|
        The list of slices, one for each continuous region of masked elements
 | 
						|
        in `a`.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    .. versionadded:: 1.4.0
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    flatnotmasked_edges, flatnotmasked_contiguous, notmasked_edges
 | 
						|
    notmasked_contiguous, clump_unmasked
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    >>> a = np.ma.masked_array(np.arange(10))
 | 
						|
    >>> a[[0, 1, 2, 6, 8, 9]] = np.ma.masked
 | 
						|
    >>> np.ma.clump_masked(a)
 | 
						|
    [slice(0, 3, None), slice(6, 7, None), slice(8, 10, None)]
 | 
						|
 | 
						|
    """
 | 
						|
    mask = ma.getmask(a)
 | 
						|
    if mask is nomask:
 | 
						|
        return []
 | 
						|
    return _ezclump(mask)
 | 
						|
 | 
						|
 | 
						|
###############################################################################
 | 
						|
#                              Polynomial fit                                 #
 | 
						|
###############################################################################
 | 
						|
 | 
						|
 | 
						|
def vander(x, n=None):
 | 
						|
    """
 | 
						|
    Masked values in the input array result in rows of zeros.
 | 
						|
 | 
						|
    """
 | 
						|
    _vander = np.vander(x, n)
 | 
						|
    m = getmask(x)
 | 
						|
    if m is not nomask:
 | 
						|
        _vander[m] = 0
 | 
						|
    return _vander
 | 
						|
 | 
						|
vander.__doc__ = ma.doc_note(np.vander.__doc__, vander.__doc__)
 | 
						|
 | 
						|
 | 
						|
def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False):
 | 
						|
    """
 | 
						|
    Any masked values in x is propagated in y, and vice-versa.
 | 
						|
 | 
						|
    """
 | 
						|
    x = asarray(x)
 | 
						|
    y = asarray(y)
 | 
						|
 | 
						|
    m = getmask(x)
 | 
						|
    if y.ndim == 1:
 | 
						|
        m = mask_or(m, getmask(y))
 | 
						|
    elif y.ndim == 2:
 | 
						|
        my = getmask(mask_rows(y))
 | 
						|
        if my is not nomask:
 | 
						|
            m = mask_or(m, my[:, 0])
 | 
						|
    else:
 | 
						|
        raise TypeError("Expected a 1D or 2D array for y!")
 | 
						|
 | 
						|
    if w is not None:
 | 
						|
        w = asarray(w)
 | 
						|
        if w.ndim != 1:
 | 
						|
            raise TypeError("expected a 1-d array for weights")
 | 
						|
        if w.shape[0] != y.shape[0]:
 | 
						|
            raise TypeError("expected w and y to have the same length")
 | 
						|
        m = mask_or(m, getmask(w))
 | 
						|
 | 
						|
    if m is not nomask:
 | 
						|
        not_m = ~m
 | 
						|
        if w is not None:
 | 
						|
            w = w[not_m]
 | 
						|
        return np.polyfit(x[not_m], y[not_m], deg, rcond, full, w, cov)
 | 
						|
    else:
 | 
						|
        return np.polyfit(x, y, deg, rcond, full, w, cov)
 | 
						|
 | 
						|
polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__)
 |