nlcpy.ma.core のソースコード

#
# * The source code in this file is based on the soure code of NumPy.
#
# # NLCPy License #
#
#     Copyright (c) 2020 NEC Corporation
#     All rights reserved.
#
#     Redistribution and use in source and binary forms, with or without
#     modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright notice,
#       this list of conditions and the following disclaimer in the documentation
#       and/or other materials provided with the distribution.
#     * Neither NEC Corporation nor the names of its contributors may be
#       used to endorse or promote products derived from this software
#       without specific prior written permission.
#
#     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
#     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# # NumPy License #
#
#     Copyright (c) 2005-2020, NumPy Developers.
#     All rights reserved.
#
#     Redistribution and use in source and binary forms, with or without
#     modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright notice,
#       this list of conditions and the following disclaimer in the documentation
#       and/or other materials provided with the distribution.
#     * Neither the name of the NumPy Developers nor the names of any contributors may be
#       used to endorse or promote products derived from this software
#       without specific prior written permission.
#
#     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
#     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# distutils: language = c++

import warnings

import nlcpy
import numpy

from nlcpy import ndarray
from nlcpy.core import core
from nlcpy.core import internal
from nlcpy.core import dtype as _dtype
from nlcpy.ufuncs import operations as ufunc_op
from nlcpy.request import request
from numpy.ma import masked

MaskType = numpy.bool_
nomask = MaskType(0)

ufunc_domain = {}
ufunc_fills = {}

default_filler = {
    'b': True,
    'c': 1.e20 + 0.0j,
    'f': 1.e20,
    'i': 999999,
    'u': 999999,
}


class MAError(Exception):
    pass


class MaskError(MAError):
    pass


def _arraymethod(funcname, onmask=True):
    """ Returns a class method wrapper around a basic array method.

    Creates a class method which returns a masked array, where the new
    ``_data`` array is the output of the corresponding basic method called
    on the original ``_data``.
    If `onmask` is True, the new mask is the output of the method called
    on the initial mask. Otherwise, the new mask is just a reference
    to the initial mask.

    Parameters
    ----------
    funcname : str
        Name of the function to apply on data.
    onmask : bool
        Whether the mask must be processed also (True) or left
        alone (False). Default is True. Make available as `_onmask`
        attribute.

    Returns
    -------
    method : instancemethod
        Class method wrapper of the specified basic array method.
    """
    def wrapped_method(self, *args, **params):
        result = getattr(self._data, funcname)(*args, **params)
        result = result.view(type(self))
        result._update_from(self)
        mask = self._mask
        if not onmask:
            result.__setmask__(mask)
        elif mask is not nomask:
            # __setmask__ makes a copy, which we don't want
            result._mask = getattr(mask, funcname)(*args, **params)
        return result
    methdoc = getattr(ndarray, funcname, None) or getattr(nlcpy, funcname, None)
    if methdoc is not None:
        wrapped_method.__doc__ = methdoc.__doc__
    wrapped_method.__name__ = funcname
    return wrapped_method


[ドキュメント]class MaskedArray(ndarray): """ An array class with possibly masked values. Masked values of True exclude the corresponding element from any computation. Parameters ---------- data : array_like Input data. mask : sequence, optional Mask. Must be convertible to an array of booleans with the same shape as `data`. True indicates a masked (i.e. invalid) data. dtype : dtype, optional Data type of the output. If `dtype` is None, the type of the data argument (``data.dtype``) is used. If `dtype` is not None and different from ``data.dtype``, a copy is performed. copy : bool, optional Whether to copy the input data (True), or to use a reference instead. Default is False. subok : bool, optional Whether to return a subclass of `MaskedArray` if possible (True) or a plain `MaskedArray`. subok=True is Not Implemented. ndmin : int, optional Minimum number of dimensions. Default is 0. fill_value : scalar, optional Value used to fill in the masked values when necessary. If None, a default based on the data-type is used. keep_mask : bool, optional Whether to combine `mask` with the mask of the input data, if any (True), or to use only `mask` for the output (False). Default is True. hard_mask : bool, optional Whether to use a hard mask or not. With a hard mask, masked values cannot be unmasked. Default is False. shrink : bool, optional Whether to force compression of an empty mask. Default is True. order : {'C', 'F', 'A'}, optional Specify the order of the array. If order is 'C', then the array will be in C-contiguous order (last-index varies the fastest). If order is 'F', then the returned array will be in Fortran-contiguous order (first-index varies the fastest). If order is 'A' (default), then the returned array may be in any order (either C-, Fortran-contiguous, or even discontiguous), unless a copy is required, in which case it will be C-contiguous. Examples -------- The ``mask`` can be initialized with an array of boolean values with the same shape as ``data``. >>> import nlcpy as vp >>> import numpy as np >>> data = vp.arange(6).reshape((2, 3)) >>> vp.ma.MaskedArray(data, mask=[[False, True, False], ... [False, False, True]]) masked_array( data=[[0, --, 2], [3, 4, --]], mask=[[False, True, False], [False, False, True]], fill_value=999999) Alternatively, the ``mask`` can be initialized to homogeneous boolean array with the same shape as ``data`` by passing in a scalar boolean value: >>> vp.ma.MaskedArray(data, mask=False) masked_array( data=[[0, 1, 2], [3, 4, 5]], mask=[[False, False, False], [False, False, False]], fill_value=999999) >>> vp.ma.MaskedArray(data, mask=True) masked_array( data=[[--, --, --], [--, --, --]], mask=[[ True, True, True], [ True, True, True]], fill_value=999999, dtype=int64) .. note:: The recommended practice for initializing ``mask`` with a scalar boolean value is to use ``True``/``False`` rather than ``np.True_``/``np.False_``. The reason is :attr:`nomask` is represented internally as ``np.False_``. >>> np.False_ is vp.ma.nomask True """ __array_priority__ = 15 def __new__(self, data=None, mask=nomask, dtype=None, copy=False, subok=None, ndmin=0, fill_value=None, keep_mask=True, hard_mask=None, shrink=True, order=None): if subok is not None: raise NotImplementedError('subok is not implemented yet') if isinstance(data, MaskedArray): _data = data._data else: _data = data if not isinstance(_data, ndarray) or copy or \ _data.dtype != dtype or _data.ndim < ndmin or \ (order == 'C' and not _data.flags.c_contiguous) or \ (order == 'F' and not _data.flags.f_contiguous): _data = nlcpy.array(_data, dtype=dtype, ndmin=ndmin, order=order, copy=copy) _data = ndarray.view(_data, MaskedArray) return _data def __init__(self, data=None, mask=nomask, dtype=None, copy=False, subok=None, ndmin=0, fill_value=None, keep_mask=True, hard_mask=None, shrink=True, order=None): if hasattr(data, '_mask'): self._mask = data._mask else: self._mask = nomask self._sharedmask = True if mask is nomask: if not keep_mask: if shrink: self._mask = nomask else: self._mask = nlcpy.zeros(self.shape, dtype=MaskType) elif isinstance(data, (tuple, list)): try: mask = nlcpy.array( [getmaskarray(nlcpy.asanyarray(m, dtype=self.dtype)) for m in data], dtype=MaskType) except ValueError: mask = nomask if mask.any(): self._mask = mask self._sharedmask = False else: self._sharedmask = not copy if copy: self._mask = self._mask.copy() if getmask(data) is not nomask: data._mask.shape = data.shape else: if mask is True: mask = nlcpy.ones(self.shape, dtype=MaskType) elif mask is False: mask = nlcpy.zeros(self.shape, dtype=MaskType) else: mask = nlcpy.array(mask, copy=copy, dtype=MaskType) if mask.shape != self.shape: (nd, nm) = (self.size, mask.size) if nm == 1: mask = nlcpy.resize(mask, self.shape) elif nm == nd: mask = nlcpy.reshape(mask, self.shape) else: msg = "Mask and data not compatible: data size is %i, " + \ "mask size is %i." raise MaskError(msg % (nd, nm)) copy = True if self._mask is nomask: self._mask = mask self._sharedmask = not copy else: if not keep_mask: self._mask = mask self._sharedmask = not copy else: self._mask = nlcpy.logical_or(mask, self._mask) self._sharedmask = False if isinstance(self._mask, nlcpy.ndarray): if self.venode != self._mask.venode: raise ValueError( 'Mask and data exist different VE node: mask on {}, data on {}' .format(self._mask.venode, self.venode) ) if fill_value is None: fill_value = getattr(data, '_fill_value', None) if fill_value is not None: self._fill_value = _check_fill_value(fill_value, self.dtype) else: self._fill_value = None if hard_mask is None: self._hardmask = getattr(data, '_hardmask', False) else: self._hardmask = hard_mask self._baseclass = ndarray def _update_from(self, obj): """ Copies some attributes of obj to self. """ if isinstance(obj, ndarray): _baseclass = type(obj) else: _baseclass = ndarray _optinfo = {} _optinfo.update(getattr(obj, '_optinfo', {})) _optinfo.update(getattr(obj, '_basedict', {})) if not isinstance(obj, MaskedArray): _optinfo.update(getattr(obj, '__dict__', {})) _dict = dict(_fill_value=getattr(obj, '_fill_value', None), _hardmask=getattr(obj, '_hardmask', False), _sharedmask=getattr(obj, '_sharedmask', False), _baseclass=getattr(obj, '_baseclass', _baseclass), _optinfo=_optinfo, _basedict=_optinfo) self.__dict__.update(_dict) self.__dict__.update(_optinfo) return
[ドキュメント] def view(self, dtype=None, type=None, fill_value=None): """ Returns a view of the MaskedArray data. Parameters ---------- dtype : data-type or ndarray sub-class, optional Data-type descriptor of the returned view, e.g., float32 or int32. The default, None, results in the view having the same data-type as `a`. As with :func:`nlcpy.ndarray.view`, dtype can also be specified as an ndarray sub-class, which then specifies the type of the returned object (this is equivalent to setting the ``type``. type : Python type, optional Type of the returned view, either ndarray or a subclass. The default None results in type preservation. fill_value : scalar, optional The value to use for invalid entries (None by default). If None, then this argument is inferred from the passed `dtype`, or in its absence the original array, as discussed in the notes below. See Also -------- nlcpy.ndarray.view : Equivalent method on ndarray object. Notes ----- ``a.view()`` is used two different ways: ``a.view(some_dtype)`` or ``a.view(dtype=some_dtype)`` constructs a view of the array's memory with a different data-type. This can cause a reinterpretation of the bytes of memory. ``a.view(ndarray_subclass)`` or ``a.view(type=ndarray_subclass)`` just returns an instance of `ndarray_subclass` that looks at the same array (same shape, dtype, etc.) This does not cause a reinterpretation of the memory. If `fill_value` is not specified, but `dtype` is specified (and is not an ndarray sub-class), the `fill_value` of the MaskedArray will be reset. If neither `fill_value` nor `dtype` are specified (or if `dtype` is an ndarray sub-class), then the fill value is preserved. Finally, if `fill_value` is specified, but `dtype` is not, the fill value is set to the specified value. For ``a.view(some_dtype)``, if ``some_dtype`` has a different number of bytes per entry than the previous dtype (for example, converting a regular array to a structured array), then the behavior of the view cannot be predicted just from the superficial appearance of ``a`` (shown by ``print(a)``). It also depends on exactly how ``a`` is stored in memory. Therefore if ``a`` is C-ordered versus fortran-ordered, versus defined as a slice or transpose, etc., the view may give different results. """ if type is None and not (dtype is ndarray or dtype in ndarray.__subclasses__()): type = MaskedArray v = super().view(dtype=dtype, type=type) if not hasattr(v, '_mask'): return v mask = self._mask if fill_value is None: fill_value = self._fill_value if isinstance(mask, ndarray): mask = mask.reshape(v.shape) if self.dtype != v.dtype: v._fill_value = None elif isinstance(fill_value, ndarray): v._fill_value = fill_value.copy() else: v._fill_value = fill_value v._mask = mask v._sharedmask = True return v
[ドキュメント] def __getitem__(self, indx): dout = self.data[indx] _mask = self._mask def _scalar_heuristic(arr, elem): if type(arr).__getitem__ == ndarray.__getitem__ and arr.size > 1: return False return None if _mask is not nomask: mout = _mask[indx] scalar_expected = not (isinstance(mout, ndarray) and mout.ndim > 0) else: mout = nomask scalar_expected = _scalar_heuristic(self.data, mout) if scalar_expected is None: scalar_expected = not isinstance(getmaskarray(self)[indx], ndarray) if scalar_expected: return masked if mout else dout.view(MaskedArray) else: dout = dout.view(MaskedArray) dout._update_from(self) # Update the mask if needed if mout is not nomask: # set shape to match that of data; this is needed for matrices dout._mask = mout.reshape(dout.shape) dout._sharedmask = True # Note: Don't try to check for m.any(), that'll take too long return dout
[ドキュメント] def __setitem__(self, indx, value): """ x.__setitem__(i, y) is equivalent to x[i] = y. Set item described by index. If value is masked, masks those locations. """ _data = self._data _mask = self._mask _dtype = _data.dtype if value is masked: # The mask wasn't set: create a full version. if _mask is nomask: _mask = self._mask = make_mask_none(self.shape, _dtype) # Now, set the mask to its value. _mask[indx] = True return # Get the _data part of the new value dval = getattr(value, '_data', value) # Get the _mask part of the new value mval = getmask(value) if _mask is nomask: # Set the data, then the mask _data[indx] = dval if mval is not nomask: _mask = self._mask = make_mask_none(self.shape, _dtype) _mask[indx] = mval elif not self._hardmask: # Set the data, then the mask if isinstance(indx, MaskedArray): _data[indx.data] = dval _mask[indx.data] = mval else: _data[indx] = dval _mask[indx] = mval elif hasattr(indx, 'dtype') and (indx.dtype == MaskType): indx = indx * nlcpy.logical_not(_mask) _data[indx] = dval else: mindx = mask_or(_mask[indx], mval, copy=True) dindx = self._data[indx] if dindx.size > 1: nlcpy.copyto(dindx, dval, where=nlcpy.logical_not(mindx)) elif mindx is nomask: dindx = dval _data[indx] = dindx _mask[indx] = mindx return
@property def shape(self): return super().shape @shape.setter def shape(self, shape): super(MaskedArray, type(self)).shape.__set__(self, shape) if getmask(self) is not nomask: self._mask.shape = self.shape def __setmask__(self, mask, copy=False): idtype = self.dtype current_mask = self._mask if mask is masked: mask = True if current_mask is nomask: # Make sure the mask is set # Just don't do anything if there's nothing to do. if mask is nomask: return current_mask = self._mask = make_mask_none(self.shape, idtype) # Hardmask: don't unmask the data if self._hardmask: current_mask |= mask # Softmask: set everything to False # If it's obviously a compatible scalar, use a quick update # method. elif isinstance(mask, (int, float, nlcpy.bool_, nlcpy.number)): current_mask[...] = mask # Otherwise fall back to the slower, general purpose way. else: mask = nlcpy.asarray(mask, dtype=nlcpy.bool_) current_mask = mask[tuple([slice(0, i) for i in self.shape])] # Reshape if needed if current_mask.shape: current_mask.shape = self.shape self._mask = current_mask return _set_mask = __setmask__ @property def mask(self): return self._mask.view() @mask.setter def mask(self, value): self.__setmask__(value)
[ドキュメント] def harden_mask(self): """ Forces the mask to hard. Whether the mask of a masked array is hard or soft is determined by its :attr:`hardmask` property. `harden_mask` sets `hardmask` to ``True``. See Also -------- nlcpy.ma.MaskedArray.hardmask """ self._hardmask = True return self
[ドキュメント] def soften_mask(self): """ Forces the mask to soft. Whether the mask of a masked array is hard or soft is determined by its :attr:`hardmask` property. `soften_mask` sets `hardmask` to ``False``. See Also -------- nlcpy.ma.MaskedArray.hardmask """ self._hardmask = False return self
@property def hardmask(self): """ Hardness of the mask. If True, masked values cannot be unmasked. """ return self._hardmask
[ドキュメント] def unshare_mask(self): """ Copies the mask and set the sharedmask flag to False. Whether the mask is shared between masked arrays can be seen from the `sharedmask` property. `unshare_mask` ensures the mask is not shared. A copy of the mask is only made if it was shared. See Also -------- sharedmask """ if self._sharedmask: self._mask = self._mask.copy() self._sharedmask = False return self
@property def sharedmask(self): """ Share status of the mask (read-only). """ return self._sharedmask
[ドキュメント] def shrink_mask(self): """ Reduces a mask to nomask when possible. Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([[1, 2], [3, 4]], mask=[0]*4) >>> x.mask array([[False, False], [False, False]]) >>> x.shrink_mask() masked_array( data=[[1, 2], [3, 4]], mask=False, fill_value=999999) >>> x.mask False """ self._mask = _shrink_mask(self._mask) return self
@property def baseclass(self): """ Class of the underlying data (read-only). """ return self._baseclass def _get_data(self): """Returns the underlying data, as a view of the masked array. The type of the data can be accessed through the :attr:`baseclass` attribute. """ return super().view() _data = property(fget=_get_data) data = property(fget=_get_data) @property def fill_value(self): """The filling value of the masked array is a scalar. When setting, None will set to a default based on the data type. Examples -------- >>> import nlcpy as vp >>> for dt in [vp.int32, vp.int64, vp.float64, vp.complex128]: ... vp.ma.array([0, 1], dtype=dt).get_fill_value() ... 999999 999999 1e+20 (1e+20+0j) >>> x = vp.ma.array([0, 1.], fill_value=-vp.inf) >>> x.fill_value -inf >>> x.fill_value = vp.pi >>> x.fill_value 3.141592653589793 Reset to default: >>> x.fill_value = None >>> x.fill_value 1e+20 """ if self._fill_value is None: self._fill_value = _check_fill_value(None, self.dtype) if isinstance(self._fill_value, (ndarray, numpy.ndarray)): return self._fill_value[()] return self._fill_value @fill_value.setter def fill_value(self, value): target = _check_fill_value(value, self.dtype) if target.ndim != 0: warnings.warn( "Non-scalar arrays for the fill value are deprecated. Use " "arrays with scalar values instead. The filled function " "still supports any array as `fill_value`.", DeprecationWarning, stacklevel=2) if self._fill_value is None: self._fill_value = target else: self._fill_value[()] = target # kept for compatibility get_fill_value = fill_value.fget set_fill_value = fill_value.fset
[ドキュメント] def filled(self, fill_value=None): """Returns a copy of self, with masked values filled with a given value. **However**, if there are no masked values to fill, self will be returned instead as an ndarray. Parameters ---------- fill_value : array_like, optional The value to use for invalid entries. Can be scalar or non-scalar. If non-scalar, the resulting ndarray must be broadcastable over input array. Default is None, in which case, the `fill_value` attribute of the array is used instead. Returns ------- filled_array : ndarray A copy of ``self`` with invalid entries replaced by *fill_value* (be it the function argument or the attribute of ``self``), or ``self`` itself as an ndarray if there are no invalid entries to be replaced. Notes ----- The result is **not** a MaskedArray! Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([1,2,3,4,5], mask=[0,0,1,0,1], fill_value=-999) >>> x.filled() array([ 1, 2, -999, 4, -999]) >>> x.filled(fill_value=1000) array([ 1, 2, 1000, 4, 1000]) >>> type(x.filled()) <class 'nlcpy.core.core.ndarray'> """ m = self._mask if m is nomask: return self._data if fill_value is None: fill_value = self.fill_value else: fill_value = _check_fill_value(fill_value, self.dtype) if not m.any(): return self._data else: result = self._data.copy('K') try: nlcpy.copyto(result, fill_value, where=m) except (TypeError, AttributeError): fill_value = nlcpy.narray(fill_value, dtype=object) d = result.astype(object) result = nlcpy.choose(m, (d, fill_value)) except IndexError: # ok, if scalar if self._data.shape: raise elif m: result = nlcpy.array(fill_value, dtype=self.dtype) else: result = self._data return result
def __str__(self): return self.get().__str__() def __repr__(self): """ Literal string representation. """ return self.get().__repr__() def __add__(self, other): return add(self, other) def __radd__(self, other): return add(other, self) def __iadd__(self, other): m = getmask(other) if self._mask is nomask: if m is not nomask: self._mask = m.copy() else: if m is not nomask: self._mask += m if numpy.isscalar(other): if self._mask is not nomask and self._mask.any(): other = numpy.array( other, dtype=numpy.result_type(self.dtype, type(other))) else: other = numpy.result_type(self.dtype, type(other)).type(other) where = nlcpy.logical_not(self._mask) nlcpy.add(self._data, other, where=where, out=self._data) else: self._data.__iadd__( nlcpy.where(self._mask, self.dtype.type(0), getdata(other))) return self def __sub__(self, other): return subtract(self, other) def __rsub__(self, other): return subtract(other, self) def __isub__(self, other): m = getmask(other) if self._mask is nomask: if m is not nomask: self._mask = m.copy() else: if m is not nomask: self._mask += m if numpy.isscalar(other): if self._mask is not nomask and self._mask.any(): other = numpy.array( other, dtype=numpy.result_type(self.dtype, type(other))) else: other = numpy.result_type(self.dtype, type(other)).type(other) where = nlcpy.logical_not(self._mask) nlcpy.subtract(self._data, other, where=where, out=self._data) else: self._data.__isub__( nlcpy.where(self._mask, self.dtype.type(0), getdata(other))) return self def __mul__(self, other): return multiply(self, other) def __rmul__(self, other): return multiply(other, self) def __imul__(self, other): m = getmask(other) if self._mask is nomask: if m is not nomask: self._mask = m.copy() else: if m is not nomask: self._mask += m if numpy.isscalar(other): if self._mask is not nomask and self._mask.any(): other = numpy.array( other, dtype=numpy.result_type(self.dtype, type(other))) else: other = numpy.result_type(self.dtype, type(other)).type(other) where = nlcpy.logical_not(self._mask) nlcpy.multiply(self._data, other, where=where, out=self._data) else: self._data.__imul__( nlcpy.where(self._mask, self.dtype.type(1), getdata(other))) return self def __div__(self, other): return divide(self, other) def __idiv__(self, other): other_data = getdata(other) dom_mask = _DomainSafeDivide().__call__(self._data, other_data) other_mask = getmask(other) new_mask = mask_or(other_mask, dom_mask) # The following 3 lines control the domain filling if dom_mask.any(): (_, fval) = ufunc_fills[nlcpy.divide] other_data = nlcpy.where(dom_mask, fval, other_data) self._mask |= new_mask self._data.__idiv__( nlcpy.where(self._mask, self.dtype.type(1), other_data)) return self def __truediv__(self, other): return true_divide(self, other) def __rtruediv__(self, other): return true_divide(other, self) def __itruediv__(self, other): other_data = getdata(other) dom_mask = _DomainSafeDivide().__call__(self._data, other_data) other_mask = getmask(other) new_mask = mask_or(other_mask, dom_mask) # The following 3 lines control the domain filling if dom_mask.any(): (_, fval) = ufunc_fills[nlcpy.true_divide] other_data = nlcpy.where(dom_mask, fval, other_data) self._mask |= new_mask self._data.__itruediv__( nlcpy.where(self._mask, self.dtype.type(1), other_data)) return self @property def imag(self): """The imaginary part of the masked array. This property is a view on the imaginary part of this `MaskedArray`. See Also -------- real Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) >>> x.imag masked_array(data=[1.0, --, 1.6], mask=[False, True, False], fill_value=1e+20) """ result = self._data.imag.view(type(self)) result.__setmask__(self._mask) result._sharedmask = False return result get_imag = imag.fget @property def real(self): """The real part of the masked array. This property is a view on the real part of this `MaskedArray`. See Also -------- imag Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([1+1.j, -2j, 3.45+1.6j], mask=[False, True, False]) >>> x.real masked_array(data=[1.0, --, 3.45], mask=[False, True, False], fill_value=1e+20) """ result = self._data.real.view(type(self)) result.__setmask__(self._mask) result._sharedmask = False return result get_real = real.fget
[ドキュメント] def ravel(self, order='C'): """Returns a 1D version of self, as a view. Parameters ---------- order : {'C', 'F', 'A', 'K'}, optional The elements of `a` are read using this index order. 'C' means to index the elements in C-like order, with the last axis index changing fastest, back to the first axis index changing slowest. 'F' means to index the elements in Fortran-like index order, with the first index changing fastest, and the last index changing slowest. Note that the 'C' and 'F' options take no account of the memory layout of the underlying array, and only refer to the order of axis indexing. 'A' means to read the elements in Fortran-like index order if `m` is Fortran *contiguous* in memory, C-like order otherwise. 'K' means to read the elements in the order they occur in memory, except for reversing the data when strides are negative. By default, 'C' index order is used. Returns ------- MaskedArray Output view is of shape ``(self.size,)`` (or ``(nlcpy.ma.product(self.shape),)``). Restriction ----------- * If order == 'K': *NotImplementedError* occurs. Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([[1,2,3],[4,5,6],[7,8,9]], mask=[0] + [1,0]*4) >>> x masked_array( data=[[1, --, 3], [--, 5, --], [7, --, 9]], mask=[[False, True, False], [ True, False, True], [False, True, False]], fill_value=999999) >>> x.ravel() masked_array(data=[1, --, 3, --, 5, --, 7, --, 9], mask=[False, True, False, True, False, True, False, True, False], fill_value=999999) """ r = ndarray.ravel(self._data, order=order).view(type(self)) r._update_from(self) if self._mask is not nomask: r._mask = self._mask.ravel(order=order).reshape(r.shape) else: r._mask = nomask return r
[ドキュメント] def reshape(self, *shape, order='C'): """ Gives a new shape to the array without changing its data. Returns a masked array containing the same data, but with a new shape. The result is a view on the original array; if this is not possible, a ValueError is raised. Parameters ---------- shape : int or tuple of ints The new shape should be compatible with the original shape. If an integer is supplied, then the result will be a 1-D array of that length. order : {'C', 'F'}, optional Determines whether the array data should be viewed as in C (row-major) or FORTRAN (column-major) order. Returns ------- reshaped_array : array A new view on the array. See Also -------- reshape : Equivalent function in the masked array module. nlcpy.ndarray.reshape : Equivalent method on ndarray object. nlcpy.reshape : Equivalent function in the NLCPy module. Notes ----- The reshaping operation cannot guarantee that a copy will not be made, to modify the shape in place, use ``a.shape = s`` Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([[1,2],[3,4]], mask=[1,0,0,1]) >>> x masked_array( data=[[--, 2], [3, --]], mask=[[ True, False], [False, True]], fill_value=999999) >>> x = x.reshape((4,1)) >>> x masked_array( data=[[--], [2], [3], [--]], mask=[[ True], [False], [False], [ True]], fill_value=999999) """ result = self.data.reshape(*shape, order=order).view(type(self)) result._update_from(self) if self._mask is not nomask: result._mask = self._mask.reshape(*shape, order=order) return result
[ドキュメント] def resize(self, newshape, refcheck=True, order=False): """ .. warning:: This method does nothing, except raise a ValueError exception. A masked array does not own its data and therefore cannot safely be resized in place. Use the :func:`nlcpy.ma.resize` function instead. This method is difficult to implement safely and may be deprecated in future releases of NLCPy. """ # Note : the 'order' keyword looks broken, let's just drop it errmsg = "A masked array does not own its data "\ "and therefore cannot be resized.\n" \ "Use the nlcpy.ma.resize function instead." raise ValueError(errmsg)
[ドキュメント] def all(self, axis=None, out=None, keepdims=nlcpy._NoValue): """ Masked version of all is not implemented yet. """ raise NotImplementedError('masked version of all is not implemented yet')
[ドキュメント] def any(self, axis=None, out=None, keepdims=False): """ Masked version of any is not implemented yet. """ raise NotImplementedError('masked version of any is not implemented yet')
[ドキュメント] def argmax(self, axis=None, out=None): """ Masked version of argmax is not implemented yet. """ raise NotImplementedError('masked version of argmax is not implemented yet')
[ドキュメント] def argmin(self, axis=None, out=None): """ Masked version of argmin is not implemented yet. """ raise NotImplementedError('masked version of argmin is not implemented yet')
[ドキュメント] def argsort(self, axis=-1, kind=None, order=None): """ Masked version of argsort is not implemented yet. """ raise NotImplementedError('masked version of argsort is not implemented yet')
[ドキュメント] def clip(self, a_min, a_max, out=None, **kwargs): """ Masked version of clip is not implemented yet. """ raise NotImplementedError('masked version of clip is not implemented yet')
[ドキュメント] def conj(self, out=None, where=True, casting='same_kind', order='K', dtype=None, subok=False): """ Masked version of conj is not implemented yet. """ raise NotImplementedError('masked version of conj is not implemented yet')
[ドキュメント] def conjugate(self, out=None, where=True, casting='same_kind', order='K', dtype=None, subok=False): """ Masked version of conjugate is not implemented yet. """ raise NotImplementedError('masked version of conjugate is not implemented yet')
[ドキュメント] def cumsum(self, axis=None, dtype=None, out=None): """ Masked version of cumsum is not implemented yet. """ raise NotImplementedError('masked version of cumsum is not implemented yet')
[ドキュメント] def dot(self, b, out=None): """ Masked version of dot is not implemented yet. """ raise NotImplementedError('masked version of dot is not implemented yet')
[ドキュメント] def max(self, axis=None, out=None, keepdims=False, initial=nlcpy._NoValue, where=True): """ Masked version of max is not implemented yet. """ raise NotImplementedError('masked version of max is not implemented yet')
[ドキュメント] def min(self, axis=None, out=None, keepdims=False, initial=nlcpy._NoValue, where=True): """ Masked version of min is not implemented yet. """ raise NotImplementedError('masked version of min is not implemented yet')
[ドキュメント] def mean(self, axis=None, dtype=None, out=False, keepdims=nlcpy._NoValue): """ Masked version of mean is not implemented yet. """ raise NotImplementedError('masked version of mean is not implemented yet')
[ドキュメント] def nonzero(self): """ Masked version of nonzero is not implemented yet. """ raise NotImplementedError('masked version of nonzero is not implemented yet')
[ドキュメント] def prod(self, axis=None, dtype=None, out=None, keepdims=False, initial=nlcpy._NoValue, where=True): """ Masked version of prod is not implemented yet. """ raise NotImplementedError('masked version of prod is not implemented yet')
[ドキュメント] def ptp(self, axis=None, out=None, keepdims=nlcpy._NoValue): """ Masked version of ptp is not implemented yet. """ raise NotImplementedError('masked version of ptp is not implemented yet')
[ドキュメント] def sort(self, axis=-1, kind=None, order=None): """ Masked version of sort is not implemented yet. """ raise NotImplementedError('masked version of sort is not implemented yet')
[ドキュメント] def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=nlcpy._NoValue): """ Masked version of std is not implemented yet. """ raise NotImplementedError('masked version of std is not implemented yet')
[ドキュメント] def sum(self, axis=None, dtype=None, out=None, keepdims=False, initial=0, where=True): """ Masked version of sum is not implemented yet. """ raise NotImplementedError('masked version of sum is not implemented yet')
[ドキュメント] def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=nlcpy._NoValue): """ Masked version of var is not implemented yet. """ raise NotImplementedError('masked version of var is not implemented yet')
[ドキュメント] def take(self, indices, axis=None, out=None, mode='raise'): if mode != 'raise': raise NotImplementedError('mode is not supported yet') (_data, _mask) = (self._data, self._mask) cls = type(self) # Make sure the indices are not masked maskindices = getmask(indices) if maskindices is not nomask: indices = indices.filled(0) # Get the data, promoting scalars to 0d arrays with [...] so that # .view works correctly if out is None: out = _data.take(indices, axis=axis)[...].view(cls) elif isinstance(out, MaskedArray): nlcpy.take(_data, indices, axis=axis, mode=mode, out=out._data) else: nlcpy.take(_data, indices, axis=axis, mode=mode, out=out) # Get the mask if isinstance(out, MaskedArray): if _mask is nomask: outmask = maskindices else: outmask = _mask.take(indices, axis=axis) outmask |= maskindices out.__setmask__(outmask) # demote 0d arrays back to scalars, for consistency with ndarray.take return out[()]
# Array methods copy = _arraymethod('copy') diagonal = _arraymethod('diagonal') flatten = _arraymethod('flatten') repeat = _arraymethod('repeat') squeeze = _arraymethod('squeeze') swapaxes = _arraymethod('swapaxes') T = property(fget=lambda self: self.transpose()) transpose = _arraymethod('transpose')
[ドキュメント] def tolist(self, fill_value=None): """ Returns the data portion of the masked array as a hierarchical Python list. Data items are converted to the nearest compatible Python type. Masked values are converted to `fill_value`. If `fill_value` is None, the corresponding entries in the output list will be ``None``. Parameters ---------- fill_value : scalar, optional The value to use for invalid entries. Default is None. Returns ------- result : list The Python list representation of the masked array. Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array([[1,2,3], [4,5,6], [7,8,9]], mask=[0] + [1,0]*4) >>> x.tolist() [[1, None, 3], [None, 5, None], [7, None, 9]] >>> x.tolist(-999) [[1, -999, 3], [-999, 5, -999], [7, -999, 9]] """ return self.get().tolist(fill_value)
[ドキュメント] def tobytes(self, fill_value=None, order='C'): """ Returns the array data as a string containing the raw bytes in the array. The array is filled with a fill value before the string conversion. Parameters ---------- fill_value : scalar, optional Value used to fill in the masked values. Default is None, in which case `MaskedArray.fill_value` is used. order : {'C','F','A'}, optional Order of the data item in the copy. Default is 'C'. - 'C' -- C order (row major). - 'F' -- Fortran order (column major). - 'A' -- Any, current order of array. - None -- Same as 'A'. See Also -------- nlcpy.ndarray.tobytes : Constructs Python bytes containing the raw data bytes in the array. tolist : Returns the data portion of the masked array as a hierarchical Python list. Notes ----- As for :func:`nlcpy.ndarray.tobytes`, information about the shape, dtype, etc., but also about `fill_value`, will be lost. Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array(vp.array([[1, 2], [3, 4]]), mask=[[0, 1], [1, 0]]) >>> x.tobytes() b'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00?B\\x0f\\x00\\x00\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x00\\x00\\x00\\x00' """ return self.get().tobytes(fill_value, order)
[ドキュメント] def astype(self, dtype, order='K', casting=None, subok=None, copy=True): if order is None: order = 'K' order_bchar = internal._normalize_order(order) order_char = chr(order_bchar) if casting is not None: raise NotImplementedError('casting is not supported yet') if subok is not None: raise NotImplementedError('subok is not supported yet') dtype = _dtype.get_dtype(dtype) if dtype == self.dtype: if not copy and ( order_char == 'K' or order_char == 'A' and ( self._c_contiguous or self._f_contiguous) or order_char == 'C' and self._c_contiguous or order_char == 'F' and self._f_contiguous): return self order_bchar = core._update_order_char(self, order_bchar) order_char = chr(order_bchar) newarray = array( self.data, dtype=dtype, order=order_char, fill_value=self._fill_value, mask=self._mask) return newarray
# ------------------------------------------------------------------------- # nlcpy original attributes and methods # -------------------------------------------------------------------------
[ドキュメント] def get(self, order='C'): data = self._data.get(order) mask = self._mask fill_value = self._fill_value if isinstance(mask, ndarray): mask = mask.get(order) if isinstance(fill_value, ndarray): fill_value = fill_value.get(order) hardmask = self._hardmask return numpy.ma.array( data, mask=mask, fill_value=fill_value, hard_mask=hardmask)
def __getattr__(self, attr): raise AttributeError( "'nlcpy.ma.MaskedArray' object has no attribute '{}'.".format(attr))
masked_array = MaskedArray class _MaskedUFunc: def __init__(self, ufunc): self.f = ufunc def __str__(self): return f"Masked version of {self.f}" class _DomainSafeDivide: """ Define a domain for safe division. """ def __init__(self, tolerance=None): self.tolerance = tolerance def __call__(self, a, b): # Delay the selection of the tolerance to here in order to reduce numpy # import times. The calculation of these parameters is a substantial # component of numpy's import time. if self.tolerance is None: self.tolerance = numpy.finfo(float).tiny # don't call ma ufuncs from __array_wrap__ which would fail for scalars a, b = nlcpy.asarray(a), nlcpy.asarray(b) return nlcpy.absolute(a) * self.tolerance >= nlcpy.absolute(b) class _MaskedBinaryOperation(_MaskedUFunc): def __init__(self, mbfunc, fillx=0, filly=0): super().__init__(mbfunc) self.fillx = fillx self.filly = filly ufunc_domain[mbfunc] = None ufunc_fills[mbfunc] = (fillx, filly) def __call__(self, a, b, *args, **kwargs): (da, db) = (getdata(a), getdata(b)) (ma, mb) = (getmask(a), getmask(b)) if ma is nomask: if mb is nomask: m = nomask else: m = nlcpy.logical_or(getmaskarray(a), mb) elif mb is nomask: m = nlcpy.logical_or(ma, getmaskarray(b)) else: m = nlcpy.logical_or(ma, mb) result = self.f(da, db, *args, **kwargs) if not numpy.isscalar(a): nlcpy.copyto(result, da, where=m) if not result.ndim: return masked if m else result masked_result = array(result, mask=m) if isinstance(a, MaskedArray): masked_result._update_from(a) elif isinstance(b, MaskedArray): masked_result._update_from(b) masked_result._sharedmask = False return masked_result add = _MaskedBinaryOperation(ufunc_op.add) subtract = _MaskedBinaryOperation(ufunc_op.subtract) multiply = _MaskedBinaryOperation(ufunc_op.multiply) class _DomainedBinaryOperation(_MaskedUFunc): """Defines binary operations that have a domain, like divide. They have no reduce, outer or accumulate. Parameters ---------- mbfunc : function The function for which to define a masked version. Made available as ``_DomainedBinaryOperation.f``. domain : class instance Default domain for the function. Should be one of the ``_Domain*`` classes. fillx : scalar, optional Filling value for the first argument, default is 0. filly : scalar, optional Filling value for the second argument, default is 0. """ def __init__(self, dbfunc, domain, fillx=0, filly=0): """abfunc(fillx, filly) must be defined. abfunc(x, filly) = x for all x to enable reduce. """ super(_DomainedBinaryOperation, self).__init__(dbfunc) self.domain = domain self.fillx = fillx self.filly = filly ufunc_domain[dbfunc] = domain ufunc_fills[dbfunc] = (fillx, filly) def __call__(self, a, b, *args, **kwargs): "Execute the call behavior." # Get the data (da, db) = (getdata(a), getdata(b)) # Get the result result = self.f(da, db, *args, **kwargs) # Get the mask as a combination of the source masks and invalid m1 = getmask(a) m2 = getmask(b) if m1 is nomask and m2 is nomask: m = nlcpy.zeros_like(result, dtype=numpy.bool_) m1 = m m2 = m else: m = nlcpy.empty_like(result, dtype=numpy.bool_) if m1 is nomask: m1 = m2 elif m2 is nomask: m2 = m1 request._push_request( "nlcpy_domain_mask", "mask_op", (m1, m2, result, m), ) # Apply the domain domain = ufunc_domain.get(self.f, None) if domain is not None: m |= domain(da, db) # Take care of the scalar case first if not m.ndim: if m: return masked else: return result # When the mask is True, put back da if possible # any errors, just abort; impossible to guarantee masked values if type(a) is MaskedArray: try: nlcpy.copyto(result, 0, casting='unsafe', where=m) # avoid using "*" since this may be overlaid masked_da = nlcpy.multiply(m, da) # only add back if it can be cast safely if numpy.can_cast(masked_da.dtype, result.dtype, casting='safe'): result += masked_da except Exception: pass # Transforms to a (subclass of) MaskedArray masked_result = result.view(MaskedArray) masked_result._mask = m if isinstance(a, MaskedArray): masked_result._update_from(a) elif isinstance(b, MaskedArray): masked_result._update_from(b) masked_result._sharedmask = False return masked_result divide = _DomainedBinaryOperation(ufunc_op.divide, _DomainSafeDivide(), 0, 1) true_divide = _DomainedBinaryOperation(ufunc_op.true_divide, _DomainSafeDivide(), 0, 1)
[ドキュメント]def filled(a, fill_value=None): """Returns input as an array with masked data replaced by a fill value. If `a` is not a `MaskedArray`, `a` itself is returned. If `a` is a `MaskedArray` and `fill_value` is None, `fill_value` is set to ``a.fill_value``. Parameters ---------- a : MaskedArray or array_like An input object. fill_value : array_like, optional. Can be scalar or non-scalar. If non-scalar, the resulting filled array should be broadcastable over input array. Default is None. Returns ------- a : ndarray The filled array. Examples -------- >>> import nlcpy as vp >>> x = vp.ma.array(vp.arange(9).reshape(3, 3), mask=[[1, 0, 0], ... [1, 0, 0], ... [0, 0, 0]]) >>> x.filled() array([[999999, 1, 2], [999999, 4, 5], [ 6, 7, 8]]) >>> x.filled(fill_value=333) array([[333, 1, 2], [333, 4, 5], [ 6, 7, 8]]) >>> x.filled(fill_value=vp.arange(3)) array([[0, 1, 2], [0, 4, 5], [6, 7, 8]]) """ if hasattr(a, 'filled'): return a.filled(fill_value) elif isinstance(a, ndarray): return a else: return nlcpy.array(a)
def _check_fill_value(fill_value, ndtype): """ Private function validating the given `fill_value` for the given dtype. If fill_value is None, it is set to the default corresponding to the dtype. If fill_value is not None, its value is forced to the given dtype. The result is always a 0d array. """ ndtype = nlcpy.dtype(ndtype) if fill_value is None: fill_value = numpy.array(default_fill_value(ndtype)) else: try: if numpy.isscalar(fill_value): fill_value = numpy.array(fill_value, copy=False, dtype=ndtype) else: fill_value = nlcpy.array(fill_value, copy=False, dtype=ndtype) except (OverflowError, ValueError) as e: err_msg = "Cannot convert fill_value %s to dtype %s" raise TypeError(err_msg % (fill_value, ndtype)) from e return fill_value def _get_dtype_of(obj): """ Convert the argument for *_fill_value into a dtype """ if isinstance(obj, nlcpy.dtype): return obj elif hasattr(obj, 'dtype'): return obj.dtype else: return nlcpy.asanyarray(obj).dtype
[ドキュメント]def default_fill_value(obj): """Returns the default fill value for the argument object. The default filling value depends on the datatype of the input array or the type of the input scalar: ======== ======== datatype default ======== ======== bool True int 999999 float 1.e20 complex 1.e20+0j ======== ======== For structured types, a structured scalar is returned, with each field the default fill value for its type. For subarray types, the fill value is an array of the same size containing the default scalar fill value. Parameters ---------- obj : ndarray, dtype or scalar The array data-type or scalar for which the default fill value is returned. Returns ------- fill_value : scalar The default fill value. Examples -------- >>> import nlcpy as vp >>> vp.ma.default_fill_value(1) 999999 >>> vp.ma.default_fill_value(vp.array([1.1, 2., vp.pi])) 1e+20 >>> vp.ma.default_fill_value(vp.dtype(complex)) (1e+20+0j) """ dtype = _get_dtype_of(obj) return default_filler.get(dtype.kind, '?')
[ドキュメント]def getdata(a, subok=None): """Returns the data of a masked array as an ndarray. Returns the data of `a` (if any) as an ndarray if `a` is a ``MaskedArray``, else return `a` as a ndarray or subclass (depending on `subok`) if not. Parameters ---------- a : array_like Input ``MaskedArray``, alternatively a ndarray or a subclass thereof. subok : bool Whether to force the output to be a `pure` ndarray (False) or to return a subclass of ndarray if appropriate. subok=True is Not Implemented. See Also -------- getmask : Returns the mask of a masked array, or nomask. getmaskarray : Returns the mask of a masked array, or full array of False. Examples -------- >>> import nlcpy.ma as ma >>> mask = [[False, True], [False, False]] >>> a = ma.array([[1, 2], [3, 4]], mask=mask, fill_value=2) >>> a masked_array( data=[[1, --], [3, 4]], mask=[[False, True], [False, False]], fill_value=2) >>> ma.getdata(a) array([[1, 2], [3, 4]]) Equivalently use the ``MaskedArray`` `data` attribute. >>> a.data array([[1, 2], [3, 4]]) """ if subok is not None: raise NotImplementedError('subok is not implemented yet') subok = False if numpy.isscalar(a): return a try: data = a._data except AttributeError: data = nlcpy.array(a, copy=False, subok=subok) return data
[ドキュメント]def getmask(a): """Returns the mask of a masked array, or nomask. Returns the mask of `a` as an ndarray if `a` is a `MaskedArray` and the mask is not `nomask`, else return `nomask`. To guarantee a full array of booleans of the same shape as a, use `getmaskarray`. Parameters ---------- a : array_like Input `MaskedArray` for which the mask is required. See Also -------- getdata : Returns the data of a masked array as an ndarray. getmaskarray : Returns the mask of a masked array, or full array of False. Examples -------- >>> import nlcpy.ma as ma >>> mask=[[False, True], [False, False]] >>> a = ma.array([[1, 2],[3, 4]], mask=mask, fill_value=2) >>> a masked_array( data=[[1, --], [3, 4]], mask=[[False, True], [False, False]], fill_value=2) >>> ma.getmask(a) array([[False, True], [False, False]]) Equivalently use the `MaskedArray` `mask` attribute. >>> a.mask array([[False, True], [False, False]]) Result when mask == `nomask` >>> b = ma.masked_array([[1,2],[3,4]]) >>> b masked_array( data=[[1, 2], [3, 4]], mask=False, fill_value=999999) >>> ma.nomask False >>> ma.getmask(b) == ma.nomask True >>> b.mask == ma.nomask True """ return getattr(a, '_mask', nomask)
def _shrink_mask(m): """ Shrinks a mask to nomask if possible """ if not m.any(): return nomask else: return m
[ドキュメント]def make_mask(m, copy=False, shrink=True, dtype=MaskType): """Creates a boolean mask from an array. Returns `m` as a boolean mask, creating a copy if necessary or requested. The function can accept any sequence that is convertible to integers, or ``nomask``. Does not require that contents must be 0s and 1s, values of 0 are interpreted as False, everything else as True. Parameters ---------- m : array_like Potential mask. copy : bool, optional Whether to return a copy of `m` (True) or `m` itself (False). shrink : bool, optional Whether to shrink `m` to ``nomask`` if all its values are False. dtype : dtype, optional Data-type of the output mask. By default, the output mask has a dtype of MaskType (bool). If the dtype is flexible, each field has a boolean dtype. This is ignored when `m` is ``nomask``, in which case ``nomask`` is always returned. Returns ------- result : ndarray A boolean mask derived from `m`. Examples -------- >>> import nlcpy as vp >>> import nlcpy.ma as ma >>> m = [True, False, True, True] >>> ma.make_mask(m) array([ True, False, True, True]) >>> m = [1, 0, 1, 1] >>> ma.make_mask(m) array([ True, False, True, True]) >>> m = [1, 0, 2, -3] >>> ma.make_mask(m) array([ True, False, True, True]) Effect of the `shrink` parameter. >>> m = vp.zeros(4) >>> m array([0., 0., 0., 0.]) >>> ma.make_mask(m) False >>> ma.make_mask(m, shrink=False) array([False, False, False, False]) """ if m is nomask: return nomask # Fill the mask in case there are missing data; turn it into an ndarray. result = nlcpy.array(filled(m, True), copy=copy, dtype=MaskType) # Bas les masques ! if shrink: result = _shrink_mask(result) return result
[ドキュメント]def make_mask_none(newshape, dtype=None): """Returns a boolean mask of the given shape, filled with False. This function returns a boolean ndarray with all entries False, that can be used in common mask manipulations. If a complex dtype is specified, the type of each field is converted to a boolean type. Parameters ---------- newshape : tuple A tuple indicating the shape of the mask. dtype : {None, dtype}, optional If None, use a MaskType instance. Otherwise, use a new datatype with the same fields as `dtype`, converted to boolean types. Returns ------- result : ndarray An ndarray of appropriate shape and dtype, filled with False. See Also -------- make_mask : Creates a boolean mask from an array. Examples -------- >>> import nlcpy.ma as ma >>> ma.make_mask_none((3,)) array([False, False, False]) """ return nlcpy.zeros(newshape, dtype=MaskType)
def mask_or(m1, m2, copy=False, shrink=True): """Combines two masks with the ``logical_or`` operator. The result may be a view on `m1` or `m2` if the other is `nomask` (i.e. False). Parameters ---------- m1, m2 : array_like Input masks. copy : bool, optional If copy is False and one of the inputs is `nomask`, return a view of the other input mask. Defaults to False. shrink : bool, optional Whether to shrink the output to `nomask` if all its values are False. Defaults to True. Returns ------- mask : output mask The result masks values that are masked in either `m1` or `m2`. Raises ------ ValueError If `m1` and `m2` have different flexible dtypes. Examples -------- >>> import nlcpy as vp >>> m1 = vp.ma.make_mask([0, 1, 1, 0]) >>> m2 = vp.ma.make_mask([1, 0, 0, 0]) >>> vp.ma.mask_or(m1, m2) array([ True, True, True, False]) """ if (m1 is nomask) or (m1 is False): dtype = getattr(m2, 'dtype', MaskType) return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype) if (m2 is nomask) or (m2 is False): dtype = getattr(m1, 'dtype', MaskType) return make_mask(m1, copy=copy, shrink=shrink, dtype=dtype) if m1 is m2 and is_mask(m1): return m1 (dtype1, dtype2) = (getattr(m1, 'dtype', None), getattr(m2, 'dtype', None)) if dtype1 != dtype2: raise ValueError("Incompatible dtypes '%s'<>'%s'" % (dtype1, dtype2)) return make_mask(nlcpy.logical_or(m1, m2), copy=copy, shrink=shrink)
[ドキュメント]def getmaskarray(arr): """Returns the mask of a masked array, or full boolean array of False. Returns the mask of `arr` as an ndarray if `arr` is a `MaskedArray` and the mask is not `nomask`, else return a full boolean array of False of the same shape as `arr`. Parameters ---------- arr : array_like Input `MaskedArray` for which the mask is required. See Also -------- getmask : Returns the mask of a masked array, or nomask. getdata : Returns the data of a masked array as an ndarray. Examples -------- >>> import nlcpy.ma as ma >>> mask = [[False, True], [False, False]] >>> a = ma.array([[1, 2],[3, 4]], mask=mask, fill_value=2) >>> a masked_array( data=[[1, --], [3, 4]], mask=[[False, True], [False, False]], fill_value=2) >>> ma.getmaskarray(a) array([[False, True], [False, False]]) Result when mask == ``nomask`` >>> b = ma.masked_array([[1,2],[3,4]]) >>> b masked_array( data=[[1, 2], [3, 4]], mask=False, fill_value=999999) >>> ma.getmaskarray(b) array([[False, False], [False, False]]) """ mask = getmask(arr) if mask is nomask: mask = make_mask_none(nlcpy.shape(arr), getattr(arr, 'dtype', None)) return mask
[ドキュメント]def is_mask(m): """Returns True if m is a valid, standard mask. This function does not check the contents of the input, only that the type is MaskType. In particular, this function returns False if the mask has a flexible dtype. Parameters ---------- m : array_like Array to test. Returns ------- result : bool True if `m.dtype.type` is MaskType, False otherwise. Examples -------- >>> import nlcpy as vp >>> import nlcpy.ma as ma >>> mask = [True, False, True, False, False] >>> m = ma.array([0, 1, 0, 2, 3], mask=mask, fill_value=0) >>> m masked_array(data=[--, 1, --, 2, 3], mask=[ True, False, True, False, False], fill_value=0) >>> ma.is_mask(m) False >>> ma.is_mask(m.mask) True Input must be an ndarray (or have similar attributes) for it to be considered a valid mask. >>> m = [False, True, False] >>> ma.is_mask(m) False >>> m = vp.array([False, True, False]) >>> m array([False, True, False]) >>> ma.is_mask(m) True """ try: return m.dtype.type is MaskType except AttributeError: return False
[ドキュメント]def array(data, dtype=None, copy=False, order=None, mask=nomask, fill_value=None, keep_mask=True, hard_mask=False, shrink=True, subok=None, ndmin=0): """ Shortcut to MaskedArray. The options are in a different order for convenience and backwards compatibility. """ return MaskedArray(data, mask=mask, dtype=dtype, copy=copy, subok=subok, keep_mask=keep_mask, hard_mask=hard_mask, fill_value=fill_value, ndmin=ndmin, shrink=shrink, order=order)
def take(a, indices, axis=None, out=None, mode='raise'): """ """ a = masked_array(a) return a.take(indices, axis=axis, out=out, mode=mode)
[ドキュメント]def transpose(a, axes=None): """ Permutes the dimensions of an array. This function is exactly equivalent to :func:`nlcpy.transpose`. See Also -------- nlcpy.transpose : Equivalent function in top-level NLCPy module. Examples -------- >>> import nlcpy as vp >>> import nlcpy.ma as ma >>> mask = [[False, False], [False, True]] >>> x = ma.array([[0, 1], [2, 3]], mask=mask) >>> x masked_array( data=[[0, 1], [2, --]], mask=[[False, False], [False, True]], fill_value=999999) >>> ma.transpose(x) masked_array( data=[[0, 2], [1, --]], mask=[[False, False], [False, True]], fill_value=999999) """ # We can't use 'frommethod', as 'transpose' doesn't take keywords try: return a.transpose(axes) except AttributeError: return ndarray(a, copy=False).transpose(axes).view(MaskedArray)
[ドキュメント]def reshape(a, new_shape, order='C'): """ Returns an array containing the same data with a new shape. Refer to :func:`MaskedArray.reshape` for full documentation. See Also -------- MaskedArray.reshape : equivalent function """ # We can't use 'frommethod', it whine about some parameters. Dmmit. try: return a.reshape(new_shape, order=order) except AttributeError: _tmp = ndarray(a, copy=False).reshape(new_shape, order=order) return _tmp.view(MaskedArray)
[ドキュメント]def resize(x, new_shape): """ Returns a new masked array with the specified size and shape. This is the masked equivalent of the :func:`nlcpy.resize` function. The new array is filled with repeated copies of `x` (in the order that the data are stored in memory). If `x` is masked, the new array will be masked, and the new mask will be a repetition of the old one. See Also -------- nlcpy.resize : Equivalent function in the top level NLCPy module. Examples -------- >>> import nlcpy as vp >>> import nlcpy.ma as ma >>> a = ma.array([[1, 2] ,[3, 4]]) >>> a[0, 1] = ma.masked >>> a masked_array( data=[[1, --], [3, 4]], mask=[[False, True], [False, False]], fill_value=999999) >>> ma.resize(a, (3, 3)) masked_array( data=[[1, --, 3], [4, 1, --], [3, 4, 1]], mask=[[False, True, False], [False, False, True], [False, False, False]], fill_value=999999) A MaskedArray is always returned, regardless of the input type. >>> a = vp.array([[1, 2] ,[3, 4]]) >>> ma.resize(a, (3, 3)) masked_array( data=[[1, 2, 3], [4, 1, 2], [3, 4, 1]], mask=False, fill_value=999999) """ # We can't use _frommethods here, as N.resize is notoriously whiny. m = getmask(x) if m is not nomask: m = nlcpy.resize(m, new_shape) data = x if isinstance(x, ndarray) else x._data result = nlcpy.resize(data, new_shape).view(MaskedArray) result._sharedmask = False if result.ndim: result._mask = m return result
def asarray(a, dtype=None, order=None): """ Converts the input to a masked array of the given data-type. No copy is performed if the input is already an `ndarray`. If `a` is a subclass of `MaskedArray`, a base class `MaskedArray` is returned. Parameters ---------- a : array_like Input data, in any form that can be converted to a masked array. This includes lists, lists of tuples, tuples, tuples of tuples, tuples of lists, ndarrays and masked arrays. dtype : dtype, optional By default, the data-type is inferred from the input data. order : {'C', 'F'}, optional Whether to use row-major ('C') or column-major ('FORTRAN') memory representation. Default is 'C'. Returns ------- out : MaskedArray Masked array interpretation of `a`. See Also -------- asanyarray : Converts the input to a masked array, conserving subclasses. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(10.).reshape(2, 5) >>> x array([[0., 1., 2., 3., 4.], [5., 6., 7., 8., 9.]]) >>> vp.ma.asarray(x) masked_array( data=[[0., 1., 2., 3., 4.], [5., 6., 7., 8., 9.]], mask=False, fill_value=1e+20) >>> type(np.ma.asarray(x)) <class 'nlcpy.ma.core.MaskedArray'> """ order = order or 'C' return masked_array(a, dtype=dtype, copy=False, keep_mask=True, order=order) def asanyarray(a, dtype=None): """ Converts the input to a masked array, conserving subclasses. If `a` is a subclass of `MaskedArray`, its class is conserved. No copy is performed if the input is already an `ndarray`. Parameters ---------- a : array_like Input data, in any form that can be converted to an array. dtype : dtype, optional By default, the data-type is inferred from the input data. order : {'C', 'F'}, optional Whether to use row-major ('C') or column-major ('FORTRAN') memory representation. Default is 'C'. Returns ------- out : MaskedArray MaskedArray interpretation of `a`. See Also -------- asarray : Converts the input to a masked array of the given data-type. Examples -------- >>> import nlcpy as vp >>> x = vp.arange(10.).reshape(2, 5) >>> x array([[0., 1., 2., 3., 4.], [5., 6., 7., 8., 9.]]) >>> vp.ma.asanyarray(x) masked_array( data=[[0., 1., 2., 3., 4.], [5., 6., 7., 8., 9.]], mask=False, fill_value=1e+20) >>> type(vp.ma.asanyarray(x)) <class 'nlcpy.ma.core.MaskedArray'> """ if isinstance(a, MaskedArray) and (dtype is None or dtype == a.dtype): return a return masked_array(a, dtype=dtype, copy=False, keep_mask=True)
[ドキュメント]def copy(a, order='K'): """ Returns a copy of the array. Refer to :func:`nlcpy.ma.MaskedArray.copy` for full documentation. """ marr = asanyarray(a) return marr.copy(order)
def diagonal(a, offset=0, axis1=0, axis2=1): """ Returns specified diagonals. Refer to :func:`nlcpy.ma.MaskedArray.diagonal` for full documentation. """ marr = asanyarray(a) return marr.diagonal(offset, axis1, axis2)
[ドキュメント]def harden_mask(a): """ Forces the mask to hard. Refer to :func:`nlcpy.ma.MaskedArray.harden_mask` for full documentation. """ marr = asanyarray(a) return marr.harden_mask()
[ドキュメント]def ravel(a, order='C'): """ Returns a contiguous flattened array. Refer to :func:`nlcpy.ma.MaskedArray.ravel` for full documentation. """ marr = asanyarray(a) return marr.ravel(order)
def repeat(a, repeats, axis=None): """ Repeats elements of an array. Refer to :func:`nlcpy.ma.MaskedArray.repeat` for full documentation. """ marr = asanyarray(a) return marr.repeat(repeats, axis)
[ドキュメント]def soften_mask(a): """ Forces the mask to soft. Refer to :func:`nlcpy.ma.MaskedArray.soften_mask` for full documentation. """ marr = asanyarray(a) return marr.soften_mask()
[ドキュメント]def swapaxes(a, axis1, axis2): """ Interchanges two axes of an array. Refer to :func:`nlcpy.swapaxes` for full documentation. """ marr = asanyarray(a) return marr.swapaxes(axis1, axis2)