diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2015-07-25 15:58:52 -0400 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2015-07-25 15:58:52 -0400 |
commit | 5eeb3c45fe407137771105ff863a46d623e7af84 (patch) | |
tree | 6f657949634f733e776cab94c2051eb684c353d1 /numpy | |
parent | 9918d35e1ac09e2d5b3548db22f4caff93fe5ac2 (diff) | |
parent | acd85d569c81e12b0b2ee37e40997cbabbd5ebc6 (diff) | |
download | numpy-5eeb3c45fe407137771105ff863a46d623e7af84.tar.gz |
Merge pull request #6046 from charris/pep8-and-pyflakes-cleanups
PEP8 and pyflakes fixups for numpy/ma/*.py and numpy/ma/tests/*.py
Merge cleanups prior to 1.10 release.
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/lib/tests/test_io.py | 16 | ||||
-rw-r--r-- | numpy/lib/tests/test_recfunctions.py | 5 | ||||
-rw-r--r-- | numpy/ma/__init__.py | 8 | ||||
-rw-r--r-- | numpy/ma/bench.py | 75 | ||||
-rw-r--r-- | numpy/ma/core.py | 1400 | ||||
-rw-r--r-- | numpy/ma/extras.py | 94 | ||||
-rw-r--r-- | numpy/ma/mrecords.py | 318 | ||||
-rw-r--r-- | numpy/ma/setup.py | 7 | ||||
-rw-r--r-- | numpy/ma/tests/test_core.py | 318 | ||||
-rw-r--r-- | numpy/ma/tests/test_extras.py | 59 | ||||
-rw-r--r-- | numpy/ma/tests/test_mrecords.py | 59 | ||||
-rw-r--r-- | numpy/ma/tests/test_old_ma.py | 38 | ||||
-rw-r--r-- | numpy/ma/tests/test_subclassing.py | 15 | ||||
-rw-r--r-- | numpy/ma/testutils.py | 153 | ||||
-rw-r--r-- | numpy/ma/timer_comparison.py | 123 |
15 files changed, 1438 insertions, 1250 deletions
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py index 8a939f85e..fbeb7fb0a 100644 --- a/numpy/lib/tests/test_io.py +++ b/numpy/lib/tests/test_io.py @@ -13,15 +13,17 @@ from datetime import datetime import numpy as np import numpy.ma as ma -from numpy.lib._iotools import (ConverterError, ConverterLockError, - ConversionWarning) +from numpy.lib._iotools import ( + ConverterError, ConverterLockError, ConversionWarning + ) from numpy.compat import asbytes, bytes, unicode from nose import SkipTest -from numpy.ma.testutils import ( - TestCase, assert_equal, assert_array_equal, assert_allclose, - assert_raises, assert_raises_regex, run_module_suite -) -from numpy.testing import assert_warns, assert_, build_err_msg +from numpy.ma.testutils import assert_equal, assert_almost_equal +from numpy.testing import ( + TestCase, run_module_suite, assert_warns, assert_, build_err_msg, + assert_raises_regex, assert_raises, assert_allclose, + assert_array_equal, + ) from numpy.testing.utils import tempdir diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py index 13e75cbd0..09cc29dc1 100644 --- a/numpy/lib/tests/test_recfunctions.py +++ b/numpy/lib/tests/test_recfunctions.py @@ -3,9 +3,8 @@ from __future__ import division, absolute_import, print_function import numpy as np import numpy.ma as ma from numpy.ma.mrecords import MaskedRecords -from numpy.ma.testutils import ( - run_module_suite, TestCase, assert_, assert_equal - ) +from numpy.ma.testutils import assert_equal +from numpy.testing import TestCase, run_module_suite, assert_ from numpy.lib.recfunctions import ( drop_fields, rename_fields, get_fieldstructure, recursive_fill_fields, find_duplicates, merge_arrays, append_fields, stack_arrays, join_by diff --git a/numpy/ma/__init__.py b/numpy/ma/__init__.py index 0cb92f667..05b641dff 100644 --- a/numpy/ma/__init__.py +++ b/numpy/ma/__init__.py @@ -35,14 +35,12 @@ may now proceed to calculate the mean of the other values: .. [1] Not-a-Number, a floating point value that is the result of an invalid operation. +.. moduleauthor:: Pierre Gerard-Marchant +.. moduleauthor:: Jarrod Millman + """ from __future__ import division, absolute_import, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' - from . import core from .core import * diff --git a/numpy/ma/bench.py b/numpy/ma/bench.py index 75e6d90c8..b86197018 100644 --- a/numpy/ma/bench.py +++ b/numpy/ma/bench.py @@ -1,22 +1,16 @@ -#! python -# encoding: utf-8 -from __future__ import division, absolute_import, print_function +#! /usr/bin/env python +from __future__ import division, print_function import timeit -#import IPython.ipapi -#ip = IPython.ipapi.get() -#from IPython import ipmagic import numpy -#from numpy import ma -#from numpy.ma import filled -#from numpy.ma.testutils import assert_equal -#####--------------------------------------------------------------------------- -#---- --- Global variables --- -#####--------------------------------------------------------------------------- +############################################################################### +# Global variables # +############################################################################### + -# Small arrays .................................. +# Small arrays xs = numpy.random.uniform(-1, 1, 6).reshape(2, 3) ys = numpy.random.uniform(-1, 1, 6).reshape(2, 3) zs = xs + 1j * ys @@ -25,7 +19,8 @@ m2 = [[True, False, True], [False, False, True]] nmxs = numpy.ma.array(xs, mask=m1) nmys = numpy.ma.array(ys, mask=m2) nmzs = numpy.ma.array(zs, mask=m1) -# Big arrays .................................... + +# Big arrays xl = numpy.random.uniform(-1, 1, 100*100).reshape(100, 100) yl = numpy.random.uniform(-1, 1, 100*100).reshape(100, 100) zl = xl + 1j * yl @@ -35,9 +30,11 @@ nmxl = numpy.ma.array(xl, mask=maskx) nmyl = numpy.ma.array(yl, mask=masky) nmzl = numpy.ma.array(zl, mask=maskx) -#####--------------------------------------------------------------------------- -#---- --- Functions --- -#####--------------------------------------------------------------------------- + +############################################################################### +# Functions # +############################################################################### + def timer(s, v='', nloop=500, nrep=3): units = ["s", "ms", "µs", "ns"] @@ -55,8 +52,6 @@ def timer(s, v='', nloop=500, nrep=3): 3, best * scaling[order], units[order])) -# ip.magic('timeit -n%i %s' % (nloop,s)) - def compare_functions_1v(func, nloop=500, @@ -66,7 +61,7 @@ def compare_functions_1v(func, nloop=500, print("%s on small arrays" % funcname) module, data = "numpy.ma", "nmxs" timer("%(module)s.%(funcname)s(%(data)s)" % locals(), v="%11s" % module, nloop=nloop) - # + print("%s on large arrays" % funcname) module, data = "numpy.ma", "nmxl" timer("%(module)s.%(funcname)s(%(data)s)" % locals(), v="%11s" % module, nloop=nloop) @@ -78,7 +73,7 @@ def compare_methods(methodname, args, vars='x', nloop=500, test=True, print("%s on small arrays" % methodname) data, ver = "nm%ss" % vars, 'numpy.ma' timer("%(data)s.%(methodname)s(%(args)s)" % locals(), v=ver, nloop=nloop) - # + print("%s on large arrays" % methodname) data, ver = "nm%sl" % vars, 'numpy.ma' timer("%(data)s.%(methodname)s(%(args)s)" % locals(), v=ver, nloop=nloop) @@ -94,51 +89,22 @@ def compare_functions_2v(func, nloop=500, test=True, print("%s on small arrays" % funcname) module, data = "numpy.ma", "nmxs,nmys" timer("%(module)s.%(funcname)s(%(data)s)" % locals(), v="%11s" % module, nloop=nloop) - # + print("%s on large arrays" % funcname) module, data = "numpy.ma", "nmxl,nmyl" timer("%(module)s.%(funcname)s(%(data)s)" % locals(), v="%11s" % module, nloop=nloop) return -############################################################################### - - -################################################################################ if __name__ == '__main__': -# # Small arrays .................................. -# xs = numpy.random.uniform(-1,1,6).reshape(2,3) -# ys = numpy.random.uniform(-1,1,6).reshape(2,3) -# zs = xs + 1j * ys -# m1 = [[True, False, False], [False, False, True]] -# m2 = [[True, False, True], [False, False, True]] -# nmxs = numpy.ma.array(xs, mask=m1) -# nmys = numpy.ma.array(ys, mask=m2) -# nmzs = numpy.ma.array(zs, mask=m1) -# mmxs = maskedarray.array(xs, mask=m1) -# mmys = maskedarray.array(ys, mask=m2) -# mmzs = maskedarray.array(zs, mask=m1) -# # Big arrays .................................... -# xl = numpy.random.uniform(-1,1,100*100).reshape(100,100) -# yl = numpy.random.uniform(-1,1,100*100).reshape(100,100) -# zl = xl + 1j * yl -# maskx = xl > 0.8 -# masky = yl < -0.8 -# nmxl = numpy.ma.array(xl, mask=maskx) -# nmyl = numpy.ma.array(yl, mask=masky) -# nmzl = numpy.ma.array(zl, mask=maskx) -# mmxl = maskedarray.array(xl, mask=maskx, shrink=True) -# mmyl = maskedarray.array(yl, mask=masky, shrink=True) -# mmzl = maskedarray.array(zl, mask=maskx, shrink=True) -# compare_functions_1v(numpy.sin) compare_functions_1v(numpy.log) compare_functions_1v(numpy.sqrt) - #.................................................................... + compare_functions_2v(numpy.multiply) compare_functions_2v(numpy.divide) compare_functions_2v(numpy.power) - #.................................................................... + compare_methods('ravel', '', nloop=1000) compare_methods('conjugate', '', 'z', nloop=1000) compare_methods('transpose', '', nloop=1000) @@ -148,7 +114,7 @@ if __name__ == '__main__': compare_methods('__getitem__', '[0,-1]', nloop=1000) compare_methods('__setitem__', '0, 17', nloop=1000, test=False) compare_methods('__setitem__', '(0,0), 17', nloop=1000, test=False) - #.................................................................... + print("-"*50) print("__setitem__ on small arrays") timer('nmxs.__setitem__((-1,0),numpy.ma.masked)', 'numpy.ma ', nloop=10000) @@ -157,7 +123,6 @@ if __name__ == '__main__': print("__setitem__ on large arrays") timer('nmxl.__setitem__((-1,0),numpy.ma.masked)', 'numpy.ma ', nloop=10000) - #.................................................................... print("-"*50) print("where on small arrays") timer('numpy.ma.where(nmxs>2,nmxs,nmys)', 'numpy.ma ', nloop=1000) diff --git a/numpy/ma/core.py b/numpy/ma/core.py index c47bcc073..d4771fb31 100644 --- a/numpy/ma/core.py +++ b/numpy/ma/core.py @@ -40,58 +40,50 @@ if sys.version_info[0] >= 3: else: import cPickle as pickle -__author__ = "Pierre GF Gerard-Marchant" -__docformat__ = "restructuredtext en" - -__all__ = ['MAError', 'MaskError', 'MaskType', 'MaskedArray', - 'bool_', - 'abs', 'absolute', 'add', 'all', 'allclose', 'allequal', 'alltrue', - 'amax', 'amin', 'angle', 'anom', 'anomalies', 'any', 'append', 'arange', - 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', - 'arctanh', 'argmax', 'argmin', 'argsort', 'around', - 'array', 'asarray', 'asanyarray', - 'bitwise_and', 'bitwise_or', 'bitwise_xor', - 'ceil', 'choose', 'clip', 'common_fill_value', 'compress', - 'compressed', 'concatenate', 'conjugate', 'copy', 'cos', 'cosh', - 'count', 'cumprod', 'cumsum', - 'default_fill_value', 'diag', 'diagonal', 'diff', 'divide', 'dump', - 'dumps', - 'empty', 'empty_like', 'equal', 'exp', 'expand_dims', - 'fabs', 'flatten_mask', 'fmod', 'filled', 'floor', 'floor_divide', - 'fix_invalid', 'flatten_structured_array', 'frombuffer', 'fromflex', - 'fromfunction', - 'getdata', 'getmask', 'getmaskarray', 'greater', 'greater_equal', - 'harden_mask', 'hypot', - 'identity', 'ids', 'indices', 'inner', 'innerproduct', - 'isMA', 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', - 'left_shift', 'less', 'less_equal', 'load', 'loads', 'log', 'log2', - 'log10', 'logical_and', 'logical_not', 'logical_or', 'logical_xor', - 'make_mask', 'make_mask_descr', 'make_mask_none', 'mask_or', - 'masked', 'masked_array', 'masked_equal', 'masked_greater', - 'masked_greater_equal', 'masked_inside', 'masked_invalid', - 'masked_less', 'masked_less_equal', 'masked_not_equal', - 'masked_object', 'masked_outside', 'masked_print_option', - 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum', - 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value', - 'mod', 'multiply', 'mvoid', - 'negative', 'nomask', 'nonzero', 'not_equal', - 'ones', 'outer', 'outerproduct', - 'power', 'prod', 'product', 'ptp', 'put', 'putmask', - 'rank', 'ravel', 'remainder', 'repeat', 'reshape', 'resize', - 'right_shift', 'round_', 'round', - 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'sometrue', - 'sort', 'soften_mask', 'sqrt', 'squeeze', 'std', 'subtract', 'sum', - 'swapaxes', - 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide', - 'var', 'where', - 'zeros'] +__all__ = [ + 'MAError', 'MaskError', 'MaskType', 'MaskedArray', 'abs', 'absolute', + 'add', 'all', 'allclose', 'allequal', 'alltrue', 'amax', 'amin', + 'angle', 'anom', 'anomalies', 'any', 'append', 'arange', 'arccos', + 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh', + 'argmax', 'argmin', 'argsort', 'around', 'array', 'asanyarray', + 'asarray', 'bitwise_and', 'bitwise_or', 'bitwise_xor', 'bool_', 'ceil', + 'choose', 'clip', 'common_fill_value', 'compress', 'compressed', + 'concatenate', 'conjugate', 'copy', 'cos', 'cosh', 'count', 'cumprod', + 'cumsum', 'default_fill_value', 'diag', 'diagonal', 'diff', 'divide', + 'dump', 'dumps', 'empty', 'empty_like', 'equal', 'exp', 'expand_dims', + 'fabs', 'filled', 'fix_invalid', 'flatten_mask', + 'flatten_structured_array', 'floor', 'floor_divide', 'fmod', + 'frombuffer', 'fromflex', 'fromfunction', 'getdata', 'getmask', + 'getmaskarray', 'greater', 'greater_equal', 'harden_mask', 'hypot', + 'identity', 'ids', 'indices', 'inner', 'innerproduct', 'isMA', + 'isMaskedArray', 'is_mask', 'is_masked', 'isarray', 'left_shift', + 'less', 'less_equal', 'load', 'loads', 'log', 'log10', 'log2', + 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'make_mask', + 'make_mask_descr', 'make_mask_none', 'mask_or', 'masked', + 'masked_array', 'masked_equal', 'masked_greater', + 'masked_greater_equal', 'masked_inside', 'masked_invalid', + 'masked_less', 'masked_less_equal', 'masked_not_equal', + 'masked_object', 'masked_outside', 'masked_print_option', + 'masked_singleton', 'masked_values', 'masked_where', 'max', 'maximum', + 'maximum_fill_value', 'mean', 'min', 'minimum', 'minimum_fill_value', + 'mod', 'multiply', 'mvoid', 'ndim', 'negative', 'nomask', 'nonzero', + 'not_equal', 'ones', 'outer', 'outerproduct', 'power', 'prod', + 'product', 'ptp', 'put', 'putmask', 'rank', 'ravel', 'remainder', + 'repeat', 'reshape', 'resize', 'right_shift', 'round', 'round_', + 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'soften_mask', + 'sometrue', 'sort', 'sqrt', 'squeeze', 'std', 'subtract', 'sum', + 'swapaxes', 'take', 'tan', 'tanh', 'trace', 'transpose', 'true_divide', + 'var', 'where', 'zeros', + ] MaskType = np.bool_ nomask = MaskType(0) + def doc_note(initialdoc, note): """ Adds a Notes section to an existing docstring. + """ if initialdoc is None: return @@ -106,46 +98,55 @@ def doc_note(initialdoc, note): """ return newdoc % (initialdoc, note) + def get_object_signature(obj): """ Get the signature from obj + """ try: sig = formatargspec(*getargspec(obj)) - except TypeError as errmsg: + except TypeError: sig = '' -# msg = "Unable to retrieve the signature of %s '%s'\n"\ -# "(Initial error message: %s)" -# warnings.warn(msg % (type(obj), -# getattr(obj, '__name__', '???'), -# errmsg)) return sig -#####-------------------------------------------------------------------------- -#---- --- Exceptions --- -#####-------------------------------------------------------------------------- +############################################################################### +# Exceptions # +############################################################################### + + class MAError(Exception): - """Class for masked array related errors.""" + """ + Class for masked array related errors. + + """ pass + + class MaskError(MAError): - "Class for mask related errors." + """ + Class for mask related errors. + + """ pass -#####-------------------------------------------------------------------------- -#---- --- Filling options --- -#####-------------------------------------------------------------------------- +############################################################################### +# Filling options # +############################################################################### + + # b: boolean - c: complex - f: floats - i: integer - O: object - S: string default_filler = {'b': True, - 'c' : 1.e20 + 0.0j, - 'f' : 1.e20, - 'i' : 999999, - 'O' : '?', - 'S' : 'N/A', - 'u' : 999999, - 'V' : '???', - 'U' : 'N/A' + 'c': 1.e20 + 0.0j, + 'f': 1.e20, + 'i': 999999, + 'O': '?', + 'S': 'N/A', + 'u': 999999, + 'V': '???', + 'U': 'N/A' } # Add datetime64 and timedelta64 types @@ -369,11 +370,13 @@ def _recursive_set_default_fill_value(dtypedescr): for currentdescr in dtypedescr: currenttype = currentdescr[1] if isinstance(currenttype, list): - deflist.append(tuple(_recursive_set_default_fill_value(currenttype))) + deflist.append( + tuple(_recursive_set_default_fill_value(currenttype))) else: deflist.append(default_fill_value(np.dtype(currenttype))) return tuple(deflist) + def _recursive_set_fill_value(fillvalue, dtypedescr): fillvalue = np.resize(fillvalue, len(dtypedescr)) output_value = [] @@ -425,7 +428,7 @@ def _check_fill_value(fill_value, ndtype): err_msg = "Cannot set fill value of string with array of dtype %s" raise TypeError(err_msg % ndtype) else: - # In case we want to convert 1e20 to int... + # In case we want to convert 1e20 to int. try: fill_value = np.array(fill_value, copy=False, dtype=ndtype) except OverflowError: @@ -501,6 +504,7 @@ def set_fill_value(a, fill_value): a.set_fill_value(fill_value) return + def get_fill_value(a): """ Return the filling value of a, if any. Otherwise, returns the @@ -513,6 +517,7 @@ def get_fill_value(a): result = default_fill_value(a) return result + def common_fill_value(a, b): """ Return the common filling value of two masked arrays, if any. @@ -545,7 +550,6 @@ def common_fill_value(a, b): return None -#####-------------------------------------------------------------------------- def filled(a, fill_value=None): """ Return input as an array with masked data replaced by a fill value. @@ -591,10 +595,11 @@ def filled(a, fill_value=None): else: return np.array(a) -#####-------------------------------------------------------------------------- + def get_masked_subclass(*arrays): """ Return the youngest subclass of MaskedArray from a list of (masked) arrays. + In case of siblings, the first listed takes over. """ @@ -617,7 +622,7 @@ def get_masked_subclass(*arrays): return MaskedArray return rcls -#####-------------------------------------------------------------------------- + def getdata(a, subok=True): """ Return the data of a masked array as an ndarray. @@ -668,6 +673,8 @@ def getdata(a, subok=True): if not subok: return data.view(ndarray) return data + + get_data = getdata @@ -721,7 +728,6 @@ def fix_invalid(a, mask=nomask, copy=True, fill_value=None): """ a = masked_array(a, copy=copy, mask=mask, subok=True) - #invalid = (numpy.isnan(a._data) | numpy.isinf(a._data)) invalid = np.logical_not(np.isfinite(a._data)) if not invalid.any(): return a @@ -732,13 +738,15 @@ def fix_invalid(a, mask=nomask, copy=True, fill_value=None): return a +############################################################################### +# Ufuncs # +############################################################################### + -#####-------------------------------------------------------------------------- -#---- --- Ufuncs --- -#####-------------------------------------------------------------------------- ufunc_domain = {} ufunc_fills = {} + class _DomainCheckInterval: """ Define a valid interval, so that : @@ -747,6 +755,7 @@ class _DomainCheckInterval: ``x < a`` or ``x > b``. """ + def __init__(self, a, b): "domain_check_interval(a,b)(x) = true where x < a or y > b" if (a > b): @@ -754,35 +763,39 @@ class _DomainCheckInterval: self.a = a self.b = b - def __call__ (self, x): + def __call__(self, x): "Execute the call behavior." - return umath.logical_or(umath.greater (x, self.b), + return umath.logical_or(umath.greater(x, self.b), umath.less(x, self.a)) - class _DomainTan: - """Define a valid interval for the `tan` function, so that: + """ + Define a valid interval for the `tan` function, so that: ``domain_tan(eps) = True`` where ``abs(cos(x)) < eps`` """ + def __init__(self, eps): "domain_tan(eps) = true where abs(cos(x)) < eps)" self.eps = eps - def __call__ (self, x): + def __call__(self, x): "Executes the call behavior." return umath.less(umath.absolute(umath.cos(x)), self.eps) - class _DomainSafeDivide: - """Define a domain for safe division.""" - def __init__ (self, tolerance=None): + """ + Define a domain for safe division. + + """ + + def __init__(self, tolerance=None): self.tolerance = tolerance - def __call__ (self, a, b): + 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. @@ -793,30 +806,36 @@ class _DomainSafeDivide: return umath.absolute(a) * self.tolerance >= umath.absolute(b) - class _DomainGreater: - """DomainGreater(v)(x) is True where x <= v.""" + """ + DomainGreater(v)(x) is True where x <= v. + + """ + def __init__(self, critical_value): "DomainGreater(v)(x) = true where x <= v" self.critical_value = critical_value - def __call__ (self, x): + def __call__(self, x): "Executes the call behavior." return umath.less_equal(x, self.critical_value) - class _DomainGreaterEqual: - """DomainGreaterEqual(v)(x) is True where x < v.""" + """ + DomainGreaterEqual(v)(x) is True where x < v. + + """ + def __init__(self, critical_value): "DomainGreaterEqual(v)(x) = true where x < v" self.critical_value = critical_value - def __call__ (self, x): + def __call__(self, x): "Executes the call behavior." return umath.less(x, self.critical_value) -#.............................................................................. + class _MaskedUnaryOperation: """ Defines masked version of unary operations, where invalid values are @@ -834,12 +853,8 @@ class _MaskedUnaryOperation: classes. Default is None. """ - def __init__ (self, mufunc, fill=0, domain=None): - """ _MaskedUnaryOperation(aufunc, fill=0, domain=None) - aufunc(fill) must be defined - self(x) returns aufunc(x) - with masked values where domain(x) is true or getmask(x) is true. - """ + + def __init__(self, mufunc, fill=0, domain=None): self.f = mufunc self.fill = fill self.domain = domain @@ -847,34 +862,42 @@ class _MaskedUnaryOperation: self.__name__ = getattr(mufunc, "__name__", str(mufunc)) ufunc_domain[mufunc] = domain ufunc_fills[mufunc] = fill - # - def __call__ (self, a, *args, **kwargs): - "Execute the call behavior." + + def __call__(self, a, *args, **kwargs): + """ + Execute the call behavior. + + """ d = getdata(a) - # Case 1.1. : Domained function + # Deal with domain if self.domain is not None: + # Case 1.1. : Domained function with np.errstate(divide='ignore', invalid='ignore'): result = self.f(d, *args, **kwargs) # Make a mask m = ~umath.isfinite(result) m |= self.domain(d) m |= getmask(a) - # Case 1.2. : Function without a domain else: + # Case 1.2. : Function without a domain # Get the result and the mask result = self.f(d, *args, **kwargs) m = getmask(a) - # Case 2.1. : The result is scalarscalar + if not result.ndim: + # Case 2.1. : The result is scalarscalar if m: return masked return result - # Case 2.2. The result is an array - # We need to fill the invalid data back w/ the input - # Now, that's plain silly: in C, we would just skip the element and keep - # the original, but we do have to do it that way in Python + if m is not nomask: - # In case result has a lower dtype than the inputs (as in equal) + # Case 2.2. The result is an array + # We need to fill the invalid data back w/ the input Now, + # that's plain silly: in C, we would just skip the element and + # keep the original, but we do have to do it that way in Python + + # In case result has a lower dtype than the inputs (as in + # equal) try: np.copyto(result, d, where=m) except TypeError: @@ -884,10 +907,9 @@ class _MaskedUnaryOperation: masked_result._mask = m masked_result._update_from(result) return masked_result - # - def __str__ (self): - return "Masked version of %s. [Invalid values are masked]" % str(self.f) + def __str__(self): + return "Masked version of %s. [Invalid values are masked]" % str(self.f) class _MaskedBinaryOperation: @@ -909,9 +931,13 @@ class _MaskedBinaryOperation: Filling value for the second argument, default is 0. """ - def __init__ (self, mbfunc, fillx=0, filly=0): - """abfunc(fillx, filly) must be defined. - abfunc(x, filly) = x for all x to enable reduce. + + def __init__(self, mbfunc, fillx=0, filly=0): + """ + abfunc(fillx, filly) must be defined. + + abfunc(x, filly) = x for all x to enable reduce. + """ self.f = mbfunc self.fillx = fillx @@ -921,8 +947,11 @@ class _MaskedBinaryOperation: ufunc_domain[mbfunc] = None ufunc_fills[mbfunc] = (fillx, filly) - def __call__ (self, a, b, *args, **kwargs): - "Execute the call behavior." + def __call__(self, a, b, *args, **kwargs): + """ + Execute the call behavior. + + """ # Get the data, as ndarray (da, db) = (getdata(a), getdata(b)) # Get the result @@ -940,11 +969,13 @@ class _MaskedBinaryOperation: m = umath.logical_or(ma, getmaskarray(b)) else: m = umath.logical_or(ma, mb) + # Case 1. : scalar if not result.ndim: if m: return masked return result + # Case 2. : array # Revert result to da where masked if m is not nomask and m.any(): @@ -958,6 +989,7 @@ class _MaskedBinaryOperation: result += masked_da except: pass + # Transforms to a (subclass of) MaskedArray masked_result = result.view(get_masked_subclass(a, b)) masked_result._mask = m @@ -965,7 +997,10 @@ class _MaskedBinaryOperation: return masked_result def reduce(self, target, axis=0, dtype=None): - """Reduce `target` along the given `axis`.""" + """ + Reduce `target` along the given `axis`. + + """ tclass = get_masked_subclass(target) m = getmask(target) t = filled(target, self.filly) @@ -993,7 +1028,8 @@ class _MaskedBinaryOperation: return masked_tr def outer(self, a, b): - """Return the function applied to the outer product of a and b. + """ + Return the function applied to the outer product of a and b. """ (da, db) = (getdata(a), getdata(b)) @@ -1033,7 +1069,6 @@ class _MaskedBinaryOperation: return "Masked version of " + str(self.f) - class _DomainedBinaryOperation: """ Define binary operations that have a domain, like divide. @@ -1054,7 +1089,8 @@ class _DomainedBinaryOperation: Filling value for the second argument, default is 0. """ - def __init__ (self, dbfunc, domain, fillx=0, filly=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. """ @@ -1106,10 +1142,10 @@ class _DomainedBinaryOperation: masked_result._update_from(result) return masked_result - def __str__ (self): + def __str__(self): return "Masked version of " + str(self.f) -#.............................................................................. + # Unary ufuncs exp = _MaskedUnaryOperation(umath.exp) conjugate = _MaskedUnaryOperation(umath.conjugate) @@ -1122,20 +1158,21 @@ sinh = _MaskedUnaryOperation(umath.sinh) cosh = _MaskedUnaryOperation(umath.cosh) tanh = _MaskedUnaryOperation(umath.tanh) abs = absolute = _MaskedUnaryOperation(umath.absolute) -angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base +angle = _MaskedUnaryOperation(angle) # from numpy.lib.function_base fabs = _MaskedUnaryOperation(umath.fabs) negative = _MaskedUnaryOperation(umath.negative) floor = _MaskedUnaryOperation(umath.floor) ceil = _MaskedUnaryOperation(umath.ceil) around = _MaskedUnaryOperation(np.round_) logical_not = _MaskedUnaryOperation(umath.logical_not) -# Domained unary ufuncs ....................................................... + +# Domained unary ufuncs sqrt = _MaskedUnaryOperation(umath.sqrt, 0.0, _DomainGreaterEqual(0.0)) log = _MaskedUnaryOperation(umath.log, 1.0, _DomainGreater(0.0)) log2 = _MaskedUnaryOperation(umath.log2, 1.0, - _DomainGreater(0.0)) + _DomainGreater(0.0)) log10 = _MaskedUnaryOperation(umath.log10, 1.0, _DomainGreater(0.0)) tan = _MaskedUnaryOperation(umath.tan, 0.0, @@ -1148,7 +1185,8 @@ arccosh = _MaskedUnaryOperation(umath.arccosh, 1.0, _DomainGreaterEqual(1.0)) arctanh = _MaskedUnaryOperation(umath.arctanh, 0.0, _DomainCheckInterval(-1.0 + 1e-15, 1.0 - 1e-15)) -# Binary ufuncs ............................................................... + +# Binary ufuncs add = _MaskedBinaryOperation(umath.add) subtract = _MaskedBinaryOperation(umath.subtract) multiply = _MaskedBinaryOperation(umath.multiply, 1, 1) @@ -1174,21 +1212,23 @@ bitwise_and = _MaskedBinaryOperation(umath.bitwise_and) bitwise_or = _MaskedBinaryOperation(umath.bitwise_or) bitwise_xor = _MaskedBinaryOperation(umath.bitwise_xor) hypot = _MaskedBinaryOperation(umath.hypot) -# Domained binary ufuncs ...................................................... + +# Domained binary ufuncs divide = _DomainedBinaryOperation(umath.divide, _DomainSafeDivide(), 0, 1) true_divide = _DomainedBinaryOperation(umath.true_divide, - _DomainSafeDivide(), 0, 1) + _DomainSafeDivide(), 0, 1) floor_divide = _DomainedBinaryOperation(umath.floor_divide, - _DomainSafeDivide(), 0, 1) + _DomainSafeDivide(), 0, 1) remainder = _DomainedBinaryOperation(umath.remainder, - _DomainSafeDivide(), 0, 1) + _DomainSafeDivide(), 0, 1) fmod = _DomainedBinaryOperation(umath.fmod, _DomainSafeDivide(), 0, 1) mod = _DomainedBinaryOperation(umath.mod, _DomainSafeDivide(), 0, 1) -#####-------------------------------------------------------------------------- -#---- --- Mask creation functions --- -#####-------------------------------------------------------------------------- +############################################################################### +# Mask creation functions # +############################################################################### + def _recursive_make_descr(datatype, newtype=bool_): "Private function allowing recursion in make_descr." @@ -1210,6 +1250,7 @@ def _recursive_make_descr(datatype, newtype=bool_): else: return newtype + def make_mask_descr(ndtype): """ Construct a dtype description list from a given dtype. @@ -1245,6 +1286,7 @@ def make_mask_descr(ndtype): ndtype = np.dtype(ndtype) return np.dtype(_recursive_make_descr(ndtype, np.bool)) + def getmask(a): """ Return the mask of a masked array, or nomask. @@ -1304,8 +1346,11 @@ def getmask(a): """ return getattr(a, '_mask', nomask) + + get_mask = getmask + def getmaskarray(arr): """ Return the mask of a masked array, or full boolean array of False. @@ -1360,6 +1405,7 @@ def getmaskarray(arr): mask = make_mask_none(np.shape(arr), getattr(arr, 'dtype', None)) return mask + def is_mask(m): """ Return True if m is a valid, standard mask. @@ -1427,6 +1473,7 @@ def is_mask(m): except AttributeError: return False + def make_mask(m, copy=False, shrink=True, dtype=MaskType): """ Create a boolean mask from an array. @@ -1570,7 +1617,8 @@ def make_mask_none(newshape, dtype=None): result = np.zeros(newshape, dtype=make_mask_descr(dtype)) return result -def mask_or (m1, m2, copy=False, shrink=True): + +def mask_or(m1, m2, copy=False, shrink=True): """ Combine two masks with the ``logical_or`` operator. @@ -1606,6 +1654,7 @@ def mask_or (m1, m2, copy=False, shrink=True): array([ True, True, True, False], dtype=bool) """ + def _recursive_mask_or(m1, m2, newmask): names = m1.dtype.names for name in names: @@ -1615,7 +1664,7 @@ def mask_or (m1, m2, copy=False, shrink=True): else: umath.logical_or(current1, m2[name], newmask[name]) return - # + if (m1 is nomask) or (m1 is False): dtype = getattr(m2, 'dtype', MaskType) return make_mask(m2, copy=copy, shrink=shrink, dtype=dtype) @@ -1665,7 +1714,7 @@ def flatten_mask(mask): array([False, False, False, False, False, True], dtype=bool) """ - # + def _flatmask(mask): "Flatten the mask and returns a (maybe nested) sequence of booleans." mnames = mask.dtype.names @@ -1673,7 +1722,7 @@ def flatten_mask(mask): return [flatten_mask(mask[name]) for name in mnames] else: return mask - # + def _flatsequence(sequence): "Generates a flattened version of the sequence." try: @@ -1685,7 +1734,7 @@ def flatten_mask(mask): yield element except TypeError: yield sequence - # + mask = np.asarray(mask) flattened = _flatsequence(_flatmask(mask)) return np.array([_ for _ in flattened], dtype=bool) @@ -1698,9 +1747,9 @@ def _check_mask_axis(mask, axis): return nomask -#####-------------------------------------------------------------------------- -#--- --- Masking functions --- -#####-------------------------------------------------------------------------- +############################################################################### +# Masking functions # +############################################################################### def masked_where(condition, a, copy=True): """ @@ -1974,11 +2023,6 @@ def masked_equal(x, value, copy=True): fill_value=999999) """ - # An alternative implementation relies on filling first: probably not needed. - # d = filled(x, 0) - # c = umath.equal(d, value) - # m = mask_or(c, getmask(x)) - # return array(d, mask=m, copy=copy) output = masked_where(equal(x, value), x, copy=copy) output.fill_value = value return output @@ -2197,7 +2241,8 @@ def masked_values(x, value, rtol=1e-5, atol=1e-8, copy=True, shrink=True): mabs = umath.absolute xnew = filled(x, value) if issubclass(xnew.dtype.type, np.floating): - condition = umath.less_equal(mabs(xnew - value), atol + rtol * mabs(value)) + condition = umath.less_equal( + mabs(xnew - value), atol + rtol * mabs(value)) mask = getattr(x, '_mask', nomask) else: condition = umath.equal(xnew, value) @@ -2248,49 +2293,68 @@ def masked_invalid(a, copy=True): return result -#####-------------------------------------------------------------------------- -#---- --- Printing options --- -#####-------------------------------------------------------------------------- +############################################################################### +# Printing options # +############################################################################### + class _MaskedPrintOption: """ Handle the string used to represent missing data in a masked array. """ - def __init__ (self, display): - "Create the masked_print_option object." + + def __init__(self, display): + """ + Create the masked_print_option object. + + """ self._display = display self._enabled = True def display(self): - "Display the string to print for masked values." + """ + Display the string to print for masked values. + + """ return self._display - def set_display (self, s): - "Set the string to print for masked values." + def set_display(self, s): + """ + Set the string to print for masked values. + + """ self._display = s def enabled(self): - "Is the use of the display value enabled?" + """ + Is the use of the display value enabled? + + """ return self._enabled def enable(self, shrink=1): - "Set the enabling shrink to `shrink`." + """ + Set the enabling shrink to `shrink`. + + """ self._enabled = shrink - def __str__ (self): + def __str__(self): return str(self._display) __repr__ = __str__ -#if you single index into a masked location you get this object. +# if you single index into a masked location you get this object. masked_print_option = _MaskedPrintOption('--') def _recursive_printoption(result, mask, printopt): """ Puts printoptions in result where mask is True. + Private function allowing for recursion + """ names = result.dtype.names for name in names: @@ -2328,14 +2392,15 @@ masked_%(name)s(data = %(data)s, %(nlen)s dtype = %(dtype)s) """) -#####-------------------------------------------------------------------------- -#---- --- MaskedArray class --- -#####-------------------------------------------------------------------------- +############################################################################### +# MaskedArray class # +############################################################################### + def _recursive_filled(a, mask, fill_value): """ Recursively fill `a` with `fill_value`. - Private function + """ names = a.dtype.names for name in names: @@ -2346,7 +2411,6 @@ def _recursive_filled(a, mask, fill_value): np.copyto(current, fill_value[name], where=mask[name]) - def flatten_structured_array(a): """ Flatten a structured array. @@ -2373,16 +2437,19 @@ def flatten_structured_array(a): [2., 2.]]) """ - # + def flatten_sequence(iterable): - """Flattens a compound of nested iterables.""" + """ + Flattens a compound of nested iterables. + + """ for elm in iter(iterable): if hasattr(elm, '__iter__'): for f in flatten_sequence(elm): yield f else: yield elm - # + a = np.asanyarray(a) inishape = a.shape a = a.ravel() @@ -2400,7 +2467,6 @@ def flatten_structured_array(a): return out - class _arraymethod(object): """ Define a wrapper for basic array methods. @@ -2430,27 +2496,29 @@ class _arraymethod(object): attribute. """ + def __init__(self, funcname, onmask=True): self.__name__ = funcname self._onmask = onmask self.obj = None self.__doc__ = self.getdoc() - # + def getdoc(self): "Return the doc of the function (from the doc of the method)." methdoc = getattr(ndarray, self.__name__, None) or \ - getattr(np, self.__name__, None) + getattr(np, self.__name__, None) if methdoc is not None: return methdoc.__doc__ - # + def __get__(self, obj, objtype=None): self.obj = obj return self - # + def __call__(self, *args, **params): methodname = self.__name__ instance = self.obj - # Fallback : if the instance has not been initialized, use the first arg + # Fallback : if the instance has not been initialized, use the first + # arg if instance is None: args = list(args) instance = args.pop(0) @@ -2517,10 +2585,11 @@ class MaskedIterator(object): fill_value = 999999) """ + def __init__(self, ma): self.ma = ma self.dataiter = ma._data.flat - # + if ma._mask is nomask: self.maskiter = None else: @@ -2543,7 +2612,7 @@ class MaskedIterator(object): return masked return result - ### This won't work is ravel makes a copy + # This won't work if ravel makes a copy def __setitem__(self, index, value): self.dataiter[index] = getdata(value) if self.maskiter is not None: @@ -2640,29 +2709,30 @@ class MaskedArray(ndarray): keep_mask=True, hard_mask=None, shrink=True, **options): """ - Create a new masked array from scratch. + Create a new masked array from scratch. - Notes - ----- - A masked array can also be created by taking a .view(MaskedArray). + Notes + ----- + A masked array can also be created by taking a .view(MaskedArray). """ - # Process data............ + # Process data. _data = np.array(data, dtype=dtype, copy=copy, subok=True, ndmin=ndmin) _baseclass = getattr(data, '_baseclass', type(_data)) - # Check that we're not erasing the mask.......... + # Check that we're not erasing the mask. if isinstance(data, MaskedArray) and (data.shape != _data.shape): copy = True - # Careful, cls might not always be MaskedArray... + # Careful, cls might not always be MaskedArray. if not isinstance(data, cls) or not subok: _data = ndarray.view(_data, cls) else: _data = ndarray.view(_data, type(data)) - # Backwards compatibility w/ numpy.core.ma ....... + # Backwards compatibility w/ numpy.core.ma. if hasattr(data, '_mask') and not isinstance(data, ndarray): _data._mask = data._mask + # FIXME _sharedmask is never used. _sharedmask = True - # Process mask ............................... + # Process mask. # Number of named fields (or zero if none) names_ = _data.dtype.names or () # Type of the mask @@ -2670,9 +2740,10 @@ class MaskedArray(ndarray): mdtype = make_mask_descr(_data.dtype) else: mdtype = MaskType - # Case 1. : no mask in input ............ + if mask is nomask: - # Erase the current mask ? + # Case 1. : no mask in input. + # Erase the current mask ? if not keep_mask: # With a reduced version if shrink: @@ -2702,15 +2773,15 @@ class MaskedArray(ndarray): data._mask.shape = data.shape else: _data._sharedmask = True - # Case 2. : With a mask in input ........ else: + # Case 2. : With a mask in input. # Read the mask with the current mdtype try: mask = np.array(mask, copy=copy, dtype=mdtype) # Or assume it's a sequence of bool/int except TypeError: mask = np.array([tuple([m] * len(mdtype)) for m in mask], - dtype=mdtype) + dtype=mdtype) # Make sure the mask and the data have the same shape if mask.shape != _data.shape: (nd, nm) = (_data.size, mask.size) @@ -2746,10 +2817,10 @@ class MaskedArray(ndarray): else: _data._mask = np.logical_or(mask, _data._mask) _data._sharedmask = False - # Update fill_value....... + # Update fill_value. if fill_value is None: fill_value = getattr(data, '_fill_value', None) - # But don't run the check unless we have something to check.... + # But don't run the check unless we have something to check. if fill_value is not None: _data._fill_value = _check_fill_value(fill_value, _data.dtype) # Process extra options .. @@ -2759,9 +2830,12 @@ class MaskedArray(ndarray): _data._hardmask = hard_mask _data._baseclass = _baseclass return _data - # + + def _update_from(self, obj): - """Copies some attributes of obj to self. + """ + Copies some attributes of obj to self. + """ if obj is not None and isinstance(obj, ndarray): _baseclass = type(obj) @@ -2784,19 +2858,21 @@ class MaskedArray(ndarray): self.__dict__.update(_optinfo) return - def __array_finalize__(self, obj): - """Finalizes the masked array. """ - # Get main attributes ......... + Finalizes the masked array. + + """ + # Get main attributes. self._update_from(obj) + # We have to decide how to initialize self.mask, based on # obj.mask. This is very difficult. There might be some # correspondence between the elements in the array we are being - # created from (= obj) and us. Or... there might not. This method can + # created from (= obj) and us. Or there might not. This method can # be called in all kinds of places for all kinds of reasons -- could - # be empty_like, could be slicing, could be a ufunc, could be a view, - # ... The numpy subclassing interface simply doesn't give us any way + # be empty_like, could be slicing, could be a ufunc, could be a view. + # The numpy subclassing interface simply doesn't give us any way # to know, which means that at best this method will be based on # guesswork and heuristics. To make things worse, there isn't even any # clear consensus about what the desired behavior is. For instance, @@ -2824,6 +2900,7 @@ class MaskedArray(ndarray): make_mask_none(obj.shape, obj.dtype)) else: _mask = getattr(obj, '_mask', nomask) + # If self and obj point to exactly the same data, then probably # self is a simple view of obj (e.g., self = obj[...]), so they # should share the same mask. (This isn't 100% reliable, e.g. self @@ -2837,7 +2914,7 @@ class MaskedArray(ndarray): else: _mask = nomask self._mask = _mask - # Finalize the mask ........... + # Finalize the mask if self._mask is not nomask: try: self._mask.shape = self.shape @@ -2852,20 +2929,21 @@ class MaskedArray(ndarray): self._fill_value = _check_fill_value(None, self.dtype) return - def __array_wrap__(self, obj, context=None): """ Special hook for ufuncs. + Wraps the numpy array and sets the mask according to context. + """ result = obj.view(type(self)) result._update_from(self) - #.......... + if context is not None: result._mask = result._mask.copy() (func, args, _) = context m = reduce(mask_or, [getmaskarray(arg) for arg in args]) - # Get the domain mask................ + # Get the domain mask domain = ufunc_domain.get(func, None) if domain is not None: # Take the domain, and make sure it's a ndarray @@ -2898,9 +2976,8 @@ class MaskedArray(ndarray): else: result._mask = m result._sharedmask = False - #.... - return result + return result def view(self, dtype=None, type=None, fill_value=None): """ @@ -2977,7 +3054,7 @@ class MaskedArray(ndarray): if getattr(output, '_fill_value', None) is not None: if fill_value is None: if dtype is None: - pass # leave _fill_value as is + pass # leave _fill_value as is else: output._fill_value = None else: @@ -2985,7 +3062,6 @@ class MaskedArray(ndarray): return output view.__doc__ = ndarray.view.__doc__ - def astype(self, newtype): """ Returns a copy of the MaskedArray cast to given newtype. @@ -3025,33 +3101,29 @@ class MaskedArray(ndarray): output._fill_value = _check_fill_value(self._fill_value, newtype) return output - def __getitem__(self, indx): - """x.__getitem__(y) <==> x[y] + """ + x.__getitem__(y) <==> x[y] Return the item described by i, as a masked array. """ - # This test is useful, but we should keep things light... -# if getmask(indx) is not nomask: -# msg = "Masked arrays must be filled before they can be used as indices!" -# raise IndexError(msg) dout = self.data[indx] - # We could directly use ndarray.__getitem__ on self... + # We could directly use ndarray.__getitem__ on self. # But then we would have to modify __array_finalize__ to prevent the - # mask of being reshaped if it hasn't been set up properly yet... + # mask of being reshaped if it hasn't been set up properly yet # So it's easier to stick to the current version _mask = self._mask # Did we extract a single item? if not getattr(dout, 'ndim', False): - # A record ................ + # A record if isinstance(dout, np.void): mask = _mask[indx] # We should always re-cast to mvoid, otherwise users can # change masks on rows that already have masked values, but not # on rows that have no masked values, which is inconsistent. dout = mvoid(dout, mask=mask, hardmask=self._hardmask) - # Just a scalar............ + # Just a scalar elif _mask is not nomask and _mask[indx]: return masked elif self.dtype.type is np.object_ and self.dtype is not dout.dtype: @@ -3060,11 +3132,11 @@ class MaskedArray(ndarray): if _mask is not nomask and _mask[indx]: return MaskedArray(dout, mask=True) else: - # Force dout to MA ........ + # Force dout to MA dout = dout.view(type(self)) # Inherit attributes from self dout._update_from(self) - # Check the fill_value .... + # Check the fill_value if isinstance(indx, basestring): if self._fill_value is not None: dout._fill_value = self._fill_value[indx] @@ -3075,11 +3147,12 @@ class MaskedArray(ndarray): # set shape to match that of data; this is needed for matrices dout._mask.shape = dout.shape dout._sharedmask = True -# Note: Don't try to check for m.any(), that'll take too long... + # 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) <==> x[i]=y + """ + x.__setitem__(i, y) <==> x[i]=y Set item described by index. If value is masked, masks those locations. @@ -3087,10 +3160,6 @@ class MaskedArray(ndarray): """ if self is masked: raise MaskError('Cannot alter the masked element.') - # This test is useful, but we should keep things light... -# if getmask(indx) is not nomask: -# msg = "Masked arrays must be filled before they can be used as indices!" -# raise IndexError(msg) _data = self._data _mask = self._mask if isinstance(indx, basestring): @@ -3099,12 +3168,12 @@ class MaskedArray(ndarray): self._mask = _mask = make_mask_none(self.shape, self.dtype) _mask[indx] = getmask(value) return - #........................................ + _dtype = _data.dtype nbfields = len(_dtype.names or ()) - #........................................ + if value is masked: - # The mask wasn't set: create a full version... + # 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. @@ -3115,7 +3184,7 @@ class MaskedArray(ndarray): if not self._isfield: self._sharedmask = False return - #........................................ + # Get the _data part of the new value dval = value # Get the _mask part of the new value @@ -3141,7 +3210,7 @@ class MaskedArray(ndarray): _data[indx] = dval else: if nbfields: - err_msg = "Flexible 'hard' masks are not yet supported..." + err_msg = "Flexible 'hard' masks are not yet supported." raise NotImplementedError(err_msg) mindx = mask_or(_mask[indx], mval, copy=True) dindx = self._data[indx] @@ -3157,7 +3226,6 @@ class MaskedArray(ndarray): super(MaskedArray, self).__setattr__(attr, value) if attr == 'dtype' and self._mask is not nomask: self._mask = self._mask.view(make_mask_descr(value), ndarray) - # Try to reset the shape of the mask (if we don't have a void) # This raises a ValueError if the dtype change won't work try: @@ -3166,60 +3234,64 @@ class MaskedArray(ndarray): pass def __getslice__(self, i, j): - """x.__getslice__(i, j) <==> x[i:j] + """ + x.__getslice__(i, j) <==> x[i:j] - Return the slice described by (i, j). The use of negative - indices is not supported. + Return the slice described by (i, j). The use of negative indices + is not supported. """ return self.__getitem__(slice(i, j)) def __setslice__(self, i, j, value): - """x.__setslice__(i, j, value) <==> x[i:j]=value + """ + x.__setslice__(i, j, value) <==> x[i:j]=value - Set the slice (i,j) of a to value. If value is masked, mask - those locations. + Set the slice (i,j) of a to value. If value is masked, mask those + locations. """ self.__setitem__(slice(i, j), value) - def __setmask__(self, mask, copy=False): - """Set the mask. + """ + Set the mask. """ idtype = self.dtype current_mask = self._mask if mask is masked: mask = True - # Make sure the mask is set + if (current_mask is nomask): - # Just don't do anything is there's nothing to do... + # 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) - # No named fields......... + if idtype.names is None: + # No named fields. # 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... + # method. elif isinstance(mask, (int, float, np.bool_, np.number)): current_mask[...] = mask - # ...otherwise fall back to the slower, general purpose way. + # Otherwise fall back to the slower, general purpose way. else: current_mask.flat = mask - # Named fields w/ ............ else: + # Named fields w/ mdtype = current_mask.dtype mask = np.array(mask, copy=False) # Mask is a singleton if not mask.ndim: # It's a boolean : make a record if mask.dtype.kind == 'b': - mask = np.array(tuple([mask.item()]*len(mdtype)), + mask = np.array(tuple([mask.item()] * len(mdtype)), dtype=mdtype) # It's a record: make sure the dtype is correct else: @@ -3239,49 +3311,52 @@ class MaskedArray(ndarray): current_mask[n] |= mask[n] # Softmask: set everything to False # If it's obviously a compatible scalar, use a quick update - # method... + # method. elif isinstance(mask, (int, float, np.bool_, np.number)): current_mask[...] = mask - # ...otherwise fall back to the slower, general purpose way. + # Otherwise fall back to the slower, general purpose way. else: current_mask.flat = mask # Reshape if needed if current_mask.shape: current_mask.shape = self.shape return + _set_mask = __setmask__ - #.... + def _get_mask(self): """Return the current mask. """ - # We could try to force a reshape, but that wouldn't work in some cases. -# return self._mask.reshape(self.shape) + # We could try to force a reshape, but that wouldn't work in some + # cases. return self._mask - mask = property(fget=_get_mask, fset=__setmask__, doc="Mask") + mask = property(fget=_get_mask, fset=__setmask__, doc="Mask") def _get_recordmask(self): """ - Return the mask of the records. - A record is masked when all the fields are masked. + Return the mask of the records. + + A record is masked when all the fields are masked. """ _mask = self._mask.view(ndarray) if _mask.dtype.names is None: return _mask - return np.all(flatten_structured_array(_mask), axis= -1) - + return np.all(flatten_structured_array(_mask), axis=-1) def _set_recordmask(self): - """Return the mask of the records. - A record is masked when all the fields are masked. + """ + Return the mask of the records. + + A record is masked when all the fields are masked. """ raise NotImplementedError("Coming soon: setting the mask per records!") + recordmask = property(fget=_get_recordmask) - #............................................ def harden_mask(self): """ Force the mask to hard. @@ -3315,7 +3390,6 @@ class MaskedArray(ndarray): hardmask = property(fget=lambda self: self._hardmask, doc="Hardness of the mask") - def unshare_mask(self): """ Copy the mask and set the sharedmask flag to False. @@ -3365,9 +3439,7 @@ class MaskedArray(ndarray): self._mask = nomask return self - #............................................ - - baseclass = property(fget=lambda self:self._baseclass, + baseclass = property(fget=lambda self: self._baseclass, doc="Class of the underlying data (read-only).") def _get_data(self): @@ -3376,22 +3448,22 @@ class MaskedArray(ndarray): """ return ndarray.view(self, self._baseclass) + _data = property(fget=_get_data) data = property(fget=_get_data) def _get_flat(self): "Return a flat iterator." return MaskedIterator(self) - # - def _set_flat (self, value): + + def _set_flat(self, value): "Set a flattened version of self to value." y = self.ravel() y[:] = value - # + flat = property(fget=_get_flat, fset=_set_flat, doc="Flat version of the array.") - def get_fill_value(self): """ Return the filling value of the masked array. @@ -3462,7 +3534,6 @@ class MaskedArray(ndarray): fill_value = property(fget=get_fill_value, fset=set_fill_value, doc="Filling value.") - def filled(self, fill_value=None): """ Return a copy of self, with masked values filled with a given value. @@ -3503,15 +3574,15 @@ class MaskedArray(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 self is masked_singleton: return np.asanyarray(fill_value) - # + if m.dtype.names: result = self._data.copy('K') _recursive_filled(result, self._mask, fill_value) @@ -3526,7 +3597,7 @@ class MaskedArray(ndarray): d = result.astype(object) result = np.choose(m, (d, fill_value)) except IndexError: - #ok, if scalar + # ok, if scalar if self._data.shape: raise elif m: @@ -3562,7 +3633,6 @@ class MaskedArray(ndarray): data = data.compress(np.logical_not(ndarray.ravel(self._mask))) return data - def compress(self, condition, axis=None, out=None): """ Return `a` where condition is ``True``. @@ -3620,18 +3690,20 @@ class MaskedArray(ndarray): """ # Get the basic components (_data, _mask) = (self._data, self._mask) - # Force the condition to a regular ndarray (forget the missing values...) + + # Force the condition to a regular ndarray and forget the missing + # values. condition = np.array(condition, copy=False, subok=False) - # + _new = _data.compress(condition, axis=axis, out=out).view(type(self)) _new._update_from(self) if _mask is not nomask: _new._mask = _mask.compress(condition, axis=axis) return _new - #............................................ def __str__(self): - """String representation. + """ + String representation. """ if masked_print_option.enabled(): @@ -3668,7 +3740,8 @@ class MaskedArray(ndarray): return str(res) def __repr__(self): - """Literal string representation. + """ + Literal string representation. """ n = len(self.shape) @@ -3690,16 +3763,19 @@ class MaskedArray(ndarray): def _delegate_binop(self, other): # This emulates the logic in - # multiarray/number.c:PyArray_GenericBinaryFunction + # multiarray/number.c:PyArray_GenericBinaryFunction if (not isinstance(other, np.ndarray) - and not hasattr(other, "__numpy_ufunc__")): + and not hasattr(other, "__numpy_ufunc__")): other_priority = getattr(other, "__array_priority__", -1000000) if self.__array_priority__ < other_priority: return True return False def __eq__(self, other): - "Check whether other equals self elementwise" + """ + Check whether other equals self elementwise. + + """ if self is masked: return masked omask = getattr(other, '_mask', nomask) @@ -3727,12 +3803,15 @@ class MaskedArray(ndarray): mask = mask.view((bool_, len(self.dtype))).all(axis) except ValueError: mask = np.all([[f[n].all() for n in mask.dtype.names] - for f in mask], axis=axis) + for f in mask], axis=axis) check._mask = mask return check - # + def __ne__(self, other): - "Check whether other doesn't equal self elementwise" + """ + Check whether other doesn't equal self elementwise + + """ if self is masked: return masked omask = getattr(other, '_mask', nomask) @@ -3760,82 +3839,121 @@ class MaskedArray(ndarray): mask = mask.view((bool_, len(self.dtype))).all(axis) except ValueError: mask = np.all([[f[n].all() for n in mask.dtype.names] - for f in mask], axis=axis) + for f in mask], axis=axis) check._mask = mask return check - # + def __add__(self, other): - "Add self to other, and return a new masked array." + """ + Add self to other, and return a new masked array. + + """ if self._delegate_binop(other): return NotImplemented return add(self, other) - # + def __radd__(self, other): - "Add other to self, and return a new masked array." + """ + Add other to self, and return a new masked array. + + """ # In analogy with __rsub__ and __rdiv__, use original order: # we get here from `other + self`. return add(other, self) - # + def __sub__(self, other): - "Subtract other from self, and return a new masked array." + """ + Subtract other from self, and return a new masked array. + + """ if self._delegate_binop(other): return NotImplemented return subtract(self, other) - # + def __rsub__(self, other): - "Subtract self from other, and return a new masked array." + """ + Subtract self from other, and return a new masked array. + + """ return subtract(other, self) - # + def __mul__(self, other): "Multiply self by other, and return a new masked array." if self._delegate_binop(other): return NotImplemented return multiply(self, other) - # + def __rmul__(self, other): - "Multiply other by self, and return a new masked array." + """ + Multiply other by self, and return a new masked array. + + """ # In analogy with __rsub__ and __rdiv__, use original order: # we get here from `other * self`. return multiply(other, self) - # + def __div__(self, other): - "Divide other into self, and return a new masked array." + """ + Divide other into self, and return a new masked array. + + """ if self._delegate_binop(other): return NotImplemented return divide(self, other) - # + def __truediv__(self, other): - "Divide other into self, and return a new masked array." + """ + Divide other into self, and return a new masked array. + + """ if self._delegate_binop(other): return NotImplemented return true_divide(self, other) - # + def __rtruediv__(self, other): - "Divide self into other, and return a new masked array." + """ + Divide self into other, and return a new masked array. + + """ return true_divide(other, self) - # + def __floordiv__(self, other): - "Divide other into self, and return a new masked array." + """ + Divide other into self, and return a new masked array. + + """ if self._delegate_binop(other): return NotImplemented return floor_divide(self, other) - # + def __rfloordiv__(self, other): - "Divide self into other, and return a new masked array." + """ + Divide self into other, and return a new masked array. + + """ return floor_divide(other, self) - # + def __pow__(self, other): - "Raise self to the power other, masking the potential NaNs/Infs" + """ + Raise self to the power other, masking the potential NaNs/Infs + + """ if self._delegate_binop(other): return NotImplemented return power(self, other) - # + def __rpow__(self, other): - "Raise other to the power self, masking the potential NaNs/Infs" + """ + Raise other to the power self, masking the potential NaNs/Infs + + """ return power(other, self) - #............................................ + def __iadd__(self, other): - "Add other to self in-place." + """ + Add other to self in-place. + + """ m = getmask(other) if self._mask is nomask: if m is not nomask and m.any(): @@ -3847,9 +3965,12 @@ class MaskedArray(ndarray): self._data.__iadd__(np.where(self._mask, self.dtype.type(0), getdata(other))) return self - #.... + def __isub__(self, other): - "Subtract other from self in-place." + """ + Subtract other from self in-place. + + """ m = getmask(other) if self._mask is nomask: if m is not nomask and m.any(): @@ -3860,9 +3981,12 @@ class MaskedArray(ndarray): self._data.__isub__(np.where(self._mask, self.dtype.type(0), getdata(other))) return self - #.... + def __imul__(self, other): - "Multiply self by other in-place." + """ + Multiply self by other in-place. + + """ m = getmask(other) if self._mask is nomask: if m is not nomask and m.any(): @@ -3873,9 +3997,12 @@ class MaskedArray(ndarray): self._data.__imul__(np.where(self._mask, self.dtype.type(1), getdata(other))) return self - #.... + def __idiv__(self, other): - "Divide self by other in-place." + """ + Divide self by other in-place. + + """ other_data = getdata(other) dom_mask = _DomainSafeDivide().__call__(self._data, other_data) other_mask = getmask(other) @@ -3884,14 +4011,16 @@ class MaskedArray(ndarray): if dom_mask.any(): (_, fval) = ufunc_fills[np.divide] other_data = np.where(dom_mask, fval, other_data) -# self._mask = mask_or(self._mask, new_mask) self._mask |= new_mask self._data.__idiv__(np.where(self._mask, self.dtype.type(1), other_data)) return self - #.... + def __ifloordiv__(self, other): - "Floor divide self by other in-place." + """ + Floor divide self by other in-place. + + """ other_data = getdata(other) dom_mask = _DomainSafeDivide().__call__(self._data, other_data) other_mask = getmask(other) @@ -3900,14 +4029,16 @@ class MaskedArray(ndarray): if dom_mask.any(): (_, fval) = ufunc_fills[np.floor_divide] other_data = np.where(dom_mask, fval, other_data) -# self._mask = mask_or(self._mask, new_mask) self._mask |= new_mask self._data.__ifloordiv__(np.where(self._mask, self.dtype.type(1), other_data)) return self - #.... + def __itruediv__(self, other): - "True divide self by other in-place." + """ + True divide self by other in-place. + + """ other_data = getdata(other) dom_mask = _DomainSafeDivide().__call__(self._data, other_data) other_mask = getmask(other) @@ -3916,14 +4047,16 @@ class MaskedArray(ndarray): if dom_mask.any(): (_, fval) = ufunc_fills[np.true_divide] other_data = np.where(dom_mask, fval, other_data) -# self._mask = mask_or(self._mask, new_mask) self._mask |= new_mask self._data.__itruediv__(np.where(self._mask, self.dtype.type(1), other_data)) return self - #... + def __ipow__(self, other): - "Raise self to the power other, in place." + """ + Raise self to the power other, in place. + + """ other_data = getdata(other) other_mask = getmask(other) with np.errstate(divide='ignore', invalid='ignore'): @@ -3939,9 +4072,12 @@ class MaskedArray(ndarray): new_mask = mask_or(other_mask, invalid) self._mask = mask_or(self._mask, new_mask) return self - #............................................ + def __float__(self): - "Convert to float." + """ + Convert to float. + + """ if self.size > 1: raise TypeError("Only length-1 arrays can be converted " "to Python scalars") @@ -3951,7 +4087,10 @@ class MaskedArray(ndarray): return float(self.item()) def __int__(self): - "Convert to int." + """ + Convert to int. + + """ if self.size > 1: raise TypeError("Only length-1 arrays can be converted " "to Python scalars") @@ -3959,7 +4098,6 @@ class MaskedArray(ndarray): raise MaskError('Cannot convert masked element to a Python int.') return int(self.item()) - def get_imag(self): """ Return the imaginary part of the masked array. @@ -3992,6 +4130,7 @@ class MaskedArray(ndarray): result = self._data.imag.view(type(self)) result.__setmask__(self._mask) return result + imag = property(fget=get_imag, doc="Imaginary part.") def get_real(self): @@ -4028,8 +4167,6 @@ class MaskedArray(ndarray): return result real = property(fget=get_real, doc="Real part") - - #............................................ def count(self, axis=None): """ Count the non-masked elements of the array along the given axis. @@ -4092,9 +4229,9 @@ class MaskedArray(ndarray): return (n1 - n2) else: return narray(n1 - n2) - #............................................ + flatten = _arraymethod('flatten') - # + def ravel(self, order='C'): """ Returns a 1D version of self, as a view. @@ -4139,10 +4276,11 @@ class MaskedArray(ndarray): else: r._mask = nomask return r - # + repeat = _arraymethod('repeat') - # - def reshape (self, *s, **kwargs): + + + def reshape(self, *s, **kwargs): """ Give a new shape to the array without changing its data. @@ -4197,7 +4335,7 @@ class MaskedArray(ndarray): if mask is not nomask: result._mask = mask.reshape(*s, **kwargs) return result - # + def resize(self, newshape, refcheck=True, order=False): """ .. warning:: @@ -4211,20 +4349,11 @@ class MaskedArray(ndarray): """ # Note : the 'order' keyword looks broken, let's just drop it -# try: -# ndarray.resize(self, newshape, refcheck=refcheck) -# if self.mask is not nomask: -# self._mask.resize(newshape, refcheck=refcheck) -# except ValueError: -# raise ValueError("Cannot resize an array that has been referenced " -# "or is referencing another array in this way.\n" -# "Use the numpy.ma.resize function.") -# return None errmsg = "A masked array does not own its data "\ "and therefore cannot be resized.\n" \ "Use the numpy.ma.resize function instead." raise ValueError(errmsg) - # + def put(self, indices, values, mode='raise'): """ Set storage-indexed locations to corresponding values. @@ -4279,9 +4408,9 @@ class MaskedArray(ndarray): values.resize(indices.shape) indices = indices[~mask] values = values[~mask] - #.... + self._data.put(indices, values, mode=mode) - #.... + if m is nomask: m = getmask(values) else: @@ -4292,8 +4421,8 @@ class MaskedArray(ndarray): m.put(indices, values._mask, mode=mode) m = make_mask(m, copy=False, shrink=True) self._mask = m - #............................................ - def ids (self): + + def ids(self): """ Return the addresses of the data and mask areas. @@ -4346,37 +4475,36 @@ class MaskedArray(ndarray): """ return self.flags['CONTIGUOUS'] - #............................................ def all(self, axis=None, out=None): """ - Check if all of the elements of `a` are true. + Check if all of the elements of `a` are true. - Performs a :func:`logical_and` over the given axis and returns the result. - Masked values are considered as True during computation. - For convenience, the output array is masked where ALL the values along the - current axis are masked: if the output would have been a scalar and that - all the values are masked, then the output is `masked`. + Performs a :func:`logical_and` over the given axis and returns the result. + Masked values are considered as True during computation. + For convenience, the output array is masked where ALL the values along the + current axis are masked: if the output would have been a scalar and that + all the values are masked, then the output is `masked`. - Parameters - ---------- - axis : {None, integer} - Axis to perform the operation over. - If None, perform over flattened array. - out : {None, array}, optional - Array into which the result can be placed. Its type is preserved - and it must be of the right shape to hold the output. + Parameters + ---------- + axis : {None, integer} + Axis to perform the operation over. + If None, perform over flattened array. + out : {None, array}, optional + Array into which the result can be placed. Its type is preserved + and it must be of the right shape to hold the output. - See Also - -------- - all : equivalent function + See Also + -------- + all : equivalent function - Examples - -------- - >>> np.ma.array([1,2,3]).all() - True - >>> a = np.ma.array([1,2,3], mask=True) - >>> (a.all() is np.ma.masked) - True + Examples + -------- + >>> np.ma.array([1,2,3]).all() + True + >>> a = np.ma.array([1,2,3], mask=True) + >>> (a.all() is np.ma.masked) + True """ mask = _check_mask_axis(self._mask, axis) @@ -4393,7 +4521,6 @@ class MaskedArray(ndarray): out.__setmask__(mask) return out - def any(self, axis=None, out=None): """ Check if any of the elements of `a` are true. @@ -4429,7 +4556,6 @@ class MaskedArray(ndarray): out.__setmask__(mask) return out - def nonzero(self): """ Return the indices of unmasked elements that are not zero. @@ -4531,7 +4657,6 @@ class MaskedArray(ndarray): """ return narray(self.filled(0), copy=False).nonzero() - def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): """ (this docstring should be overwritten) @@ -4560,13 +4685,12 @@ class MaskedArray(ndarray): return r d = self.filled(0).dot(other.filled(0), out._data) if out.mask.shape != d.shape: - out._mask = numpy.empty(d.shape, MaskType) + out._mask = np.empty(d.shape, MaskType) np.dot(am, bm, out._mask) np.logical_not(out._mask, out._mask) return out dot.__doc__ = ndarray.dot.__doc__ - def sum(self, axis=None, dtype=None, out=None): """ Return the sum of the array elements over the given axis. @@ -4634,7 +4758,6 @@ class MaskedArray(ndarray): outmask.flat = newmask return out - def cumsum(self, axis=None, dtype=None, out=None): """ Return the cumulative sum of the elements along the given axis. @@ -4691,7 +4814,6 @@ class MaskedArray(ndarray): result.__setmask__(self._mask) return result - def prod(self, axis=None, dtype=None, out=None): """ Return the product of the array elements over the given axis. @@ -4813,7 +4935,6 @@ class MaskedArray(ndarray): result.__setmask__(self._mask) return result - def mean(self, axis=None, dtype=None, out=None): """ Returns the average of the array elements. @@ -4939,7 +5060,7 @@ class MaskedArray(ndarray): dvar._mask = mask_or(self._mask.all(axis), (cnt <= 0)) dvar._update_from(self) elif getattr(dvar, '_mask', False): - # Make sure that masked is returned when the scalar is masked. + # Make sure that masked is returned when the scalar is masked. dvar = masked if out is not None: if isinstance(out, MaskedArray): @@ -4963,7 +5084,6 @@ class MaskedArray(ndarray): return dvar var.__doc__ = np.var.__doc__ - def std(self, axis=None, dtype=None, out=None, ddof=0): "" dvar = self.var(axis=axis, dtype=dtype, out=out, ddof=ddof) @@ -4975,7 +5095,6 @@ class MaskedArray(ndarray): return dvar std.__doc__ = np.std.__doc__ - #............................................ def round(self, decimals=0, out=None): """ Return an array rounded a to the given number of decimals. @@ -4998,7 +5117,6 @@ class MaskedArray(ndarray): return out round.__doc__ = ndarray.round.__doc__ - #............................................ def argsort(self, axis=None, kind='quicksort', order=None, fill_value=None): """ Return an ndarray of indices that sort the array along the @@ -5052,7 +5170,6 @@ class MaskedArray(ndarray): d = self.filled(fill_value).view(ndarray) return d.argsort(axis=axis, kind=kind, order=order) - def argmin(self, axis=None, fill_value=None, out=None): """ Return array of indices to the minimum values along the given axis. @@ -5094,7 +5211,6 @@ class MaskedArray(ndarray): d = self.filled(fill_value).view(ndarray) return d.argmin(axis, out=out) - def argmax(self, axis=None, fill_value=None, out=None): """ Returns array of indices of the maximum values along the given axis. @@ -5132,71 +5248,70 @@ class MaskedArray(ndarray): d = self.filled(fill_value).view(ndarray) return d.argmax(axis, out=out) - - def sort(self, axis= -1, kind='quicksort', order=None, + def sort(self, axis=-1, kind='quicksort', order=None, endwith=True, fill_value=None): """ - Sort the array, in-place + Sort the array, in-place - Parameters - ---------- - a : array_like - Array to be sorted. - axis : int, optional - Axis along which to sort. If None, the array is flattened before - sorting. The default is -1, which sorts along the last axis. - kind : {'quicksort', 'mergesort', 'heapsort'}, optional - Sorting algorithm. Default is 'quicksort'. - order : list, optional - When `a` is a structured array, this argument specifies which fields - to compare first, second, and so on. This list does not need to - include all of the fields. - endwith : {True, False}, optional - Whether missing values (if any) should be forced in the upper indices - (at the end of the array) (True) or lower indices (at the beginning). - When the array contains unmasked values of the largest (or smallest if - False) representable value of the datatype the ordering of these values - and the masked values is undefined. To enforce the masked values are - at the end (beginning) in this case one must sort the mask. - fill_value : {var}, optional - Value used internally for the masked values. - If ``fill_value`` is not None, it supersedes ``endwith``. - - Returns - ------- - sorted_array : ndarray - Array of the same type and shape as `a`. - - See Also - -------- - ndarray.sort : Method to sort an array in-place. - argsort : Indirect sort. - lexsort : Indirect stable sort on multiple keys. - searchsorted : Find elements in a sorted array. + Parameters + ---------- + a : array_like + Array to be sorted. + axis : int, optional + Axis along which to sort. If None, the array is flattened before + sorting. The default is -1, which sorts along the last axis. + kind : {'quicksort', 'mergesort', 'heapsort'}, optional + Sorting algorithm. Default is 'quicksort'. + order : list, optional + When `a` is a structured array, this argument specifies which fields + to compare first, second, and so on. This list does not need to + include all of the fields. + endwith : {True, False}, optional + Whether missing values (if any) should be forced in the upper indices + (at the end of the array) (True) or lower indices (at the beginning). + When the array contains unmasked values of the largest (or smallest if + False) representable value of the datatype the ordering of these values + and the masked values is undefined. To enforce the masked values are + at the end (beginning) in this case one must sort the mask. + fill_value : {var}, optional + Value used internally for the masked values. + If ``fill_value`` is not None, it supersedes ``endwith``. - Notes - ----- - See ``sort`` for notes on the different sorting algorithms. + Returns + ------- + sorted_array : ndarray + Array of the same type and shape as `a`. - Examples - -------- - >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) - >>> # Default - >>> a.sort() - >>> print a - [1 3 5 -- --] + See Also + -------- + ndarray.sort : Method to sort an array in-place. + argsort : Indirect sort. + lexsort : Indirect stable sort on multiple keys. + searchsorted : Find elements in a sorted array. - >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) - >>> # Put missing values in the front - >>> a.sort(endwith=False) - >>> print a - [-- -- 1 3 5] + Notes + ----- + See ``sort`` for notes on the different sorting algorithms. - >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) - >>> # fill_value takes over endwith - >>> a.sort(endwith=False, fill_value=3) - >>> print a - [1 -- -- 3 5] + Examples + -------- + >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) + >>> # Default + >>> a.sort() + >>> print a + [1 3 5 -- --] + + >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) + >>> # Put missing values in the front + >>> a.sort(endwith=False) + >>> print a + [-- -- 1 3 5] + + >>> a = ma.array([1, 2, 5, 4, 3],mask=[0, 1, 0, 1, 0]) + >>> # fill_value takes over endwith + >>> a.sort(endwith=False, fill_value=3) + >>> print a + [1 -- -- 3 5] """ if self._mask is nomask: @@ -5231,33 +5346,32 @@ class MaskedArray(ndarray): self._mask.flat = tmp_mask return - #............................................ def min(self, axis=None, out=None, fill_value=None): """ - Return the minimum along a given axis. + Return the minimum along a given axis. - Parameters - ---------- - axis : {None, int}, optional - Axis along which to operate. By default, ``axis`` is None and the - flattened input is used. - out : array_like, optional - Alternative output array in which to place the result. Must be of - the same shape and buffer length as the expected output. - fill_value : {var}, optional - Value used to fill in the masked values. - If None, use the output of `minimum_fill_value`. + Parameters + ---------- + axis : {None, int}, optional + Axis along which to operate. By default, ``axis`` is None and the + flattened input is used. + out : array_like, optional + Alternative output array in which to place the result. Must be of + the same shape and buffer length as the expected output. + fill_value : {var}, optional + Value used to fill in the masked values. + If None, use the output of `minimum_fill_value`. - Returns - ------- - amin : array_like - New array holding the result. - If ``out`` was specified, ``out`` is returned. + Returns + ------- + amin : array_like + New array holding the result. + If ``out`` was specified, ``out`` is returned. - See Also - -------- - minimum_fill_value - Returns the minimum filling value for a given datatype. + See Also + -------- + minimum_fill_value + Returns the minimum filling value for a given datatype. """ _mask = self._mask @@ -5266,7 +5380,8 @@ class MaskedArray(ndarray): fill_value = minimum_fill_value(self) # No explicit output if out is None: - result = self.filled(fill_value).min(axis=axis, out=out).view(type(self)) + result = self.filled(fill_value).min( + axis=axis, out=out).view(type(self)) if result.ndim: # Set the mask result.__setmask__(newmask) @@ -5330,7 +5445,6 @@ class MaskedArray(ndarray): else: return minimum.reduce(self, axis) - #........................ def max(self, axis=None, out=None, fill_value=None): """ Return the maximum along a given axis. @@ -5365,7 +5479,8 @@ class MaskedArray(ndarray): fill_value = maximum_fill_value(self) # No explicit output if out is None: - result = self.filled(fill_value).max(axis=axis, out=out).view(type(self)) + result = self.filled(fill_value).max( + axis=axis, out=out).view(type(self)) if result.ndim: # Set the mask result.__setmask__(newmask) @@ -5448,17 +5563,16 @@ class MaskedArray(ndarray): out.__setmask__(outmask) return out - - # Array methods --------------------------------------- + # Array methods copy = _arraymethod('copy') diagonal = _arraymethod('diagonal') transpose = _arraymethod('transpose') - T = property(fget=lambda self:self.transpose()) + T = property(fget=lambda self: self.transpose()) swapaxes = _arraymethod('swapaxes') clip = _arraymethod('clip', onmask=False) copy = _arraymethod('copy') squeeze = _arraymethod('squeeze') - #-------------------------------------------- + def tolist(self, fill_value=None): """ Return the data portion of the masked array as a hierarchical Python list. @@ -5493,48 +5607,23 @@ class MaskedArray(ndarray): # Explicit fill_value: fill the array and get the list if fill_value is not None: return self.filled(fill_value).tolist() - # Structured array ............. + # Structured array. names = self.dtype.names if names: result = self._data.astype([(_, object) for _ in names]) for n in names: result[n][_mask[n]] = None return result.tolist() - # Standard arrays ............... + # Standard arrays. if _mask is nomask: return [None] - # Set temps to save time when dealing w/ marrays... + # Set temps to save time when dealing w/ marrays. inishape = self.shape result = np.array(self._data.ravel(), dtype=object) result[_mask.ravel()] = None result.shape = inishape return result.tolist() -# if fill_value is not None: -# return self.filled(fill_value).tolist() -# result = self.filled().tolist() -# # Set temps to save time when dealing w/ mrecarrays... -# _mask = self._mask -# if _mask is nomask: -# return result -# nbdims = self.ndim -# dtypesize = len(self.dtype) -# if nbdims == 0: -# return tuple([None] * dtypesize) -# elif nbdims == 1: -# maskedidx = _mask.nonzero()[0].tolist() -# if dtypesize: -# nodata = tuple([None] * dtypesize) -# else: -# nodata = None -# [operator.setitem(result, i, nodata) for i in maskedidx] -# else: -# for idx in zip(*[i.tolist() for i in _mask.nonzero()]): -# tmp = result -# for i in idx[:-1]: -# tmp = tmp[i] -# tmp[idx[-1]] = None -# return result - #........................ + def tostring(self, fill_value=None, order='C'): """ This function is a compatibility alias for tobytes. Despite its name it @@ -5542,7 +5631,7 @@ class MaskedArray(ndarray): """ return self.tobytes(fill_value, order='C') - #........................ + def tobytes(self, fill_value=None, order='C'): """ Return the array data as a string containing the raw bytes in the array. @@ -5582,7 +5671,7 @@ class MaskedArray(ndarray): """ return self.filled(fill_value).tobytes(order=order) - #........................ + def tofile(self, fid, sep="", format="%s"): """ Save a masked array to a file in binary format. @@ -5636,7 +5725,7 @@ class MaskedArray(ndarray): [(7, False) (8, True) (9, False)]] """ - # Get the basic dtype .... + # Get the basic dtype. ddtype = self.dtype # Make sure we have a mask _mask = self._mask @@ -5644,14 +5733,14 @@ class MaskedArray(ndarray): _mask = make_mask_none(self.shape, ddtype) # And get its dtype mdtype = self._mask.dtype - # + record = np.ndarray(shape=self.shape, dtype=[('_data', ddtype), ('_mask', mdtype)]) record['_data'] = self._data record['_mask'] = self._mask return record torecords = toflex - #-------------------------------------------- + # Pickling def __getstate__(self): """Return the internal state of the masked array, for pickling @@ -5664,13 +5753,13 @@ class MaskedArray(ndarray): self.dtype, self.flags.fnc, self._data.tobytes(cf), - #self._data.tolist(), + # self._data.tolist(), getmaskarray(self).tobytes(cf), - #getmaskarray(self).tolist(), + # getmaskarray(self).tolist(), self._fill_value, ) return state - # + def __setstate__(self, state): """Restore the internal state of the masked array, for pickling purposes. ``state`` is typically the output of the @@ -5687,7 +5776,7 @@ class MaskedArray(ndarray): super(MaskedArray, self).__setstate__((shp, typ, isf, raw)) self._mask.__setstate__((shp, make_mask_descr(typ), isf, msk)) self.fill_value = flv - # + def __reduce__(self): """Return a 3-tuple for pickling a MaskedArray. @@ -5695,7 +5784,7 @@ class MaskedArray(ndarray): return (_mareconstruct, (self.__class__, self._baseclass, (0,), 'b',), self.__getstate__()) - # + def __deepcopy__(self, memo=None): from copy import deepcopy copied = MaskedArray.__new__(type(self), self, copy=True) @@ -5717,15 +5806,11 @@ def _mareconstruct(subtype, baseclass, baseshape, basetype,): return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) - - - - class mvoid(MaskedArray): """ Fake a 'void' object to use for masked array with structured dtypes. """ - # + def __new__(self, data, mask=nomask, dtype=None, fill_value=None, hardmask=False, copy=False, subok=True): _data = np.array(data, copy=copy, subok=subok, dtype=dtype) @@ -5749,10 +5834,14 @@ class mvoid(MaskedArray): def _get_data(self): # Make sure that the _data part is a np.void return self.view(ndarray)[()] + _data = property(fget=_get_data) def __getitem__(self, indx): - "Get the index..." + """ + Get the index. + + """ m = self._mask if m is not nomask and m[indx]: return masked @@ -5857,10 +5946,11 @@ class mvoid(MaskedArray): return tuple(result) +############################################################################## +# Shortcuts # +############################################################################## + -#####-------------------------------------------------------------------------- -#---- --- Shortcuts --- -#####--------------------------------------------------------------------------- def isMaskedArray(x): """ Test whether input is an instance of MaskedArray. @@ -5911,33 +6001,34 @@ def isMaskedArray(x): """ return isinstance(x, MaskedArray) + + isarray = isMaskedArray -isMA = isMaskedArray #backward compatibility +isMA = isMaskedArray # backward compatibility -# We define the masked singleton as a float for higher precedence... -# Note that it can be tricky sometimes w/ type comparison class MaskedConstant(MaskedArray): - # + # We define the masked singleton as a float for higher precedence. + # Note that it can be tricky sometimes w/ type comparison _data = data = np.array(0.) _mask = mask = np.array(True) _baseclass = ndarray - # + def __new__(self): return self._data.view(self) - # + def __array_finalize__(self, obj): return - # + def __array_wrap__(self, obj): return self - # + def __str__(self): return str(masked_print_option._display) - # + def __repr__(self): return 'masked' - # + def flatten(self): return masked_array([self._data], dtype=float, mask=[True]) @@ -5948,29 +6039,27 @@ class MaskedConstant(MaskedArray): masked = masked_singleton = MaskedConstant() - - - masked_array = MaskedArray + def array(data, dtype=None, copy=False, order=False, mask=nomask, fill_value=None, keep_mask=True, hard_mask=False, shrink=True, subok=True, ndmin=0, ): - """array(data, dtype=None, copy=False, order=False, mask=nomask, - fill_value=None, keep_mask=True, hard_mask=False, shrink=True, - subok=True, ndmin=0) + """ + Shortcut to MaskedArray. - Acts as shortcut to MaskedArray, with options in a different order - for convenience. And backwards compatibility... + The options are in a different order for convenience and backwards + compatibility. """ - #!!!: we should try to put 'order' somwehere + # we should try to put 'order' somewhere 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) array.__doc__ = masked_array.__doc__ + def is_masked(x): """ Determine whether input has masked values. @@ -6024,9 +6113,11 @@ def is_masked(x): return False -#####--------------------------------------------------------------------------- -#---- --- Extrema functions --- -#####--------------------------------------------------------------------------- +############################################################################## +# Extrema functions # +############################################################################## + + class _extrema_operation(object): """ Generic class for maximum/minimum functions. @@ -6036,18 +6127,19 @@ class _extrema_operation(object): `_minimum_operation`. """ + def __call__(self, a, b=None): "Executes the call behavior." if b is None: return self.reduce(a) return where(self.compare(a, b), a, b) - #......... + def reduce(self, target, axis=None): "Reduce target along the given axis." target = narray(target, copy=False, subok=True) m = getmask(target) if axis is not None: - kargs = { 'axis' : axis } + kargs = {'axis': axis} else: kargs = {} target = target.ravel() @@ -6056,7 +6148,8 @@ class _extrema_operation(object): if m is nomask: t = self.ufunc.reduce(target, **kargs) else: - target = target.filled(self.fill_value_func(target)).view(type(target)) + target = target.filled( + self.fill_value_func(target)).view(type(target)) t = self.ufunc.reduce(target, **kargs) m = umath.logical_and.reduce(m, **kargs) if hasattr(t, '_mask'): @@ -6064,8 +6157,8 @@ class _extrema_operation(object): elif m: t = masked return t - #......... - def outer (self, a, b): + + def outer(self, a, b): "Return the function applied to the outer product of a and b." ma = getmask(a) mb = getmask(b) @@ -6081,10 +6174,12 @@ class _extrema_operation(object): result._mask = m return result -#............................ + class _minimum_operation(_extrema_operation): + "Object to calculate minima" - def __init__ (self): + + def __init__(self): """minimum(a, b) or minimum(a) In one argument case, returns the scalar minimum. """ @@ -6093,10 +6188,12 @@ In one argument case, returns the scalar minimum. self.compare = less self.fill_value_func = minimum_fill_value -#............................ + class _maximum_operation(_extrema_operation): + "Object to calculate maxima" - def __init__ (self): + + def __init__(self): """maximum(a, b) or maximum(a) In one argument case returns the scalar maximum. """ @@ -6105,39 +6202,46 @@ class _maximum_operation(_extrema_operation): self.compare = greater self.fill_value_func = maximum_fill_value -#.......................................................... + def min(obj, axis=None, out=None, fill_value=None): try: return obj.min(axis=axis, fill_value=fill_value, out=out) except (AttributeError, TypeError): - # If obj doesn't have a min method, - # ...or if the method doesn't accept a fill_value argument + # If obj doesn't have a min method or if the method doesn't accept + # a fill_value argument return asanyarray(obj).min(axis=axis, fill_value=fill_value, out=out) min.__doc__ = MaskedArray.min.__doc__ + def max(obj, axis=None, out=None, fill_value=None): try: return obj.max(axis=axis, fill_value=fill_value, out=out) except (AttributeError, TypeError): - # If obj doesn't have a max method, - # ...or if the method doesn't accept a fill_value argument + # If obj doesn't have a max method, or if the method doesn't accept + # a fill_value argument return asanyarray(obj).max(axis=axis, fill_value=fill_value, out=out) max.__doc__ = MaskedArray.max.__doc__ + def ptp(obj, axis=None, out=None, fill_value=None): - """a.ptp(axis=None) = a.max(axis)-a.min(axis)""" + """ + a.ptp(axis=None) = a.max(axis) - a.min(axis) + + """ try: return obj.ptp(axis, out=out, fill_value=fill_value) except (AttributeError, TypeError): - # If obj doesn't have a ptp method, - # ...or if the method doesn't accept a fill_value argument + # If obj doesn't have a ptp method or if the method doesn't accept + # a fill_value argument return asanyarray(obj).ptp(axis=axis, fill_value=fill_value, out=out) ptp.__doc__ = MaskedArray.ptp.__doc__ -#####--------------------------------------------------------------------------- -#---- --- Definition of functions from the corresponding methods --- -#####--------------------------------------------------------------------------- +############################################################################## +# Definition of functions from the corresponding methods # +############################################################################## + + class _frommethod: """ Define functions from existing MaskedArray methods. @@ -6148,20 +6252,22 @@ class _frommethod: Name of the method to transform. """ + def __init__(self, methodname, reversed=False): self.__name__ = methodname self.__doc__ = self.getdoc() self.reversed = reversed - # + def getdoc(self): "Return the doc of the function (from the doc of the method)." meth = getattr(MaskedArray, self.__name__, None) or\ - getattr(np, self.__name__, None) + getattr(np, self.__name__, None) signature = self.__name__ + get_object_signature(meth) if meth is not None: - doc = """ %s\n%s""" % (signature, getattr(meth, '__doc__', None)) + doc = """ %s\n%s""" % ( + signature, getattr(meth, '__doc__', None)) return doc - # + def __call__(self, a, *args, **params): if self.reversed: args = list(args) @@ -6181,6 +6287,7 @@ class _frommethod: method = getattr(np, method_name) return method(a, *args, **params) + all = _frommethod('all') anomalies = anom = _frommethod('anom') any = _frommethod('any') @@ -6208,6 +6315,7 @@ swapaxes = _frommethod('swapaxes') trace = _frommethod('trace') var = _frommethod('var') + def take(a, indices, axis=None, out=None, mode='raise'): """ """ @@ -6215,7 +6323,6 @@ def take(a, indices, axis=None, out=None, mode='raise'): return a.take(indices, axis=axis, out=out, mode=mode) -#.............................................................................. def power(a, b, third=None): """ Returns element-wise base array raised to power from second array. @@ -6267,20 +6374,7 @@ def power(a, b, third=None): result._data[invalid] = result.fill_value return result -# if fb.dtype.char in typecodes["Integer"]: -# return masked_array(umath.power(fa, fb), m) -# m = mask_or(m, (fa < 0) & (fb != fb.astype(int))) -# if m is nomask: -# return masked_array(umath.power(fa, fb)) -# else: -# fa = fa.copy() -# if m.all(): -# fa.flat = 1 -# else: -# np.copyto(fa, 1, where=m) -# return masked_array(umath.power(fa, fb), m) - -#.............................................................................. + def argsort(a, axis=None, kind='quicksort', order=None, fill_value=None): "Function version of the eponymous method." if fill_value is None: @@ -6291,6 +6385,7 @@ def argsort(a, axis=None, kind='quicksort', order=None, fill_value=None): return d.argsort(axis, kind=kind, order=order) argsort.__doc__ = MaskedArray.argsort.__doc__ + def argmin(a, axis=None, fill_value=None): "Function version of the eponymous method." if fill_value is None: @@ -6299,6 +6394,7 @@ def argmin(a, axis=None, fill_value=None): return d.argmin(axis=axis) argmin.__doc__ = MaskedArray.argmin.__doc__ + def argmax(a, axis=None, fill_value=None): "Function version of the eponymous method." if fill_value is None: @@ -6311,7 +6407,8 @@ def argmax(a, axis=None, fill_value=None): return d.argmax(axis=axis) argmax.__doc__ = MaskedArray.argmax.__doc__ -def sort(a, axis= -1, kind='quicksort', order=None, endwith=True, fill_value=None): + +def sort(a, axis=-1, kind='quicksort', order=None, endwith=True, fill_value=None): "Function version of the eponymous method." a = narray(a, copy=True, subok=True) if axis is None: @@ -6404,7 +6501,7 @@ def concatenate(arrays, axis=0): d = np.concatenate([getdata(a) for a in arrays], axis) rcls = get_masked_subclass(*arrays) data = d.view(rcls) - # Check whether one of the arrays has a non-empty mask... + # Check whether one of the arrays has a non-empty mask. for x in arrays: if getmask(x) is not nomask: break @@ -6412,16 +6509,15 @@ def concatenate(arrays, axis=0): return data # OK, so we have to concatenate the masks dm = np.concatenate([getmaskarray(a) for a in arrays], axis) - # If we decide to keep a '_shrinkmask' option, we want to check that ... - # ... all of them are True, and then check for dm.any() -# shrink = numpy.logical_or.reduce([getattr(a,'_shrinkmask',True) for a in arrays]) -# if shrink and not dm.any(): + # If we decide to keep a '_shrinkmask' option, we want to check that + # all of them are True, and then check for dm.any() if not dm.dtype.fields and not dm.any(): data._mask = nomask else: data._mask = dm.reshape(d.shape) return data + def count(a, axis=None): if isinstance(a, MaskedArray): return a.count(axis) @@ -6496,8 +6592,8 @@ def expand_dims(x, axis): result._mask.shape = new_shape return result -#...................................... -def left_shift (a, n): + +def left_shift(a, n): """ Shift the bits of an integer to the left. @@ -6517,7 +6613,8 @@ def left_shift (a, n): d = umath.left_shift(filled(a, 0), n) return masked_array(d, mask=m) -def right_shift (a, n): + +def right_shift(a, n): """ Shift the bits of an integer to the right. @@ -6537,7 +6634,7 @@ def right_shift (a, n): d = umath.right_shift(filled(a, 0), n) return masked_array(d, mask=m) -#...................................... + def put(a, indices, values, mode='raise'): """ Set storage-indexed locations to corresponding values. @@ -6556,7 +6653,8 @@ def put(a, indices, values, mode='raise'): except AttributeError: return narray(a, copy=False).put(indices, values, mode=mode) -def putmask(a, mask, values): #, mode='raise'): + +def putmask(a, mask, values): # , mode='raise'): """ Changes elements of an array based on conditional and input values. @@ -6594,6 +6692,7 @@ def putmask(a, mask, values): #, mode='raise'): np.copyto(a._data, valdata, where=mask) return + def transpose(a, axes=None): """ Permute the dimensions of an array. @@ -6627,12 +6726,13 @@ def transpose(a, axes=None): fill_value = 999999) """ - #We can't use 'frommethod', as 'transpose' doesn't take keywords + # We can't use 'frommethod', as 'transpose' doesn't take keywords try: return a.transpose(axes) except AttributeError: return narray(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. @@ -6644,13 +6744,14 @@ def reshape(a, new_shape, order='C'): MaskedArray.reshape : equivalent function """ - #We can't use 'frommethod', it whine about some parameters. Dmmit. + # We can't use 'frommethod', it whine about some parameters. Dmmit. try: return a.reshape(new_shape, order=order) except AttributeError: _tmp = narray(a, copy=False).reshape(new_shape, order=order) return _tmp.view(MaskedArray) + def resize(x, new_shape): """ Return a new masked array with the specified size and shape. @@ -6715,26 +6816,50 @@ def resize(x, new_shape): return result -#................................................ -def rank(obj): - "maskedarray version of the numpy function." - return np.rank(getdata(obj)) +def rank(obj): + """ + maskedarray version of the numpy function. + + .. note:: + Deprecated since 1.10.0 + + """ + # 2015-04-12, 1.10.0 + warnings.warn( + "`rank` is deprecated; use the `ndim` function instead. ", + np.VisibleDeprecationWarning) + return np.ndim(getdata(obj)) + rank.__doc__ = np.rank.__doc__ -# + + +def ndim(obj): + """ + maskedarray version of the numpy function. + + """ + return np.ndim(getdata(obj)) + +ndim.__doc__ = np.ndim.__doc__ + + def shape(obj): "maskedarray version of the numpy function." return np.shape(getdata(obj)) shape.__doc__ = np.shape.__doc__ -# + + def size(obj, axis=None): "maskedarray version of the numpy function." return np.size(getdata(obj), axis) size.__doc__ = np.size.__doc__ -#................................................ -#####-------------------------------------------------------------------------- -#---- --- Extra functions --- -#####-------------------------------------------------------------------------- + +############################################################################## +# Extra functions # +############################################################################## + + def where(condition, x=_NoValue, y=_NoValue): """ Return a masked array with elements from x or y, depending on condition. @@ -6822,7 +6947,7 @@ def where(condition, x=_NoValue, y=_NoValue): return d -def choose (indices, choices, out=None, mode='raise'): +def choose(indices, choices, out=None, mode='raise'): """ Use an index array to construct a new array from a set of choices. @@ -6867,26 +6992,27 @@ def choose (indices, choices, out=None, mode='raise'): fill_value=999999) """ - def fmask (x): + def fmask(x): "Returns the filled array, or True if masked." if x is masked: return True return filled(x) - def nmask (x): + + def nmask(x): "Returns the mask, True if ``masked``, False if ``nomask``." if x is masked: return True return getmask(x) - # Get the indices...... + # Get the indices. c = filled(indices, 0) - # Get the masks........ + # Get the masks. masks = [nmask(x) for x in choices] data = [fmask(x) for x in choices] # Construct the mask outputmask = np.choose(c, masks, mode=mode) outputmask = make_mask(mask_or(outputmask, getmask(indices)), copy=0, shrink=True) - # Get the choices...... + # Get the choices. d = np.choose(c, data, mode=mode, out=out).view(MaskedArray) if out is not None: if isinstance(out, MaskedArray): @@ -6929,6 +7055,7 @@ def round_(a, decimals=0, out=None): return out round = round_ + def inner(a, b): """ Returns the inner product of a and b for arrays of floating point types. @@ -6952,6 +7079,7 @@ inner.__doc__ = doc_note(np.inner.__doc__, "Masked values are replaced by 0.") innerproduct = inner + def outer(a, b): "maskedarray version of the numpy function." fa = filled(a, 0).ravel() @@ -6969,7 +7097,8 @@ outer.__doc__ = doc_note(np.outer.__doc__, "Masked values are replaced by 0.") outerproduct = outer -def allequal (a, b, fill_value=True): + +def allequal(a, b, fill_value=True): """ Return True if all entries of a and b are equal, using fill_value as a truth value where either or both are masked. @@ -7026,7 +7155,8 @@ def allequal (a, b, fill_value=True): else: return False -def allclose (a, b, masked_equal=True, rtol=1e-5, atol=1e-8): + +def allclose(a, b, masked_equal=True, rtol=1e-5, atol=1e-8): """ Returns True if two arrays are element-wise equal within a tolerance. @@ -7130,7 +7260,7 @@ def allclose (a, b, masked_equal=True, rtol=1e-5, atol=1e-8): return np.all(d) -#.............................................................................. + def asarray(a, dtype=None, order=None): """ Convert the input to a masked array of the given data-type. @@ -7178,6 +7308,7 @@ def asarray(a, dtype=None, order=None): """ return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=False) + def asanyarray(a, dtype=None): """ Convert the input to a masked array, conserving subclasses. @@ -7224,9 +7355,9 @@ def asanyarray(a, dtype=None): return masked_array(a, dtype=dtype, copy=False, keep_mask=True, subok=True) -#####-------------------------------------------------------------------------- -#---- --- Pickling --- -#####-------------------------------------------------------------------------- +############################################################################## +# Pickling # +############################################################################## def dump(a, F): """ Pickle a masked array to a file. @@ -7245,6 +7376,7 @@ def dump(a, F): F = open(F, 'w') return pickle.dump(a, F) + def dumps(a): """ Return a string corresponding to the pickling of a masked array. @@ -7260,6 +7392,7 @@ def dumps(a): """ return pickle.dumps(a) + def load(F): """ Wrapper around ``cPickle.load`` which accepts either a file-like object @@ -7284,6 +7417,7 @@ def load(F): F = open(F, 'r') return pickle.load(F) + def loads(strg): """ Load a pickle from the current string. @@ -7302,9 +7436,10 @@ def loads(strg): """ return pickle.loads(strg) -################################################################################ -def fromfile(file, dtype=float, count= -1, sep=''): - raise NotImplementedError("fromfile() not yet implemented for a MaskedArray.") + +def fromfile(file, dtype=float, count=-1, sep=''): + raise NotImplementedError( + "fromfile() not yet implemented for a MaskedArray.") def fromflex(fxarray): @@ -7372,8 +7507,8 @@ def fromflex(fxarray): return masked_array(fxarray['_data'], mask=fxarray['_mask']) - class _convert2ma: + """ Convert functions from numpy to numpy.ma. @@ -7384,12 +7519,12 @@ class _convert2ma: """ __doc__ = None - # + def __init__(self, funcname, params=None): self._func = getattr(np, funcname) self.__doc__ = self.getdoc() self._extras = params or {} - # + def getdoc(self): "Return the doc of the function (from the doc of the method)." doc = getattr(self._func, '__doc__', None) @@ -7400,7 +7535,7 @@ class _convert2ma: sig = "%s%s\n" % (self._func.__name__, sig) doc = sig + doc return doc - # + def __call__(self, a, *args, **params): # Find the common parameters to the call and the definition _extras = self._extras @@ -7423,7 +7558,8 @@ empty = _convert2ma('empty', params=dict(fill_value=None, hardmask=False)) empty_like = _convert2ma('empty_like') frombuffer = _convert2ma('frombuffer') fromfunction = _convert2ma('fromfunction') -identity = _convert2ma('identity', params=dict(fill_value=None, hardmask=False)) +identity = _convert2ma( + 'identity', params=dict(fill_value=None, hardmask=False)) indices = np.indices ones = _convert2ma('ones', params=dict(fill_value=None, hardmask=False)) ones_like = np.ones_like @@ -7431,7 +7567,7 @@ squeeze = np.squeeze zeros = _convert2ma('zeros', params=dict(fill_value=None, hardmask=False)) zeros_like = np.zeros_like -############################################################################### + def append(a, b, axis=None): """Append values to the end of an array. diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py index bd593e65f..a47c58684 100644 --- a/numpy/ma/extras.py +++ b/numpy/ma/extras.py @@ -10,39 +10,27 @@ A collection of utilities for `numpy.ma`. """ from __future__ import division, absolute_import, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' - -__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', - 'in1d', 'intersect1d', - 'mask_cols', 'mask_rowcols', 'mask_rows', 'masked_all', - 'masked_all_like', 'median', 'mr_', - 'notmasked_contiguous', 'notmasked_edges', - 'polyfit', - 'row_stack', - 'setdiff1d', 'setxor1d', - 'unique', 'union1d', - 'vander', 'vstack', - ] +__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', 'in1d', 'intersect1d', 'mask_cols', 'mask_rowcols', + 'mask_rows', 'masked_all', 'masked_all_like', 'median', 'mr_', + 'notmasked_contiguous', 'notmasked_edges', 'polyfit', 'row_stack', + 'setdiff1d', 'setxor1d', 'unique', 'union1d', 'vander', 'vstack', + ] import itertools import warnings from . import core as ma -from .core import MaskedArray, MAError, add, array, asarray, concatenate, count, \ - filled, getmask, getmaskarray, make_mask_descr, masked, masked_array, \ - mask_or, nomask, ones, sort, zeros, getdata -#from core import * +from .core import ( + MaskedArray, MAError, add, array, asarray, concatenate, filled, + getmask, getmaskarray, make_mask_descr, masked, masked_array, mask_or, + nomask, ones, sort, zeros, getdata + ) import numpy as np from numpy import ndarray, array as nxarray @@ -50,9 +38,11 @@ import numpy.core.umath as umath from numpy.lib.index_tricks import AxisConcatenator -#............................................................................... def issequence(seq): - """Is seq a sequence (ndarray, list or tuple)?""" + """ + Is seq a sequence (ndarray, list or tuple)? + + """ if isinstance(seq, (ndarray, tuple, list)): return True return False @@ -268,7 +258,6 @@ class _fromnxfunction: return '\n'.join((sig, doc, locdoc)) return - def __call__(self, *args, **params): func = getattr(np, self.__name__) if len(args) == 1: @@ -350,9 +339,9 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs): 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 + # 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) @@ -420,7 +409,8 @@ def apply_over_axes(func, a, axes): if array(axes).ndim == 0: axes = (axes,) for axis in axes: - if axis < 0: axis = N + axis + if axis < 0: + axis = N + axis args = (val, axis) res = func(*args) if res.ndim == val.ndim: @@ -557,10 +547,9 @@ def average(a, axis=None, weights=None, returned=False): d = add.reduce(w, axis) del w elif wsh == (ash[axis],): - ni = ash[axis] r = [None] * len(ash) r[axis] = slice(None, None, 1) - w = eval ("w[" + repr(tuple(r)) + "] * ones(ash, float)") + w = eval("w[" + repr(tuple(r)) + "] * ones(ash, float)") n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) del w, r @@ -580,11 +569,10 @@ def average(a, axis=None, weights=None, returned=False): n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) elif wsh == (ash[axis],): - ni = ash[axis] r = [None] * len(ash) r[axis] = slice(None, None, 1) - w = eval ("w[" + repr(tuple(r)) + \ - "] * masked_array(ones(ash, float), mask)") + w = eval("w[" + repr(tuple(r)) + + "] * masked_array(ones(ash, float), mask)") n = add.reduce(a * w, axis) d = add.reduce(w, axis, dtype=float) else: @@ -715,7 +703,6 @@ def median(a, axis=None, out=None, overwrite_input=False): return s -#.............................................................................. def compress_nd(x, axis=None): """Supress slices from multiple dimensions which contain masked values. @@ -1284,11 +1271,9 @@ def setdiff1d(ar1, ar2, assume_unique=False): return ar1[in1d(ar1, ar2, assume_unique=True, invert=True)] -#####-------------------------------------------------------------------------- -#---- --- Covariance --- -#####-------------------------------------------------------------------------- - - +############################################################################### +# Covariance # +############################################################################### def _covhelper(x, y=None, rowvar=True, allow_masked=True): @@ -1301,7 +1286,7 @@ def _covhelper(x, y=None, rowvar=True, allow_masked=True): 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...") + raise ValueError("Cannot process masked data.") # if x.shape[0] == 1: rowvar = True @@ -1319,7 +1304,7 @@ def _covhelper(x, y=None, rowvar=True, allow_masked=True): 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...") + raise ValueError("Cannot process masked data.") if xmask.any() or ymask.any(): if y.shape == x.shape: # Define some common mask @@ -1912,26 +1897,29 @@ def clump_masked(a): return slices +############################################################################### +# Polynomial fit # +############################################################################### -#####-------------------------------------------------------------------------- -#---- 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) @@ -1950,7 +1938,7 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False): w = asarray(w) if w.ndim != 1: raise TypeError("expected a 1-d array for weights") - if w.shape[0] != y.shape[0] : + if w.shape[0] != y.shape[0]: raise TypeError("expected w and y to have the same length") m = mask_or(m, getmask(w)) @@ -1963,5 +1951,3 @@ def polyfit(x, y, deg, rcond=None, full=False, w=None, cov=False): return np.polyfit(x, y, deg, rcond, full, w, cov) polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__) - -################################################################################ diff --git a/numpy/ma/mrecords.py b/numpy/ma/mrecords.py index 644383925..382bcc972 100644 --- a/numpy/ma/mrecords.py +++ b/numpy/ma/mrecords.py @@ -5,19 +5,15 @@ where fields can be accessed as attributes. Note that :class:`numpy.ma.MaskedArray` already supports structured datatypes and the masking of individual fields. -:author: Pierre Gerard-Marchant +.. moduleauthor:: Pierre Gerard-Marchant """ from __future__ import division, absolute_import, print_function -#!!!: * We should make sure that no field is called '_mask','mask','_fieldmask', -#!!!: or whatever restricted keywords. -#!!!: An idea would be to no bother in the first place, and then rename the -#!!!: invalid fields with a trailing underscore... -#!!!: Maybe we could just overload the parser function ? - - -__author__ = "Pierre GF Gerard-Marchant" +# We should make sure that no field is called '_mask','mask','_fieldmask', +# or whatever restricted keywords. An idea would be to no bother in the +# first place, and then rename the invalid fields with a trailing +# underscore. Maybe we could just overload the parser function ? import sys import warnings @@ -36,20 +32,27 @@ _byteorderconv = np.core.records._byteorderconv _typestr = ntypes._typestr import numpy.ma as ma -from numpy.ma import MAError, MaskedArray, masked, nomask, masked_array, \ - getdata, getmaskarray, filled +from numpy.ma import ( + MAError, MaskedArray, masked, nomask, masked_array, getdata, + getmaskarray, filled + ) _check_fill_value = ma.core._check_fill_value -__all__ = ['MaskedRecords', 'mrecarray', - 'fromarrays', 'fromrecords', 'fromtextfile', 'addfield', - ] +__all__ = [ + 'MaskedRecords', 'mrecarray', 'fromarrays', 'fromrecords', + 'fromtextfile', 'addfield', + ] reserved_fields = ['_data', '_mask', '_fieldmask', 'dtype'] + def _getformats(data): - "Returns the formats of each array of arraylist as a comma-separated string." + """ + Returns the formats of arrays in arraylist as a comma-separated string. + + """ if hasattr(data, 'dtype'): return ",".join([desc[1] for desc in data.dtype.descr]) @@ -62,10 +65,14 @@ def _getformats(data): formats += ',' return formats[:-1] + def _checknames(descr, names=None): - """Checks that the field names of the descriptor ``descr`` are not some -reserved keywords. If this is the case, a default 'f%i' is substituted. -If the argument `names` is not None, updates the field names to valid names. + """ + Checks that field names ``descr`` are not reserved keywords. + + If this is the case, a default 'f%i' is substituted. If the argument + `names` is not None, updates the field names to valid names. + """ ndescr = len(descr) default_names = ['f%i' % i for i in range(ndescr)] @@ -103,29 +110,33 @@ def _get_fieldmask(self): class MaskedRecords(MaskedArray, object): """ -*IVariables*: - _data : {recarray} + Attributes + ---------- + _data : recarray Underlying data, as a record array. - _mask : {boolean array} - Mask of the records. A record is masked when all its fields are masked. - _fieldmask : {boolean recarray} - Record array of booleans, setting the mask of each individual field of each record. - _fill_value : {record} + _mask : boolean array + Mask of the records. A record is masked when all its fields are + masked. + _fieldmask : boolean recarray + Record array of booleans, setting the mask of each individual field + of each record. + _fill_value : record Filling values for each field. + """ - #............................................ + def __new__(cls, shape, dtype=None, buf=None, offset=0, strides=None, formats=None, names=None, titles=None, byteorder=None, aligned=False, mask=nomask, hard_mask=False, fill_value=None, keep_mask=True, copy=False, **options): - # + self = recarray.__new__(cls, shape, dtype=dtype, buf=buf, offset=offset, strides=strides, formats=formats, names=names, titles=titles, byteorder=byteorder, aligned=aligned,) - # + mdtype = ma.make_mask_descr(self.dtype) if mask is nomask or not np.size(mask): if not keep_mask: @@ -154,9 +165,9 @@ class MaskedRecords(MaskedArray, object): dtype=mdtype) self._mask = _mask return self - #...................................................... + def __array_finalize__(self, obj): - # Make sure we have a _fieldmask by default .. + # Make sure we have a _fieldmask by default _mask = getattr(obj, '_mask', None) if _mask is None: objmask = getattr(obj, '_mask', nomask) @@ -175,19 +186,29 @@ class MaskedRecords(MaskedArray, object): _dict['_baseclass'] = recarray return - def _getdata(self): - "Returns the data as a recarray." + """ + Returns the data as a recarray. + + """ return ndarray.view(self, recarray) + _data = property(fget=_getdata) def _getfieldmask(self): - "Alias to mask" + """ + Alias to mask. + + """ return self._mask + _fieldmask = property(fget=_getfieldmask) def __len__(self): - "Returns the length" + """ + Returns the length + + """ # We have more than one record if self.ndim: return len(self._data) @@ -197,20 +218,21 @@ class MaskedRecords(MaskedArray, object): def __getattribute__(self, attr): try: return object.__getattribute__(self, attr) - except AttributeError: # attr must be a fieldname + except AttributeError: + # attr must be a fieldname pass fielddict = ndarray.__getattribute__(self, 'dtype').fields try: res = fielddict[attr][:2] except (TypeError, KeyError): raise AttributeError("record array has no attribute %s" % attr) - # So far, so good... + # So far, so good _localdict = ndarray.__getattribute__(self, '__dict__') _data = ndarray.view(self, _localdict['_baseclass']) obj = _data.getfield(*res) if obj.dtype.fields: - raise NotImplementedError("MaskedRecords is currently limited to"\ - "simple records...") + raise NotImplementedError("MaskedRecords is currently limited to" + "simple records.") # Get some special attributes # Reset the object's mask hasmasked = False @@ -238,9 +260,11 @@ class MaskedRecords(MaskedArray, object): obj = obj.item() return obj - def __setattr__(self, attr, val): - "Sets the attribute attr to the value val." + """ + Sets the attribute attr to the value val. + + """ # Should we call __setmask__ first ? if attr in ['mask', 'fieldmask']: self.__setmask__(val) @@ -260,14 +284,15 @@ class MaskedRecords(MaskedArray, object): exctype, value = sys.exc_info()[:2] raise exctype(value) else: - # Get the list of names ...... + # Get the list of names fielddict = ndarray.__getattribute__(self, 'dtype').fields or {} # Check the attribute if attr not in fielddict: return ret - if newattr: # We just added this one - try: # or this setattr worked on an internal - # attribute. + if newattr: + # We just added this one or this setattr worked on an + # internal attribute. + try: object.__delattr__(self, attr) except: return ret @@ -276,7 +301,7 @@ class MaskedRecords(MaskedArray, object): res = fielddict[attr][:2] except (TypeError, KeyError): raise AttributeError("record array has no attribute %s" % attr) - # + if val is masked: _fill_value = _localdict['_fill_value'] if _fill_value is not None: @@ -291,19 +316,22 @@ class MaskedRecords(MaskedArray, object): _localdict['_mask'].__setitem__(attr, mval) return obj - def __getitem__(self, indx): - """Returns all the fields sharing the same fieldname base. -The fieldname base is either `_data` or `_mask`.""" + """ + Returns all the fields sharing the same fieldname base. + + The fieldname base is either `_data` or `_mask`. + + """ _localdict = self.__dict__ _mask = ndarray.__getattribute__(self, '_mask') _data = ndarray.view(self, _localdict['_baseclass']) - # We want a field ........ + # We want a field if isinstance(indx, basestring): - #!!!: Make sure _sharedmask is True to propagate back to _fieldmask - #!!!: Don't use _set_mask, there are some copies being made... - #!!!: ...that break propagation - #!!!: Don't force the mask to nomask, that wrecks easy masking + # Make sure _sharedmask is True to propagate back to _fieldmask + # Don't use _set_mask, there are some copies being made that + # break propagation Don't force the mask to nomask, that wreaks + # easy masking obj = _data[indx].view(MaskedArray) obj._mask = _mask[indx] obj._sharedmask = True @@ -314,21 +342,26 @@ The fieldname base is either `_data` or `_mask`.""" if not obj.ndim and obj._mask: return masked return obj - # We want some elements .. - # First, the data ........ + # We want some elements. + # First, the data. obj = np.array(_data[indx], copy=False).view(mrecarray) obj._mask = np.array(_mask[indx], copy=False).view(recarray) return obj - #.... + def __setitem__(self, indx, value): - "Sets the given record to value." + """ + Sets the given record to value. + + """ MaskedArray.__setitem__(self, indx, value) if isinstance(indx, basestring): self._mask[indx] = ma.getmaskarray(value) - def __str__(self): - "Calculates the string representation." + """ + Calculates the string representation. + + """ if self.size > 1: mstr = ["(%s)" % ",".join([str(i) for i in s]) for s in zip(*[getattr(self, f) for f in self.dtype.names])] @@ -337,9 +370,12 @@ The fieldname base is either `_data` or `_mask`.""" mstr = ["%s" % ",".join([str(i) for i in s]) for s in zip([getattr(self, f) for f in self.dtype.names])] return "(%s)" % ", ".join(mstr) - # + def __repr__(self): - "Calculates the repr representation." + """ + Calculates the repr representation. + + """ _names = self.dtype.names fmt = "%%%is : %%s" % (max([len(n) for n in _names]) + 4,) reprstr = [fmt % (f, getattr(self, f)) for f in self.dtype.names] @@ -347,16 +383,19 @@ The fieldname base is either `_data` or `_mask`.""" reprstr.extend([fmt % (' fill_value', self.fill_value), ' )']) return str("\n".join(reprstr)) -# #...................................................... + def view(self, dtype=None, type=None): - """Returns a view of the mrecarray.""" - # OK, basic copy-paste from MaskedArray.view... + """ + Returns a view of the mrecarray. + + """ + # OK, basic copy-paste from MaskedArray.view. if dtype is None: if type is None: output = ndarray.view(self) else: output = ndarray.view(self, type) - # Here again... + # Here again. elif type is None: try: if issubclass(dtype, ndarray): @@ -368,8 +407,8 @@ The fieldname base is either `_data` or `_mask`.""" except TypeError: dtype = np.dtype(dtype) # we need to revert to MaskedArray, but keeping the possibility - # ...of subclasses (eg, TimeSeriesRecords), so we'll force a type - # ...set to the first parent + # of subclasses (eg, TimeSeriesRecords), so we'll force a type + # set to the first parent if dtype.fields is None: basetype = self.__class__.__bases__[0] output = self.__array__().view(dtype, basetype) @@ -387,27 +426,35 @@ The fieldname base is either `_data` or `_mask`.""" return output def harden_mask(self): - "Forces the mask to hard" + """ + Forces the mask to hard. + + """ self._hardmask = True + def soften_mask(self): - "Forces the mask to soft" + """ + Forces the mask to soft + + """ self._hardmask = False def copy(self): - """Returns a copy of the masked record.""" - _localdict = self.__dict__ + """ + Returns a copy of the masked record. + + """ copied = self._data.copy().view(type(self)) copied._mask = self._mask.copy() return copied def tolist(self, fill_value=None): - """Copy the data portion of the array to a hierarchical python - list and returns that list. + """ + Return the data portion of the array as a 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``. + 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``. """ if fill_value is not None: @@ -416,10 +463,11 @@ The fieldname base is either `_data` or `_mask`.""" mask = narray(self._mask.tolist()) result[mask] = None return result.tolist() - #-------------------------------------------- - # Pickling + def __getstate__(self): - """Return the internal state of the masked array, for pickling purposes. + """Return the internal state of the masked array. + + This is for pickling. """ state = (1, @@ -431,11 +479,13 @@ The fieldname base is either `_data` or `_mask`.""" self._fill_value, ) return state - # + def __setstate__(self, state): - """Restore the internal state of the masked array, for pickling purposes. - ``state`` is typically the output of the ``__getstate__`` output, and is a - 5-tuple: + """ + Restore the internal state of the masked array. + + This is for pickling. ``state`` is typically the output of the + ``__getstate__`` output, and is a 5-tuple: - class name - a tuple giving the shape of the data @@ -449,9 +499,10 @@ The fieldname base is either `_data` or `_mask`.""" mdtype = dtype([(k, bool_) for (k, _) in self.dtype.descr]) self.__dict__['_mask'].__setstate__((shp, mdtype, isf, msk)) self.fill_value = flv - # + def __reduce__(self): - """Return a 3-tuple for pickling a MaskedArray. + """ + Return a 3-tuple for pickling a MaskedArray. """ return (_mrreconstruct, @@ -459,27 +510,27 @@ The fieldname base is either `_data` or `_mask`.""" self.__getstate__()) def _mrreconstruct(subtype, baseclass, baseshape, basetype,): - """Internal function that builds a new MaskedArray from the - information stored in a pickle. + """ + Build a new MaskedArray from the information stored in a pickle. """ _data = ndarray.__new__(baseclass, baseshape, basetype).view(subtype) -# _data._mask = ndarray.__new__(ndarray, baseshape, 'b1') -# return _data _mask = ndarray.__new__(ndarray, baseshape, 'b1') return subtype.__new__(subtype, _data, mask=_mask, dtype=basetype,) - mrecarray = MaskedRecords -#####--------------------------------------------------------------------------- -#---- --- Constructors --- -#####--------------------------------------------------------------------------- + +############################################################################### +# Constructors # +############################################################################### + def fromarrays(arraylist, dtype=None, shape=None, formats=None, names=None, titles=None, aligned=False, byteorder=None, fill_value=None): - """Creates a mrecarray from a (flat) list of masked arrays. + """ + Creates a mrecarray from a (flat) list of masked arrays. Parameters ---------- @@ -504,6 +555,7 @@ def fromarrays(arraylist, dtype=None, shape=None, formats=None, Notes ----- Lists of tuples should be preferred over lists of lists for faster processing. + """ datalist = [getdata(x) for x in arraylist] masklist = [np.atleast_1d(getmaskarray(x)) for x in arraylist] @@ -517,11 +569,11 @@ def fromarrays(arraylist, dtype=None, shape=None, formats=None, return _array -#.............................................................................. def fromrecords(reclist, dtype=None, shape=None, formats=None, names=None, titles=None, aligned=False, byteorder=None, fill_value=None, mask=nomask): - """Creates a MaskedRecords from a list of records. + """ + Creates a MaskedRecords from a list of records. Parameters ---------- @@ -548,14 +600,11 @@ def fromrecords(reclist, dtype=None, shape=None, formats=None, names=None, Notes ----- Lists of tuples should be preferred over lists of lists for faster processing. + """ # Grab the initial _fieldmask, if needed: _mask = getattr(reclist, '_mask', None) - # Get the list of records..... - try: - nfields = len(reclist[0]) - except TypeError: - nfields = len(reclist[0].dtype) + # Get the list of records. if isinstance(reclist, ndarray): # Make sure we don't have some hidden mask if isinstance(reclist, MaskedArray): @@ -584,19 +633,24 @@ def fromrecords(reclist, dtype=None, shape=None, formats=None, names=None, mrec._mask[:] = _mask return mrec + def _guessvartypes(arr): - """Tries to guess the dtypes of the str_ ndarray `arr`, by testing element-wise -conversion. Returns a list of dtypes. -The array is first converted to ndarray. If the array is 2D, the test is performed -on the first line. An exception is raised if the file is 3D or more. + """ + Tries to guess the dtypes of the str_ ndarray `arr`. + + Guesses by testing element-wise conversion. Returns a list of dtypes. + The array is first converted to ndarray. If the array is 2D, the test + is performed on the first line. An exception is raised if the file is + 3D or more. + """ vartypes = [] arr = np.asarray(arr) - if len(arr.shape) == 2 : + if len(arr.shape) == 2: arr = arr[0] elif len(arr.shape) > 2: raise ValueError("The array should be 2D at most!") - # Start the conversion loop ....... + # Start the conversion loop. for f in arr: try: int(f) @@ -605,7 +659,7 @@ on the first line. An exception is raised if the file is 3D or more. float(f) except ValueError: try: - val = complex(f) + complex(f) except ValueError: vartypes.append(arr.dtype) else: @@ -616,9 +670,13 @@ on the first line. An exception is raised if the file is 3D or more. vartypes.append(np.dtype(int)) return vartypes + def openfile(fname): - "Opens the file handle of file `fname`" - # A file handle ................... + """ + Opens the file handle of file `fname`. + + """ + # A file handle if hasattr(fname, 'readline'): return fname # Try to open the file and guess its type @@ -635,7 +693,8 @@ def openfile(fname): def fromtextfile(fname, delimitor=None, commentchar='#', missingchar='', varnames=None, vartypes=None): - """Creates a mrecarray from data stored in the file `filename`. + """ + Creates a mrecarray from data stored in the file `filename`. Parameters ---------- @@ -657,12 +716,12 @@ def fromtextfile(fname, delimitor=None, commentchar='#', missingchar='', Ultra simple: the varnames are in the header, one line""" - # Try to open the file ...................... - f = openfile(fname) + # Try to open the file. + ftext = openfile(fname) # Get the first non-empty line as the varnames while True: - line = f.readline() + line = ftext.readline() firstline = line[:line.find(commentchar)].strip() _varnames = firstline.split(delimitor) if len(_varnames) > 1: @@ -670,13 +729,13 @@ def fromtextfile(fname, delimitor=None, commentchar='#', missingchar='', if varnames is None: varnames = _varnames - # Get the data .............................. - _variables = masked_array([line.strip().split(delimitor) for line in f - if line[0] != commentchar and len(line) > 1]) + # Get the data. + _variables = masked_array([line.strip().split(delimitor) for line in ftext + if line[0] != commentchar and len(line) > 1]) (_, nfields) = _variables.shape - f.close() + ftext.close() - # Try to guess the dtype .................... + # Try to guess the dtype. if vartypes is None: vartypes = _guessvartypes(_variables[0]) else: @@ -687,11 +746,11 @@ def fromtextfile(fname, delimitor=None, commentchar='#', missingchar='', warnings.warn(msg % (len(vartypes), nfields)) vartypes = _guessvartypes(_variables[0]) - # Construct the descriptor .................. + # Construct the descriptor. mdescr = [(n, f) for (n, f) in zip(varnames, vartypes)] mfillv = [ma.default_fill_value(f) for f in vartypes] - # Get the data and the mask ................. + # Get the data and the mask. # We just need a list of masked_arrays. It's easier to create it like that: _mask = (_variables.T == missingchar) _datalist = [masked_array(a, mask=m, dtype=t, fill_value=f) @@ -699,18 +758,21 @@ def fromtextfile(fname, delimitor=None, commentchar='#', missingchar='', return fromarrays(_datalist, dtype=mdescr) -#.................................................................... + def addfield(mrecord, newfield, newfieldname=None): - """Adds a new field to the masked record array, using `newfield` as data -and `newfieldname` as name. If `newfieldname` is None, the new field name is -set to 'fi', where `i` is the number of existing fields. + """Adds a new field to the masked record array + + Uses `newfield` as data and `newfieldname` as name. If `newfieldname` + is None, the new field name is set to 'fi', where `i` is the number of + existing fields. + """ _data = mrecord._data _mask = mrecord._mask if newfieldname is None or newfieldname in reserved_fields: newfieldname = 'f%i' % len(_data.dtype) newfield = ma.array(newfield) - # Get the new data ............ + # Get the new data. # Create a new empty recarray newdtype = np.dtype(_data.dtype.descr + [(newfieldname, newfield.dtype)]) newdata = recarray(_data.shape, newdtype) @@ -720,7 +782,7 @@ set to 'fi', where `i` is the number of existing fields. # Add the new field newdata.setfield(newfield._data, *newdata.dtype.fields[newfieldname]) newdata = newdata.view(MaskedRecords) - # Get the new mask ............. + # Get the new mask # Create a new empty recarray newmdtype = np.dtype([(n, bool_) for n in newdtype.names]) newmask = recarray(_data.shape, newmdtype) diff --git a/numpy/ma/setup.py b/numpy/ma/setup.py index 5486ff46a..d1d6c89b5 100644 --- a/numpy/ma/setup.py +++ b/numpy/ma/setup.py @@ -1,13 +1,6 @@ #!/usr/bin/env python from __future__ import division, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' - -import os - def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration config = Configuration('ma', parent_package, top_path) diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py index ce6cddac7..d3ec70488 100644 --- a/numpy/ma/tests/test_core.py +++ b/numpy/ma/tests/test_core.py @@ -9,25 +9,43 @@ from __future__ import division, absolute_import, print_function __author__ = "Pierre GF Gerard-Marchant" import warnings -import sys import pickle -from functools import reduce import operator - -from nose.tools import assert_raises +from functools import reduce import numpy as np import numpy.ma.core import numpy.core.fromnumeric as fromnumeric +import numpy.core.umath as umath +from numpy.testing import TestCase, run_module_suite, assert_raises from numpy import ndarray -from numpy.ma.testutils import * -from numpy.ma.core import * from numpy.compat import asbytes, asbytes_nested +from numpy.ma.testutils import ( + assert_, assert_array_equal, assert_equal, assert_almost_equal, + assert_equal_records, fail_if_equal, assert_not_equal, + assert_mask_equal, + ) +from numpy.ma.core import ( + MAError, MaskError, MaskType, MaskedArray, abs, absolute, add, all, + allclose, allequal, alltrue, angle, anom, arange, arccos, arctan2, + arcsin, arctan, argsort, array, asarray, choose, concatenate, + conjugate, cos, cosh, count, default_fill_value, diag, divide, empty, + empty_like, equal, exp, flatten_mask, filled, fix_invalid, + flatten_structured_array, fromflex, getmask, getmaskarray, greater, + greater_equal, identity, inner, isMaskedArray, less, less_equal, log, + log10, make_mask, make_mask_descr, mask_or, masked, masked_array, + masked_equal, masked_greater, masked_greater_equal, masked_inside, + masked_less, masked_less_equal, masked_not_equal, masked_outside, + masked_print_option, masked_values, masked_where, max, maximum, + maximum_fill_value, min, minimum, minimum_fill_value, mod, multiply, + mvoid, nomask, not_equal, ones, outer, power, product, put, putmask, + ravel, repeat, reshape, resize, shape, sin, sinh, sometrue, sort, sqrt, + subtract, sum, take, tan, tanh, transpose, where, zeros, + ) pi = np.pi -#.............................................................................. class TestMaskedArray(TestCase): # Base test class for MaskedArrays. @@ -95,7 +113,7 @@ class TestMaskedArray(TestCase): xm.shape = s ym.shape = s xf.shape = s - # + self.assertTrue(not isMaskedArray(x)) self.assertTrue(isMaskedArray(xm)) assert_equal(shape(xm), s) @@ -126,7 +144,7 @@ class TestMaskedArray(TestCase): xmym = concatenate((xm, ym), 1) assert_equal(np.concatenate((x, y), 1), xmym) assert_equal(np.concatenate((xm.mask, ym.mask), 1), xmym._mask) - # + x = zeros(2) y = array(ones(2), mask=[False, True]) z = concatenate((x, y)) @@ -141,7 +159,7 @@ class TestMaskedArray(TestCase): data = masked_array(list(zip(np.random.rand(10), np.arange(10))), dtype=[('a', float), ('b', int)]) - # + test = concatenate([data[:5], data[5:]]) assert_equal_records(test, data) @@ -177,7 +195,7 @@ class TestMaskedArray(TestCase): data = array((x, x[::-1])) assert_equal(data, [[0, 1, 2, 3, 4], [4, 3, 2, 1, 0]]) assert_equal(data._mask, [[1, 0, 0, 0, 0], [0, 0, 0, 0, 1]]) - # + x.mask = nomask data = array((x, x[::-1])) assert_equal(data, [[0, 1, 2, 3, 4], [4, 3, 2, 1, 0]]) @@ -221,7 +239,7 @@ class TestMaskedArray(TestCase): a[0] = x assert_equal(a[0], x) self.assertTrue(a[0] is x) - # + import datetime dt = datetime.datetime.now() a[0] = dt @@ -234,7 +252,8 @@ class TestMaskedArray(TestCase): x3 = array(x1, mask=[0, 1, 0, 1]) x4 = array(x1) # test conversion to strings - junk, garbage = str(x2), repr(x2) + str(x2) # raises? + repr(x2) # raises? assert_equal(np.sort(x1), sort(x2, endwith=False)) # tests of indexing assert_(type(x2[1]) is type(x1[1])) @@ -283,8 +302,8 @@ class TestMaskedArray(TestCase): x3 = array(x1, mask=[[0, 1, 0], [1, 0, 0]]) x4 = array(x1) # test conversion to strings - junk, garbage = str(x2), repr(x2) - # assert_equal(np.sort(x1), sort(x2, endwith=False)) + str(x2) # raises? + repr(x2) # raises? # tests of indexing assert_(type(x2[1, 0]) is type(x1[1, 0])) assert_(x1[1, 0] == x2[1, 0]) @@ -372,7 +391,7 @@ class TestMaskedArray(TestCase): y9 = x4.copy() assert_equal(y9._data, x4._data) assert_equal(y9._mask, x4._mask) - # + x = masked_array([1, 2, 3], mask=[0, 1, 0]) # Copy is False by default y = masked_array(x) @@ -388,11 +407,11 @@ class TestMaskedArray(TestCase): copied = deepcopy(a) assert_equal(copied.mask, a.mask) assert_not_equal(id(a._mask), id(copied._mask)) - # + copied[1] = 1 assert_equal(copied.mask, [0, 0, 0]) assert_equal(a.mask, [0, 1, 0]) - # + copied = deepcopy(a) assert_equal(copied.mask, a.mask) copied.mask[1] = False @@ -463,11 +482,11 @@ class TestMaskedArray(TestCase): assert_equal(1, int(array([[[1]]]))) assert_equal(1.0, float(array([[1]]))) self.assertRaises(TypeError, float, array([1, 1])) - # + with warnings.catch_warnings(): warnings.simplefilter('ignore', UserWarning) assert_(np.isnan(float(array([1], mask=[1])))) - # + a = array([1, 2, 3], mask=[1, 0, 0]) self.assertRaises(TypeError, lambda:float(a)) assert_equal(float(a[-1]), 3.) @@ -487,14 +506,14 @@ class TestMaskedArray(TestCase): assert_equal(z.imag, 10 * x) assert_equal((z * conjugate(z)).real, 101 * x * x) z.imag[...] = 0.0 - # + x = arange(10) x[3] = masked assert_(str(x[3]) == str(masked)) c = x >= 8 assert_(count(where(c, masked, masked)) == 0) assert_(shape(where(c, masked, masked)) == c.shape) - # + z = masked_where(c, x) assert_(z.dtype is x.dtype) assert_(z[3] is masked) @@ -565,7 +584,7 @@ class TestMaskedArray(TestCase): test = a.filled(0) control = np.array([(1, (0, 1)), (2, (2, 0))], dtype=ndtype) assert_equal(test, control) - # + test = a['B'].filled(0) control = np.array([(0, 1), (2, 0)], dtype=a['B'].dtype) assert_equal(test, control) @@ -637,10 +656,10 @@ class TestMaskedArray(TestCase): a = np.array([(1, 2,)], dtype=ndtype)[0] f = mvoid(a) assert_(isinstance(f, mvoid)) - # + a = masked_array([(1, 2)], mask=[(1, 0)], dtype=ndtype)[0] assert_(isinstance(a, mvoid)) - # + a = masked_array([(1, 2), (1, 2)], mask=[(1, 0), (0, 0)], dtype=ndtype) f = mvoid(a._data[0], a._mask[0]) assert_(isinstance(f, mvoid)) @@ -698,7 +717,6 @@ class TestMaskedArray(TestCase): assert mx2[0] == 0. -#------------------------------------------------------------------------------ class TestMaskedArrayArithmetic(TestCase): # Base test class for MaskedArrays. @@ -761,15 +779,15 @@ class TestMaskedArrayArithmetic(TestCase): x = arange(6, dtype=float) x.shape = (2, 3) y = arange(3, dtype=float) - # + z = x / y assert_equal(z, [[-1., 1., 1.], [-1., 4., 2.5]]) assert_equal(z.mask, [[1, 0, 0], [1, 0, 0]]) - # + z = x / y[None,:] assert_equal(z, [[-1., 1., 1.], [-1., 4., 2.5]]) assert_equal(z.mask, [[1, 0, 0], [1, 0, 0]]) - # + y = arange(2, dtype=float) z = x / y[:, None] assert_equal(z, [[-1., -1., -1.], [3., 4., 5.]]) @@ -880,7 +898,7 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal([1, 2], res) assert_(getmask(res) is nomask) - ott= array([0., 1., 2., 3.]) + ott = array([0., 1., 2., 3.]) res = count(ott, 0) assert_(isinstance(res, ndarray)) assert_(res.dtype.type is np.intp) @@ -896,7 +914,7 @@ class TestMaskedArrayArithmetic(TestCase): # following are true because of careful selection of data assert_equal(max(xr), maximum(xmr)) assert_equal(min(xr), minimum(xmr)) - # + assert_equal(minimum([1, 2, 3], [4, 0, 9]), [1, 0, 3]) assert_equal(maximum([1, 2, 3], [4, 0, 9]), [4, 2, 9]) x = arange(5) @@ -907,7 +925,7 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(maximum(x, y), where(greater(x, y), x, y)) assert_(minimum(x) == 0) assert_(maximum(x) == 4) - # + x = arange(4).reshape(2, 2) x[-1, -1] = masked assert_equal(maximum(x), 2) @@ -917,15 +935,15 @@ class TestMaskedArrayArithmetic(TestCase): aminimum = minimum(a, a) self.assertTrue(isinstance(aminimum, MaskedArray)) assert_equal(aminimum, np.minimum(a, a)) - # + aminimum = minimum.outer(a, a) self.assertTrue(isinstance(aminimum, MaskedArray)) assert_equal(aminimum, np.minimum.outer(a, a)) - # + amaximum = maximum(a, a) self.assertTrue(isinstance(amaximum, MaskedArray)) assert_equal(amaximum, np.maximum(a, a)) - # + amaximum = maximum.outer(a, a) self.assertTrue(isinstance(amaximum, MaskedArray)) assert_equal(amaximum, np.maximum.outer(a, a)) @@ -975,7 +993,7 @@ class TestMaskedArrayArithmetic(TestCase): self.assertTrue(xm[0].ptp() is masked) self.assertTrue(xm[0].ptp(0) is masked) self.assertTrue(xm[0].ptp(-1) is masked) - # + x = array([1, 2, 3], mask=True) self.assertTrue(x.min() is masked) self.assertTrue(x.max() is masked) @@ -1006,21 +1024,21 @@ class TestMaskedArrayArithmetic(TestCase): # Test binary operations on 2D data a = array([[1.], [2.], [3.]], mask=[[False], [True], [True]]) b = array([[2., 3.], [4., 5.], [6., 7.]]) - # + test = a * b control = array([[2., 3.], [2., 2.], [3., 3.]], mask=[[0, 0], [1, 1], [1, 1]]) assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + test = b * a control = array([[2., 3.], [4., 5.], [6., 7.]], mask=[[0, 0], [1, 1], [1, 1]]) assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + a = array([[1.], [2.], [3.]]) b = array([[2., 3.], [4., 5.], [6., 7.]], mask=[[0, 0], [0, 0], [0, 1]]) @@ -1030,7 +1048,7 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + test = b * a control = array([[2, 3], [8, 10], [18, 7]], mask=[[0, 0], [0, 0], [0, 1]]) @@ -1042,21 +1060,21 @@ class TestMaskedArrayArithmetic(TestCase): # Test domained binary operations on 2D data a = array([[1.], [2.], [3.]], mask=[[False], [True], [True]]) b = array([[2., 3.], [4., 5.], [6., 7.]]) - # + test = a / b control = array([[1. / 2., 1. / 3.], [2., 2.], [3., 3.]], mask=[[0, 0], [1, 1], [1, 1]]) assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + test = b / a control = array([[2. / 1., 3. / 1.], [4., 5.], [6., 7.]], mask=[[0, 0], [1, 1], [1, 1]]) assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + a = array([[1.], [2.], [3.]]) b = array([[2., 3.], [4., 5.], [6., 7.]], mask=[[0, 0], [0, 0], [0, 1]]) @@ -1066,7 +1084,7 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(test, control) assert_equal(test.data, control.data) assert_equal(test.mask, control.mask) - # + test = b / a control = array([[2 / 1., 3 / 1.], [4 / 2., 5 / 2.], [6 / 3., 7]], mask=[[0, 0], [0, 0], [0, 1]]) @@ -1135,9 +1153,9 @@ class TestMaskedArrayArithmetic(TestCase): def test_methods_with_output(self): xm = array(np.random.uniform(0, 10, 12)).reshape(3, 4) xm[:, 0] = xm[0] = xm[-1, -1] = masked - # + funclist = ('sum', 'prod', 'var', 'std', 'max', 'min', 'ptp', 'mean',) - # + for funcname in funclist: npfunc = getattr(np, funcname) xmmeth = getattr(xm, funcname) @@ -1148,7 +1166,7 @@ class TestMaskedArrayArithmetic(TestCase): # ... the result should be the given output assert_(result is output) assert_equal(result, xmmeth(axis=0, out=output)) - # + output = empty(4, dtype=int) result = xmmeth(axis=0, out=output) assert_(result is output) @@ -1187,8 +1205,9 @@ class TestMaskedArrayArithmetic(TestCase): assert_equal(test.mask, [False, False]) def test_eq_w_None(self): - # Really, comparisons with None should not be done, but - # check them anyway + # Really, comparisons with None should not be done, but check them + # anyway. Note that pep8 will flag these tests. + # With partial mask a = array([1, 2], mask=[0, 1]) assert_equal(a == None, False) @@ -1219,19 +1238,18 @@ class TestMaskedArrayArithmetic(TestCase): a = masked_array([-1, 0, 1, 2, 3], mask=[0, 0, 0, 0, 1]) control = masked_array([np.nan, np.nan, 0, np.log(2), -1], mask=[1, 1, 0, 0, 1]) - # + test = log(a) assert_equal(test, control) assert_equal(test.mask, control.mask) assert_equal(a.mask, [0, 0, 0, 0, 1]) - # + test = np.log(a) assert_equal(test, control) assert_equal(test.mask, control.mask) assert_equal(a.mask, [0, 0, 0, 0, 1]) -#------------------------------------------------------------------------------ class TestMaskedArrayAttributes(TestCase): def test_keepmask(self): @@ -1292,7 +1310,7 @@ class TestMaskedArrayAttributes(TestCase): xh[filled(xh > 1, False)] = 5 assert_equal(xh._data, [0, 1, 2, 5, 5]) assert_equal(xh._mask, [1, 1, 1, 0, 0]) - # + xh = array([[1, 2], [3, 4]], mask=[[1, 0], [0, 0]], hard_mask=True) xh[0] = 0 assert_equal(xh._data, [[1, 0], [3, 4]]) @@ -1407,7 +1425,7 @@ class TestMaskedArrayAttributes(TestCase): m = np.ma.array(a) m.dtype = np.dtype('f4') - repr(m) # raises? + repr(m) # raises? assert_equal(m.dtype, np.dtype('f4')) # check that dtype changes that change shape of mask too much @@ -1417,7 +1435,7 @@ class TestMaskedArrayAttributes(TestCase): m.dtype = np.dtype('f8') assert_raises(ValueError, assign) - b = a.view(dtype='f4', type=np.ma.MaskedArray) # raises? + b = a.view(dtype='f4', type=np.ma.MaskedArray) # raises? assert_equal(b.dtype, np.dtype('f4')) # check that nomask is preserved @@ -1428,18 +1446,17 @@ class TestMaskedArrayAttributes(TestCase): assert_equal(m._mask, np.ma.nomask) -#------------------------------------------------------------------------------ class TestFillingValues(TestCase): def test_check_on_scalar(self): # Test _check_fill_value set to valid and invalid values _check_fill_value = np.ma.core._check_fill_value - # + fval = _check_fill_value(0, int) assert_equal(fval, 0) fval = _check_fill_value(None, int) assert_equal(fval, default_fill_value(0)) - # + fval = _check_fill_value(0, "|S3") assert_equal(fval, asbytes("0")) fval = _check_fill_value(None, "|S3") @@ -1502,20 +1519,20 @@ class TestFillingValues(TestCase): # properly dealt with a = array(asbytes_nested(['3', '4', '5'])) a._optinfo.update({'comment':"updated!"}) - # + b = array(a, dtype=int) assert_equal(b._data, [3, 4, 5]) assert_equal(b.fill_value, default_fill_value(0)) - # + b = array(a, dtype=float) assert_equal(b._data, [3, 4, 5]) assert_equal(b.fill_value, default_fill_value(0.)) - # + b = a.astype(int) assert_equal(b._data, [3, 4, 5]) assert_equal(b.fill_value, default_fill_value(0)) assert_equal(b._optinfo['comment'], "updated!") - # + b = a.astype([('a', '|S3')]) assert_equal(b['a']._data, a._data) assert_equal(b['a'].fill_value, a.fill_value) @@ -1525,19 +1542,19 @@ class TestFillingValues(TestCase): data = masked_array([1, 2, 3], fill_value=-999) series = data[[0, 2, 1]] assert_equal(series._fill_value, data._fill_value) - # + mtype = [('f', float), ('s', '|S3')] x = array([(1, 'a'), (2, 'b'), (pi, 'pi')], dtype=mtype) x.fill_value = 999 assert_equal(x.fill_value.item(), [999., asbytes('999')]) assert_equal(x['f'].fill_value, 999) assert_equal(x['s'].fill_value, asbytes('999')) - # + x.fill_value = (9, '???') assert_equal(x.fill_value.item(), (9, asbytes('???'))) assert_equal(x['f'].fill_value, 9) assert_equal(x['s'].fill_value, asbytes('???')) - # + x = array([1, 2, 3.1]) x.fill_value = 999 assert_equal(np.asarray(x.fill_value).dtype, float) @@ -1560,7 +1577,7 @@ class TestFillingValues(TestCase): assert_equal(_check_fill_value(None, ndtype), control) control = np.array((0,), dtype=[('f0', float)]).astype(ndtype) assert_equal(_check_fill_value(0, ndtype), control) - # + ndtype = np.dtype("int, (2,3)float, float") control = np.array((default_fill_value(0), default_fill_value(0.), @@ -1594,13 +1611,13 @@ class TestFillingValues(TestCase): assert_equal(test['A'], default_fill_value(a['A'])) assert_equal(test['B']['BA'], default_fill_value(a['B']['BA'])) assert_equal(test['B']['BB'], default_fill_value(a['B']['BB'])) - # + test = minimum_fill_value(a) assert_equal(test[0], minimum_fill_value(a['A'])) assert_equal(test[1][0], minimum_fill_value(a['B']['BA'])) assert_equal(test[1][1], minimum_fill_value(a['B']['BB'])) assert_equal(test[1], minimum_fill_value(a['B'])) - # + test = maximum_fill_value(a) assert_equal(test[0], maximum_fill_value(a['A'])) assert_equal(test[1][0], maximum_fill_value(a['B']['BA'])) @@ -1643,13 +1660,13 @@ class TestFillingValues(TestCase): # Test adding a fill_value parameter to empty/ones/zeros a = empty(3, fill_value=999.) assert_equal(a.fill_value, 999.) - # + a = ones(3, fill_value=999., dtype=float) assert_equal(a.fill_value, 999.) - # + a = zeros(3, fill_value=0., dtype=complex) assert_equal(a.fill_value, 0.) - # + a = identity(3, fill_value=0., dtype=complex) assert_equal(a.fill_value, 0.) @@ -1696,7 +1713,6 @@ class TestFillingValues(TestCase): assert_(y.fill_value == 999999) -#------------------------------------------------------------------------------ class TestUfuncs(TestCase): # Test class for the application of ufuncs on MaskedArrays. @@ -1816,7 +1832,6 @@ class TestUfuncs(TestCase): assert_(a / me_too == "Me2rdiv") -#------------------------------------------------------------------------------ class TestMaskedArrayInPlaceArithmetics(TestCase): # Test MaskedArray Arithmetics @@ -1843,7 +1858,7 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(x, y + 1) xm += 1 assert_equal(xm, y + 1) - # + (x, _, xm) = self.floatdata id1 = x.data.ctypes._data x += 1. @@ -1934,20 +1949,20 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(xm.mask, mask_or(mask_or(m, a.mask), (a == 0))) def test_inplace_division_misc(self): - # + x = [1., 1., 1., -2., pi / 2., 4., 5., -10., 10., 1., 2., 3.] y = [5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.] m1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0] m2 = [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1] xm = masked_array(x, mask=m1) ym = masked_array(y, mask=m2) - # + z = xm / ym assert_equal(z._mask, [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1]) assert_equal(z._data, [1., 1., 1., -1., -pi / 2., 4., 5., 1., 1., 1., 2., 3.]) #assert_equal(z._data, [0.2,1.,1./3.,-1.,-pi/2.,-1.,5.,1.,1.,1.,2.,1.]) - # + xm = xm.copy() xm /= ym assert_equal(xm._mask, [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1]) @@ -2066,7 +2081,7 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(a, [[2, 2], [4, 4]]) if a.mask is not nomask: assert_equal(a.mask, [[0, 0], [0, 0]]) - # + a = array([[1, 1], [3, 3]]) b = array([1, 1], mask=[0, 1]) a += b @@ -2080,7 +2095,7 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(a, [[0, 0], [2, 2]]) if a.mask is not nomask: assert_equal(a.mask, [[0, 0], [0, 0]]) - # + a = array([[1, 1], [3, 3]]) b = array([1, 1], mask=[0, 1]) a -= b @@ -2094,7 +2109,7 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(a, [[1, 1], [3, 3]]) if a.mask is not nomask: assert_equal(a.mask, [[0, 0], [0, 0]]) - # + a = array([[1, 1], [3, 3]]) b = array([1, 1], mask=[0, 1]) a *= b @@ -2145,7 +2160,6 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(len(w), 0, "Failed on type=%s." % t) - def test_inplace_subtraction_array_type(self): # Test of inplace subtractions for t in self.othertypes: @@ -2322,7 +2336,6 @@ class TestMaskedArrayInPlaceArithmetics(TestCase): assert_equal(len(w), 0, "Failed on type=%s." % t) -#------------------------------------------------------------------------------ class TestMaskedArrayMethods(TestCase): # Test class for miscellaneous MaskedArrays methods. def setUp(self): @@ -2368,7 +2381,7 @@ class TestMaskedArrayMethods(TestCase): assert_equal(a.compress([1, 0, 1]), a._data.compress([1, 0, 1])) assert_equal(a.conj(), a._data.conj()) assert_equal(a.conjugate(), a._data.conjugate()) - # + m = array([[1, 2], [3, 4]]) assert_equal(m.diagonal(), m._data.diagonal()) assert_equal(a.sum(), a._data.sum()) @@ -2410,14 +2423,14 @@ class TestMaskedArrayMethods(TestCase): mx = masked_array(x, mask=m) mxbig = (mx > 0.5) mxsmall = (mx < 0.5) - # + self.assertFalse(mxbig.all()) self.assertTrue(mxbig.any()) assert_equal(mxbig.all(0), [False, False, True]) assert_equal(mxbig.all(1), [False, False, True]) assert_equal(mxbig.any(0), [False, False, True]) assert_equal(mxbig.any(1), [True, True, True]) - # + self.assertFalse(mxsmall.all()) self.assertTrue(mxsmall.any()) assert_equal(mxsmall.all(0), [True, True, False]) @@ -2436,14 +2449,14 @@ class TestMaskedArrayMethods(TestCase): mX = masked_array(X, mask=m) mXbig = (mX > 0.5) mXsmall = (mX < 0.5) - # + self.assertFalse(mXbig.all()) self.assertTrue(mXbig.any()) assert_equal(mXbig.all(0), np.matrix([False, False, True])) assert_equal(mXbig.all(1), np.matrix([False, False, True]).T) assert_equal(mXbig.any(0), np.matrix([False, False, True])) assert_equal(mXbig.any(1), np.matrix([True, True, True]).T) - # + self.assertFalse(mXsmall.all()) self.assertTrue(mXsmall.any()) assert_equal(mXsmall.all(0), np.matrix([True, True, False])) @@ -2455,13 +2468,13 @@ class TestMaskedArrayMethods(TestCase): # Some fun with all and any store = empty((), dtype=bool) full = array([1, 2, 3], mask=True) - # + self.assertTrue(full.all() is masked) full.all(out=store) self.assertTrue(store) self.assertTrue(store._mask, True) self.assertTrue(store is not masked) - # + store = empty((), dtype=bool) self.assertTrue(full.any() is masked) full.any(out=store) @@ -2472,7 +2485,7 @@ class TestMaskedArrayMethods(TestCase): def test_argmax_argmin(self): # Tests argmin & argmax on MaskedArrays. (x, X, XX, m, mx, mX, mXX, m2x, m2X, m2XX) = self.d - # + assert_equal(mx.argmin(), 35) assert_equal(mX.argmin(), 35) assert_equal(m2x.argmin(), 4) @@ -2481,12 +2494,12 @@ class TestMaskedArrayMethods(TestCase): assert_equal(mX.argmax(), 28) assert_equal(m2x.argmax(), 31) assert_equal(m2X.argmax(), 31) - # + assert_equal(mX.argmin(0), [2, 2, 2, 5, 0, 5]) assert_equal(m2X.argmin(0), [2, 2, 4, 5, 0, 4]) assert_equal(mX.argmax(0), [0, 5, 0, 5, 4, 0]) assert_equal(m2X.argmax(0), [5, 5, 0, 5, 1, 0]) - # + assert_equal(mX.argmin(1), [4, 1, 0, 0, 5, 5, ]) assert_equal(m2X.argmin(1), [4, 4, 0, 0, 5, 3]) assert_equal(mX.argmax(1), [2, 4, 1, 1, 4, 1]) @@ -2514,27 +2527,27 @@ class TestMaskedArrayMethods(TestCase): a = masked_array([1., 2., 3., 4., 5.], fill_value=9999) condition = (a > 1.5) & (a < 3.5) assert_equal(a.compress(condition), [2., 3.]) - # + a[[2, 3]] = masked b = a.compress(condition) assert_equal(b._data, [2., 3.]) assert_equal(b._mask, [0, 1]) assert_equal(b.fill_value, 9999) assert_equal(b, a[condition]) - # + condition = (a < 4.) b = a.compress(condition) assert_equal(b._data, [1., 2., 3.]) assert_equal(b._mask, [0, 0, 1]) assert_equal(b.fill_value, 9999) assert_equal(b, a[condition]) - # + a = masked_array([[10, 20, 30], [40, 50, 60]], mask=[[0, 0, 1], [1, 0, 0]]) b = a.compress(a.ravel() >= 22) assert_equal(b._data, [30, 40, 50, 60]) assert_equal(b._mask, [1, 1, 0, 0]) - # + x = np.array([3, 1, 2]) b = a.compress(x >= 2, axis=1) assert_equal(b._data, [[10, 30], [40, 60]]) @@ -2548,7 +2561,7 @@ class TestMaskedArrayMethods(TestCase): a[0] = masked b = a.compressed() assert_equal(b, [2, 3, 4]) - # + a = array(np.matrix([1, 2, 3, 4]), mask=[0, 0, 0, 0]) b = a.compressed() assert_equal(b, a) @@ -2563,11 +2576,11 @@ class TestMaskedArrayMethods(TestCase): a = masked_array([(1, 1.1, '1.1'), (2, 2.2, '2.2'), (3, 3.3, '3.3')], dtype=datatype) assert_equal(len(a.fill_value.item()), len(datatype)) - # + b = empty_like(a) assert_equal(b.shape, a.shape) assert_equal(b.fill_value, a.fill_value) - # + b = empty(len(a), dtype=datatype) assert_equal(b.shape, a.shape) assert_equal(b.fill_value, a.fill_value) @@ -2592,7 +2605,7 @@ class TestMaskedArrayMethods(TestCase): self.assertTrue(x[3] is masked) self.assertTrue(x[4] is not masked) assert_equal(x, [0, 10, 2, -1, 40]) - # + x = masked_array(arange(10), mask=[1, 0, 0, 0, 0] * 2) i = [0, 2, 4, 6] x.put(i, [6, 4, 2, 0]) @@ -2601,7 +2614,7 @@ class TestMaskedArrayMethods(TestCase): x.put(i, masked_array([0, 2, 4, 6], [1, 0, 1, 0])) assert_array_equal(x, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ]) assert_equal(x.mask, [1, 0, 0, 0, 1, 1, 0, 0, 0, 0]) - # + x = masked_array(arange(10), mask=[1, 0, 0, 0, 0] * 2) put(x, i, [6, 4, 2, 0]) assert_equal(x, asarray([6, 1, 4, 3, 2, 5, 0, 7, 8, 9, ])) @@ -2688,28 +2701,28 @@ class TestMaskedArrayMethods(TestCase): def test_sort(self): # Test sort x = array([1, 4, 2, 3], mask=[0, 1, 0, 0], dtype=np.uint8) - # + sortedx = sort(x) assert_equal(sortedx._data, [1, 2, 3, 4]) assert_equal(sortedx._mask, [0, 0, 0, 1]) - # + sortedx = sort(x, endwith=False) assert_equal(sortedx._data, [4, 1, 2, 3]) assert_equal(sortedx._mask, [1, 0, 0, 0]) - # + x.sort() assert_equal(x._data, [1, 2, 3, 4]) assert_equal(x._mask, [0, 0, 0, 1]) - # + x = array([1, 4, 2, 3], mask=[0, 1, 0, 0], dtype=np.uint8) x.sort(endwith=False) assert_equal(x._data, [4, 1, 2, 3]) assert_equal(x._mask, [1, 0, 0, 0]) - # + x = [1, 4, 2, 3] sortedx = sort(x) self.assertTrue(not isinstance(sorted, MaskedArray)) - # + x = array([0, 1, -1, -2, 2], mask=nomask, dtype=np.int8) sortedx = sort(x, endwith=False) assert_equal(sortedx._data, [-2, -1, 0, 1, 2]) @@ -2764,7 +2777,7 @@ class TestMaskedArrayMethods(TestCase): data=[(3, 3), (3, 2), (2, 2), (2, 1), (1, 0), (1, 1), (1, 2)], mask=[(0, 0), (0, 1), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0)], dtype=[('A', int), ('B', int)]) - # + test = sort(a) b = array( data=[(1, 1), (1, 2), (2, 1), (2, 2), (3, 3), (3, 2), (1, 0)], @@ -2772,7 +2785,7 @@ class TestMaskedArrayMethods(TestCase): dtype=[('A', int), ('B', int)]) assert_equal(test, b) assert_equal(test.mask, b.mask) - # + test = sort(a, endwith=False) b = array( data=[(1, 0), (1, 1), (1, 2), (2, 1), (2, 2), (3, 2), (3, 3), ], @@ -2812,7 +2825,7 @@ class TestMaskedArrayMethods(TestCase): 0, 0, 1, 0, 1, 0]) mX = array(x, mask=m).reshape(6, 6) mXX = mX.reshape(3, 2, 2, 3) - # + mXswapped = mX.swapaxes(0, 1) assert_equal(mXswapped[-1], mX[:, -1]) @@ -2826,7 +2839,7 @@ class TestMaskedArrayMethods(TestCase): assert_equal(x.take([0, 0, 3]), x[[0, 0, 3]]) assert_equal(x.take([[0, 1], [0, 1]]), masked_array([[10, 20], [10, 20]], [[0, 1], [0, 1]])) - # + x = array([[10, 20, 30], [40, 50, 60]], mask=[[0, 0, 1], [1, 0, 0, ]]) assert_equal(x.take([0, 2], axis=1), array([[10, 30], [40, 60]], mask=[[0, 1], [1, 0]])) @@ -2919,12 +2932,12 @@ class TestMaskedArrayMethods(TestCase): record = data.toflex() assert_equal(record['_data'], data._data) assert_equal(record['_mask'], data._mask) - # + data[[0, 1, 2, -1]] = masked record = data.toflex() assert_equal(record['_data'], data._data) assert_equal(record['_mask'], data._mask) - # + ndtype = [('i', int), ('s', '|S3'), ('f', float)] data = array([(i, s, f) for (i, s, f) in zip(np.arange(10), 'ABCDEFGHIJKLM', @@ -2934,7 +2947,7 @@ class TestMaskedArrayMethods(TestCase): record = data.toflex() assert_equal(record['_data'], data._data) assert_equal(record['_mask'], data._mask) - # + ndtype = np.dtype("int, (2,3)float, float") data = array([(i, f, ff) for (i, f, ff) in zip(np.arange(10), np.random.rand(10), @@ -2951,12 +2964,12 @@ class TestMaskedArrayMethods(TestCase): test = fromflex(a.toflex()) assert_equal(test, a) assert_equal(test.mask, a.mask) - # + a = array([1, 2, 3], mask=[0, 0, 1]) test = fromflex(a.toflex()) assert_equal(test, a) assert_equal(test.mask, a.mask) - # + a = array([(1, 1.), (2, 2.), (3, 3.)], mask=[(1, 0), (0, 0), (0, 1)], dtype=[('A', int), ('B', float)]) test = fromflex(a.toflex()) @@ -2970,11 +2983,10 @@ class TestMaskedArrayMethods(TestCase): mask=[0, 0, 1, 0, 0]) assert_equal(marray.T, control) assert_equal(marray.transpose(), control) - # + assert_equal(MaskedArray.cumsum(marray.T, 0), control.cumsum(0)) -#------------------------------------------------------------------------------ class TestMaskedArrayMathMethods(TestCase): def setUp(self): @@ -3016,7 +3028,7 @@ class TestMaskedArrayMathMethods(TestCase): assert_equal(mXcp._data, mX.filled(0).cumsum(0)) mXcp = mX.cumsum(1) assert_equal(mXcp._data, mX.filled(0).cumsum(1)) - # + mXcp = mX.cumprod(0) assert_equal(mXcp._data, mX.filled(1).cumprod(0)) mXcp = mX.cumprod(1) @@ -3026,7 +3038,7 @@ class TestMaskedArrayMathMethods(TestCase): # Tests cumsum/cumprod w/ output xm = array(np.random.uniform(0, 10, 12)).reshape(3, 4) xm[:, 0] = xm[0] = xm[-1, -1] = masked - # + for funcname in ('cumsum', 'cumprod'): npfunc = getattr(np, funcname) xmmeth = getattr(xm, funcname) @@ -3038,7 +3050,7 @@ class TestMaskedArrayMathMethods(TestCase): # ... the result should be the given output self.assertTrue(result is output) assert_equal(result, xmmeth(axis=0, out=output)) - # + output = empty((3, 4), dtype=int) result = xmmeth(axis=0, out=output) self.assertTrue(result is output) @@ -3058,7 +3070,7 @@ class TestMaskedArrayMathMethods(TestCase): assert_equal(mX.ptp(1), rows) def test_add_object(self): - x = masked_array(['a', 'b'], mask = [1, 0], dtype=object) + x = masked_array(['a', 'b'], mask=[1, 0], dtype=object) y = x + 'x' assert_equal(y[1], 'bx') assert_(y.mask[0]) @@ -3142,7 +3154,7 @@ class TestMaskedArrayMathMethods(TestCase): # Test a special case for var nout = np.array(-1, dtype=float) mout = array(-1, dtype=float) - # + x = array(arange(10), mask=True) for methodname in ('var', 'std'): method = getattr(x, methodname) @@ -3152,15 +3164,15 @@ class TestMaskedArrayMathMethods(TestCase): # Using a masked array as explicit output with warnings.catch_warnings(): warnings.simplefilter('ignore') - _ = method(out=mout) + method(out=mout) self.assertTrue(mout is not masked) assert_equal(mout.mask, True) # Using a ndarray as explicit output with warnings.catch_warnings(): warnings.simplefilter('ignore') - _ = method(out=nout) + method(out=nout) self.assertTrue(np.isnan(nout)) - # + x = array(arange(10), mask=True) x[-1] = 9 for methodname in ('var', 'std'): @@ -3205,25 +3217,24 @@ class TestMaskedArrayMathMethods(TestCase): def test_axis_methods_nomask(self): # Test the combination nomask & methods w/ axis a = array([[1, 2, 3], [4, 5, 6]]) - # + assert_equal(a.sum(0), [5, 7, 9]) assert_equal(a.sum(-1), [6, 15]) assert_equal(a.sum(1), [6, 15]) - # + assert_equal(a.prod(0), [4, 10, 18]) assert_equal(a.prod(-1), [6, 120]) assert_equal(a.prod(1), [6, 120]) - # + assert_equal(a.min(0), [1, 2, 3]) assert_equal(a.min(-1), [1, 4]) assert_equal(a.min(1), [1, 4]) - # + assert_equal(a.max(0), [4, 5, 6]) assert_equal(a.max(-1), [3, 6]) assert_equal(a.max(1), [3, 6]) -#------------------------------------------------------------------------------ class TestMaskedArrayMathMethodsComplex(TestCase): # Test class for miscellaneous MaskedArrays methods. def setUp(self): @@ -3277,7 +3288,6 @@ class TestMaskedArrayMathMethodsComplex(TestCase): mX[:, k].compressed().std()) -#------------------------------------------------------------------------------ class TestMaskedArrayFunctions(TestCase): # Test class for miscellaneous functions. @@ -3350,7 +3360,7 @@ class TestMaskedArrayFunctions(TestCase): # test that masked_where on a structured array sets a structured # mask (see issue #2972) a = np.zeros(10, dtype=[("A", "<f2"), ("B", "<f4")]) - am = np.ma.masked_where(a["A"]<5, a) + am = np.ma.masked_where(a["A"] < 5, a) assert_equal(am.mask.dtype.names, am.dtype.names) assert_equal(am["A"], np.ma.masked_array(np.zeros(10), np.ones(10))) @@ -3407,7 +3417,7 @@ class TestMaskedArrayFunctions(TestCase): # ... the result should be the given output self.assertTrue(result is output) assert_equal(result, xm.round(decimals=2, out=output)) - # + output = empty((3, 4), dtype=float) result = xm.round(decimals=2, out=output) self.assertTrue(result is output) @@ -3445,7 +3455,7 @@ class TestMaskedArrayFunctions(TestCase): b1 = np.array([2, 4, 3]) b2 = np.array([b1, b1]) b2m = array(b2, mask=[[0, 1, 0], [0, 1, 0]]) - # + ctrl = array([[1 ** 2, 2 ** 4, 3 ** 3], [4 ** 2, 5 ** 4, 6 ** 3]], mask=[[1, 1, 0], [0, 1, 1]]) # No broadcasting, base & exp w/ mask @@ -3460,7 +3470,7 @@ class TestMaskedArrayFunctions(TestCase): test = a2 ** b2m assert_equal(test, ctrl) assert_equal(test.mask, b2m.mask) - # + ctrl = array([[2 ** 2, 4 ** 4, 3 ** 3], [2 ** 2, 4 ** 4, 3 ** 3]], mask=[[0, 1, 0], [0, 1, 0]]) test = b1 ** b2m @@ -3479,7 +3489,7 @@ class TestMaskedArrayFunctions(TestCase): xm = masked_array(x, mask=m1) ym = masked_array(y, mask=m2) xm.set_fill_value(1e+20) - # + d = where(xm > 2, xm, -9) assert_equal(d, [-9., -9., -9., -9., -9., 4., -9., -9., 10., -9., -9., 3.]) @@ -3494,7 +3504,7 @@ class TestMaskedArrayFunctions(TestCase): tmp = xm._mask.copy() tmp[(xm <= 2).filled(True)] = True assert_equal(d._mask, tmp) - # + ixm = xm.astype(int) d = where(ixm > 2, ixm, masked) assert_equal(d, [-9, -9, -9, -9, -9, 4, -9, -9, 10, -9, -9, 3]) @@ -3541,7 +3551,7 @@ class TestMaskedArrayFunctions(TestCase): assert_(z[0] is masked) assert_(z[1] is not masked) assert_(z[2] is masked) - # + x = arange(1, 6) x[-1] = masked y = arange(1, 6) * 10 @@ -3630,7 +3640,7 @@ class TestMaskedArrayFunctions(TestCase): b = a.reshape(5, 2, order='F') assert_equal(b.shape, (5, 2)) self.assertTrue(b.flags['F']) - # + c = np.reshape(a, (2, 5)) self.assertTrue(isinstance(c, MaskedArray)) assert_equal(c.shape, (2, 5)) @@ -3778,32 +3788,39 @@ class TestMaskedArrayFunctions(TestCase): a = np.ma.array([1, 2]) test = np.ma.compressed(a) assert_(type(test) is np.ndarray) + # Test case when input data is ndarray subclass class A(np.ndarray): pass + a = np.ma.array(A(shape=0)) test = np.ma.compressed(a) assert_(type(test) is A) + # Test that compress flattens test = np.ma.compressed([[1],[2]]) assert_equal(test.ndim, 1) test = np.ma.compressed([[[[[1]]]]]) assert_equal(test.ndim, 1) + # Test case when input is MaskedArray subclass class M(MaskedArray): pass + test = np.ma.compressed(M(shape=(0,1,2))) assert_equal(test.ndim, 1) + # with .compessed() overriden class M(MaskedArray): def compressed(self): return 42 + test = np.ma.compressed(M(shape=(0,1,2))) assert_equal(test, 42) -#------------------------------------------------------------------------------ + class TestMaskedFields(TestCase): - # + def setUp(self): ilist = [1, 2, 3, 4, 5] flist = [1.1, 2.2, 3.3, 4.4, 5.5] @@ -3867,9 +3884,8 @@ class TestMaskedFields(TestCase): def test_mask_element(self): "Check record access" base = self.data['base'] - (base_a, base_b, base_c) = (base['a'], base['b'], base['c']) base[0] = masked - # + for n in ('a', 'b', 'c'): assert_equal(base[n].mask, [1, 1, 0, 0, 1]) assert_equal(base[n]._data, base._data[n]) @@ -3901,7 +3917,7 @@ class TestMaskedFields(TestCase): test = a.view((float, 2)) assert_equal(test, data) assert_equal(test.mask, controlmask.reshape(-1, 2)) - # + test = a.view((float, 2), np.matrix) assert_equal(test, data) self.assertTrue(isinstance(test, np.matrix)) @@ -3959,9 +3975,8 @@ class TestMaskedFields(TestCase): assert_equal(len(rec), len(self.data['ddtype'])) -#------------------------------------------------------------------------------ class TestMaskedView(TestCase): - # + def setUp(self): iterator = list(zip(np.arange(10), np.random.rand(10))) data = np.array(iterator) @@ -3994,18 +4009,18 @@ class TestMaskedView(TestCase): def test_view_to_flexible_dtype(self): (data, a, controlmask) = self.data - # + test = a.view([('A', float), ('B', float)]) assert_equal(test.mask.dtype.names, ('A', 'B')) assert_equal(test['A'], a['a']) assert_equal(test['B'], a['b']) - # + test = a[0].view([('A', float), ('B', float)]) self.assertTrue(isinstance(test, MaskedArray)) assert_equal(test.mask.dtype.names, ('A', 'B')) assert_equal(test['A'], a['a'][0]) assert_equal(test['B'], a['b'][0]) - # + test = a[-1].view([('A', float), ('B', float)]) self.assertTrue(isinstance(test, MaskedArray)) assert_equal(test.dtype.names, ('A', 'B')) @@ -4031,7 +4046,7 @@ class TestMaskedView(TestCase): def test_view_to_dtype_and_type(self): (data, a, controlmask) = self.data - # + test = a.view((float, 2), np.matrix) assert_equal(test, data) self.assertTrue(isinstance(test, np.matrix)) @@ -4081,6 +4096,5 @@ def test_append_masked_array_along_axis(): assert_array_equal(result.mask, expected.mask) -############################################################################### if __name__ == "__main__": run_module_suite() diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py index 3c7b95c9e..b6d902995 100644 --- a/numpy/ma/tests/test_extras.py +++ b/numpy/ma/tests/test_extras.py @@ -9,30 +9,27 @@ Adapted from the original test_ma by Pierre Gerard-Marchant """ from __future__ import division, absolute_import, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' - import warnings import numpy as np -from numpy.testing import (TestCase, run_module_suite, assert_warns, - assert_raises, clear_and_catch_warnings) -from numpy.ma.testutils import (rand, assert_, assert_array_equal, - assert_equal, assert_almost_equal) -from numpy.ma.core import (array, arange, masked, MaskedArray, masked_array, - getmaskarray, shape, nomask, ones, zeros, count) -import numpy.ma.extras as mae +from numpy.testing import ( + TestCase, run_module_suite, assert_warns, clear_and_catch_warnings + ) +from numpy.ma.testutils import ( + assert_, assert_array_equal, assert_equal, assert_almost_equal + ) +from numpy.ma.core import ( + array, arange, masked, MaskedArray, masked_array, getmaskarray, shape, + nomask, ones, zeros, count + ) from numpy.ma.extras import ( - atleast_2d, mr_, dot, polyfit, - cov, corrcoef, median, average, - unique, setxor1d, setdiff1d, union1d, intersect1d, in1d, ediff1d, - apply_over_axes, apply_along_axis, - compress_nd, compress_rowcols, mask_rowcols, - clump_masked, clump_unmasked, - flatnotmasked_contiguous, notmasked_contiguous, notmasked_edges, - masked_all, masked_all_like) + atleast_2d, mr_, dot, polyfit, cov, corrcoef, median, average, unique, + setxor1d, setdiff1d, union1d, intersect1d, in1d, ediff1d, + apply_over_axes, apply_along_axis, compress_nd, compress_rowcols, + mask_rowcols, clump_masked, clump_unmasked, flatnotmasked_contiguous, + notmasked_contiguous, notmasked_edges, masked_all, masked_all_like + ) +import numpy.ma.extras as mae class TestGeneric(TestCase): @@ -267,10 +264,10 @@ class TestConcatenator(TestCase): def test_2d(self): # Tests mr_ on 2D arrays. - a_1 = rand(5, 5) - a_2 = rand(5, 5) - m_1 = np.round_(rand(5, 5), 0) - m_2 = np.round_(rand(5, 5), 0) + a_1 = np.random.rand(5, 5) + a_2 = np.random.rand(5, 5) + m_1 = np.round_(np.random.rand(5, 5), 0) + m_2 = np.round_(np.random.rand(5, 5), 0) b_1 = masked_array(a_1, mask=m_1) b_2 = masked_array(a_2, mask=m_2) # append columns @@ -358,13 +355,13 @@ class TestCompressFunctions(TestCase): # axis=None a = compress_nd(x) - assert_equal(a, [[[ 0, 2, 3 , 4], + assert_equal(a, [[[ 0, 2, 3, 4], [10, 12, 13, 14], [15, 17, 18, 19]], [[40, 42, 43, 44], [50, 52, 53, 54], [55, 57, 58, 59]]]) - + # axis=0 a = compress_nd(x, 0) assert_equal(a, [[[ 0, 1, 2, 3, 4], @@ -449,8 +446,8 @@ class TestCompressFunctions(TestCase): # axis=(0, 2) a = compress_nd(x, (0, 2)) - assert_equal(a, [[[ 0, 2, 3, 4], - [ 5, 7, 8, 9], + assert_equal(a, [[[ 0, 2, 3, 4], + [ 5, 7, 8, 9], [10, 12, 13, 14], [15, 17, 18, 19]], [[40, 42, 43, 44], @@ -595,7 +592,7 @@ class TestApplyAlongAxis(TestCase): xa = apply_along_axis(myfunc, 2, a) assert_equal(xa, [[1, 4], [7, 10]]) - # Tests kwargs functions + # Tests kwargs functions def test_3d_kwargs(self): a = arange(12).reshape(2, 2, 3) @@ -1120,7 +1117,7 @@ class TestArraySetOps(TestCase): class TestShapeBase(TestCase): - # + def test_atleast2d(self): # Test atleast_2d a = masked_array([0, 1, 2], mask=[0, 1, 0]) @@ -1131,7 +1128,5 @@ class TestShapeBase(TestCase): assert_equal(a.mask.shape, a.data.shape) -############################################################################### -#------------------------------------------------------------------------------ if __name__ == "__main__": run_module_suite() diff --git a/numpy/ma/tests/test_mrecords.py b/numpy/ma/tests/test_mrecords.py index 54945e8f0..84b68ba0f 100644 --- a/numpy/ma/tests/test_mrecords.py +++ b/numpy/ma/tests/test_mrecords.py @@ -13,22 +13,22 @@ import pickle import numpy as np import numpy.ma as ma from numpy import recarray -from numpy.core.records import (fromrecords as recfromrecords, - fromarrays as recfromarrays) - from numpy.compat import asbytes, asbytes_nested -from numpy.ma.testutils import * from numpy.ma import masked, nomask -from numpy.ma.mrecords import (MaskedRecords, mrecarray, fromarrays, - fromtextfile, fromrecords, addfield) - - -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' +from numpy.testing import TestCase, run_module_suite +from numpy.core.records import ( + fromrecords as recfromrecords, fromarrays as recfromarrays + ) +from numpy.ma.mrecords import ( + MaskedRecords, mrecarray, fromarrays, fromtextfile, fromrecords, + addfield + ) +from numpy.ma.testutils import ( + assert_, assert_equal, + assert_equal_records, + ) -#.............................................................................. class TestMRecords(TestCase): # Base test class for MaskedArrays. def __init__(self, *args, **kwds): @@ -147,7 +147,7 @@ class TestMRecords(TestCase): data = ma.array([('a', 1), ('b', 2), ('c', 3)], dtype=ndtype) rdata = data.view(MaskedRecords) val = ma.array([10, 20, 30], mask=[1, 0, 0]) - # + with warnings.catch_warnings(): warnings.simplefilter("ignore") rdata['num'] = val @@ -201,7 +201,7 @@ class TestMRecords(TestCase): def test_set_mask_fromfields(self): mbase = self.base.copy().view(mrecarray) - # + nmask = np.array( [(0, 1, 0), (0, 1, 0), (1, 0, 1), (1, 0, 1), (0, 0, 0)], dtype=[('a', bool), ('b', bool), ('c', bool)]) @@ -237,7 +237,7 @@ class TestMRecords(TestCase): assert_equal(mbase.c._data, asbytes_nested(['5', '5', 'three', 'four', 'five'])) assert_equal(mbase.b._mask, [0, 0, 0, 0, 1]) - # + mbase = base.view(mrecarray).copy() mbase[:2] = masked assert_equal(mbase.a._data, [1, 2, 3, 4, 5]) @@ -328,7 +328,7 @@ class TestMRecords(TestCase): ddtype = [('a', int), ('b', float), ('c', '|S8')] mrec = fromarrays([_a, _b, _c], dtype=ddtype, fill_value=(99999, 99999., 'N/A')) - # + assert_equal(mrec.tolist(), [(1, 1.1, None), (2, 2.2, asbytes('two')), (None, None, asbytes('three'))]) @@ -344,12 +344,12 @@ class TestMRecords(TestCase): easy = mrecarray(1, dtype=[('i', int), ('s', '|S8'), ('f', float)]) easy[0] = masked assert_equal(easy.filled(1).item(), (1, asbytes('1'), 1.)) - # + solo = mrecarray(1, dtype=[('f0', '<f8', (2, 2))]) solo[0] = masked assert_equal(solo.filled(1).item(), np.array((1,), dtype=solo.dtype).item()) - # + mult = mrecarray(2, dtype="i4, (2,3)float, float") mult[0] = masked mult[1] = (1, 1, 1) @@ -360,7 +360,7 @@ class TestMRecords(TestCase): class TestView(TestCase): - # + def setUp(self): (a, b) = (np.arange(10), np.random.rand(10)) ndtype = [('a', np.float), ('b', np.float)] @@ -396,7 +396,7 @@ class TestView(TestCase): self.assertTrue(test._fill_value is None) -############################################################################### +############################################################################## class TestMRecordsImport(TestCase): # Base test class for MaskedArrays. def __init__(self, *args, **kwds): @@ -442,12 +442,12 @@ class TestMRecordsImport(TestCase): assert_equal(_mrec.dtype, mrec.dtype) for field in _mrec.dtype.names: assert_equal(getattr(_mrec, field), getattr(mrec._data, field)) - # + _mrec = fromrecords(nrec.tolist(), names='c1,c2,c3') assert_equal(_mrec.dtype, [('c1', int), ('c2', float), ('c3', '|S5')]) for (f, n) in zip(('c1', 'c2', 'c3'), ('a', 'b', 'c')): assert_equal(getattr(_mrec, f), getattr(mrec._data, n)) - # + _mrec = fromrecords(mrec) assert_equal(_mrec.dtype, mrec.dtype) assert_equal_records(_mrec._data, mrec.filled()) @@ -456,19 +456,19 @@ class TestMRecordsImport(TestCase): def test_fromrecords_wmask(self): # Tests construction from records w/ mask. (mrec, nrec, ddtype) = self.data - # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=[0, 1, 0,]) assert_equal_records(_mrec._data, mrec._data) assert_equal(_mrec._mask.tolist(), [(0, 0, 0), (1, 1, 1), (0, 0, 0)]) - # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=True) assert_equal_records(_mrec._data, mrec._data) assert_equal(_mrec._mask.tolist(), [(1, 1, 1), (1, 1, 1), (1, 1, 1)]) - # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._mask) assert_equal_records(_mrec._data, mrec._data) assert_equal(_mrec._mask.tolist(), mrec._mask.tolist()) - # + _mrec = fromrecords(nrec.tolist(), dtype=ddtype, mask=mrec._mask.tolist()) assert_equal_records(_mrec._data, mrec._data) @@ -476,7 +476,8 @@ class TestMRecordsImport(TestCase): def test_fromtextfile(self): # Tests reading from a text file. - fcontent = asbytes("""# + fcontent = asbytes( +"""# 'One (S)','Two (I)','Three (F)','Four (M)','Five (-)','Six (C)' 'strings',1,1.0,'mixed column',,1 'with embedded "double quotes"',2,2.0,1.0,,1 @@ -490,7 +491,7 @@ class TestMRecordsImport(TestCase): os.close(tmp_fd) mrectxt = fromtextfile(tmp_fl, delimitor=',', varnames='ABCDEFG') os.remove(tmp_fl) - # + self.assertTrue(isinstance(mrectxt, MaskedRecords)) assert_equal(mrectxt.F, [1, 1, 1, 1]) assert_equal(mrectxt.E._mask, [1, 1, 1, 1]) @@ -515,7 +516,5 @@ def test_record_array_with_object_field(): y[1] -############################################################################### -#------------------------------------------------------------------------------ if __name__ == "__main__": run_module_suite() diff --git a/numpy/ma/tests/test_old_ma.py b/numpy/ma/tests/test_old_ma.py index 047f91c77..a32f358c0 100644 --- a/numpy/ma/tests/test_old_ma.py +++ b/numpy/ma/tests/test_old_ma.py @@ -1,13 +1,25 @@ from __future__ import division, absolute_import, print_function -import sys from functools import reduce import numpy as np -from numpy.ma import * -from numpy.core.numerictypes import float32 -from numpy.ma.core import umath -from numpy.testing import * +import numpy.core.umath as umath +import numpy.core.fromnumeric as fromnumeric +from numpy.testing import TestCase, run_module_suite, assert_ +from numpy.ma.testutils import assert_array_equal +from numpy.ma import ( + MaskType, MaskedArray, absolute, add, all, allclose, allequal, alltrue, + arange, arccos, arcsin, arctan, arctan2, array, average, choose, + concatenate, conjugate, cos, cosh, count, divide, equal, exp, filled, + getmask, greater, greater_equal, inner, isMaskedArray, less, + less_equal, log, log10, make_mask, masked, masked_array, masked_equal, + masked_greater, masked_greater_equal, masked_inside, masked_less, + masked_less_equal, masked_not_equal, masked_outside, + masked_print_option, masked_values, masked_where, maximum, minimum, + multiply, nomask, nonzero, not_equal, ones, outer, product, put, ravel, + repeat, resize, shape, sin, sinh, sometrue, sort, sqrt, subtract, sum, + take, tan, tanh, transpose, where, zeros, + ) pi = np.pi @@ -15,10 +27,7 @@ pi = np.pi def eq(v, w, msg=''): result = allclose(v, w) if not result: - print("""Not eq:%s -%s ----- -%s""" % (msg, str(v), str(w))) + print("Not eq:%s\n%s\n----%s" % (msg, str(v), str(w))) return result @@ -202,10 +211,11 @@ class TestMa(TestCase): x2 = array(x1, mask=[1, 0, 0, 0]) x3 = array(x1, mask=[0, 1, 0, 1]) x4 = array(x1) - # test conversion to strings - junk, garbage = str(x2), repr(x2) + # test conversion to strings + str(x2) # raises? + repr(x2) # raises? assert_(eq(np.sort(x1), sort(x2, fill_value=0))) - # tests of indexing + # tests of indexing assert_(type(x2[1]) is type(x1[1])) assert_(x1[1] == x2[1]) assert_(x2[0] is masked) @@ -387,7 +397,7 @@ class TestMa(TestCase): [1, 0, 1, 0, 1])) assert_(eq(masked_where([1, 1, 0, 0, 0], [1, 2, 3, 4, 5]), [99, 99, 3, 4, 5])) - atest = ones((10, 10, 10), dtype=float32) + atest = ones((10, 10, 10), dtype=np.float32) btest = zeros(atest.shape, MaskType) ctest = masked_where(btest, atest) assert_(eq(atest, ctest)) @@ -489,7 +499,7 @@ class TestMa(TestCase): xm /= arange(10) assert_(eq(xm, ones((10,)))) - x = arange(10).astype(float32) + x = arange(10).astype(np.float32) xm = arange(10) xm[2] = masked x += 1. diff --git a/numpy/ma/tests/test_subclassing.py b/numpy/ma/tests/test_subclassing.py index 2e98348e6..68734425c 100644 --- a/numpy/ma/tests/test_subclassing.py +++ b/numpy/ma/tests/test_subclassing.py @@ -8,15 +8,14 @@ """ from __future__ import division, absolute_import, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = '1.0' -__revision__ = "$Revision: 3473 $" -__date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $' - import numpy as np -from numpy.testing import * -from numpy.ma.testutils import * -from numpy.ma.core import * +from numpy.testing import TestCase, run_module_suite, assert_raises +from numpy.ma.testutils import assert_equal +from numpy.ma.core import ( + array, arange, masked, MaskedArray, masked_array, log, add, hypot, + divide, asarray, asanyarray, nomask + ) +# from numpy.ma.core import ( class SubArray(np.ndarray): diff --git a/numpy/ma/testutils.py b/numpy/ma/testutils.py index feff3e879..8dc821878 100644 --- a/numpy/ma/testutils.py +++ b/numpy/ma/testutils.py @@ -7,32 +7,48 @@ """ from __future__ import division, absolute_import, print_function -__author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)" -__version__ = "1.0" -__revision__ = "$Revision: 3529 $" -__date__ = "$Date: 2007-11-13 10:01:14 +0200 (Tue, 13 Nov 2007) $" - - import operator import numpy as np from numpy import ndarray, float_ import numpy.core.umath as umath -from numpy.testing import * +from numpy.testing import ( + TestCase, assert_, assert_allclose, assert_array_almost_equal_nulp, + assert_raises, build_err_msg, run_module_suite, + ) import numpy.testing.utils as utils +from .core import mask_or, getmask, masked_array, nomask, masked, filled + +__all__masked = [ + 'almost', 'approx', 'assert_almost_equal', 'assert_array_almost_equal', + 'assert_array_approx_equal', 'assert_array_compare', + 'assert_array_equal', 'assert_array_less', 'assert_close', + 'assert_equal', 'assert_equal_records', 'assert_mask_equal', + 'assert_not_equal', 'fail_if_array_equal', + ] + +# Include some normal test functions to avoid breaking other projects who +# have mistakenly included them from this file. SciPy is one. That is +# unfortunate, as some of these functions are not intended to work with +# masked arrays. But there was no way to tell before. +__some__from_testing = [ + 'TestCase', 'assert_', 'assert_allclose', + 'assert_array_almost_equal_nulp', 'assert_raises', 'run_module_suite', + ] -from .core import mask_or, getmask, masked_array, nomask, masked, filled, \ - equal, less +__all__ = __all__masked + __some__from_testing + + +def approx(a, b, fill_value=True, rtol=1e-5, atol=1e-8): + """ + Returns true if all components of a and b are equal to given tolerances. -#------------------------------------------------------------------------------ -def approx (a, b, fill_value=True, rtol=1e-5, atol=1e-8): - """Returns true if all components of a and b are equal subject to given tolerances. + If fill_value is True, masked values considered equal. Otherwise, + masked values are considered unequal. The relative error rtol should + be positive and << 1.0 The absolute error atol comes into play for + those elements of b that are very small or zero; it says how small a + must be also. -If fill_value is True, masked values considered equal. Otherwise, masked values -are considered unequal. -The relative error rtol should be positive and << 1.0 -The absolute error atol comes into play for those elements of b that are very -small or zero; it says how small a must be also. """ m = mask_or(getmask(a), getmask(b)) d1 = filled(a) @@ -46,9 +62,12 @@ small or zero; it says how small a must be also. def almost(a, b, decimal=6, fill_value=True): - """Returns True if a and b are equal up to decimal places. -If fill_value is True, masked values considered equal. Otherwise, masked values -are considered unequal. + """ + Returns True if a and b are equal up to decimal places. + + If fill_value is True, masked values considered equal. Otherwise, + masked values are considered unequal. + """ m = mask_or(getmask(a), getmask(b)) d1 = filled(a) @@ -61,16 +80,24 @@ are considered unequal. return d.ravel() -#................................................ def _assert_equal_on_sequences(actual, desired, err_msg=''): - "Asserts the equality of two non-array sequences." + """ + Asserts the equality of two non-array sequences. + + """ assert_equal(len(actual), len(desired), err_msg) for k in range(len(desired)): assert_equal(actual[k], desired[k], 'item=%r\n%s' % (k, err_msg)) return + def assert_equal_records(a, b): - """Asserts that two records are equal. Pretty crude for now.""" + """ + Asserts that two records are equal. + + Pretty crude for now. + + """ assert_equal(a.dtype, b.dtype) for f in a.dtype.names: (af, bf) = (operator.getitem(a, f), operator.getitem(b, f)) @@ -80,14 +107,17 @@ def assert_equal_records(a, b): def assert_equal(actual, desired, err_msg=''): - "Asserts that two items are equal." + """ + Asserts that two items are equal. + + """ # Case #1: dictionary ..... if isinstance(desired, dict): if not isinstance(actual, dict): raise AssertionError(repr(type(actual))) assert_equal(len(actual), len(desired), err_msg) for k, i in desired.items(): - if not k in actual: + if k not in actual: raise AssertionError("%s not in %s" % (k, actual)) assert_equal(actual[k], desired[k], 'key=%r\n%s' % (k, err_msg)) return @@ -101,7 +131,7 @@ def assert_equal(actual, desired, err_msg=''): return # Case #4. arrays or equivalent if ((actual is masked) and not (desired is masked)) or \ - ((desired is masked) and not (actual is masked)): + ((desired is masked) and not (actual is masked)): msg = build_err_msg([actual, desired], err_msg, header='', names=('x', 'y')) raise ValueError(msg) @@ -112,26 +142,20 @@ def assert_equal(actual, desired, err_msg=''): return _assert_equal_on_sequences(actual.tolist(), desired.tolist(), err_msg='') -# elif actual_dtype.char in "OV" and desired_dtype.char in "OV": -# if (actual_dtype != desired_dtype) and actual_dtype: -# msg = build_err_msg([actual_dtype, desired_dtype], -# err_msg, header='', names=('actual', 'desired')) -# raise ValueError(msg) -# return _assert_equal_on_sequences(actual.tolist(), -# desired.tolist(), -# err_msg='') return assert_array_equal(actual, desired, err_msg) def fail_if_equal(actual, desired, err_msg='',): - """Raises an assertion error if two items are equal. + """ + Raises an assertion error if two items are equal. + """ if isinstance(desired, dict): if not isinstance(actual, dict): raise AssertionError(repr(type(actual))) fail_if_equal(len(actual), len(desired), err_msg) for k, i in desired.items(): - if not k in actual: + if k not in actual: raise AssertionError(repr(k)) fail_if_equal(actual[k], desired[k], 'key=%r\n%s' % (k, err_msg)) return @@ -146,12 +170,16 @@ def fail_if_equal(actual, desired, err_msg='',): if not desired != actual: raise AssertionError(msg) + assert_not_equal = fail_if_equal def assert_almost_equal(actual, desired, decimal=7, err_msg='', verbose=True): - """Asserts that two items are almost equal. - The test is equivalent to abs(desired-actual) < 0.5 * 10**(-decimal) + """ + Asserts that two items are almost equal. + + The test is equivalent to abs(desired-actual) < 0.5 * 10**(-decimal). + """ if isinstance(actual, np.ndarray) or isinstance(desired, np.ndarray): return assert_array_almost_equal(actual, desired, decimal=decimal, @@ -167,17 +195,18 @@ assert_close = assert_almost_equal def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='', fill_value=True): - """Asserts that a comparison relation between two masked arrays is satisfied - elementwise.""" - # Fill the data first -# xf = filled(x) -# yf = filled(y) + """ + Asserts that comparison between two masked arrays is satisfied. + + The comparison is elementwise. + + """ # Allocate a common mask and refill m = mask_or(getmask(x), getmask(y)) x = masked_array(x, copy=False, mask=m, keep_mask=False, subok=False) y = masked_array(y, copy=False, mask=m, keep_mask=False, subok=False) if ((x is masked) and not (y is masked)) or \ - ((y is masked) and not (x is masked)): + ((y is masked) and not (x is masked)): msg = build_err_msg([x, y], err_msg=err_msg, verbose=verbose, header=header, names=('x', 'y')) raise ValueError(msg) @@ -190,14 +219,20 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='', def assert_array_equal(x, y, err_msg='', verbose=True): - """Checks the elementwise equality of two masked arrays.""" + """ + Checks the elementwise equality of two masked arrays. + + """ assert_array_compare(operator.__eq__, x, y, err_msg=err_msg, verbose=verbose, header='Arrays are not equal') def fail_if_array_equal(x, y, err_msg='', verbose=True): - "Raises an assertion error if two masked arrays are not equal (elementwise)." + """ + Raises an assertion error if two masked arrays are not equal elementwise. + + """ def compare(x, y): return (not np.alltrue(approx(x, y))) assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose, @@ -205,8 +240,12 @@ def fail_if_array_equal(x, y, err_msg='', verbose=True): def assert_array_approx_equal(x, y, decimal=6, err_msg='', verbose=True): - """Checks the elementwise equality of two masked arrays, up to a given - number of decimals.""" + """ + Checks the equality of two masked arrays, up to given number odecimals. + + The equality is checked elementwise. + + """ def compare(x, y): "Returns the result of the loose comparison between x and y)." return approx(x, y, rtol=10. ** -decimal) @@ -215,8 +254,12 @@ def assert_array_approx_equal(x, y, decimal=6, err_msg='', verbose=True): def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): - """Checks the elementwise equality of two masked arrays, up to a given - number of decimals.""" + """ + Checks the equality of two masked arrays, up to given number odecimals. + + The equality is checked elementwise. + + """ def compare(x, y): "Returns the result of the loose comparison between x and y)." return almost(x, y, decimal) @@ -225,14 +268,20 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): def assert_array_less(x, y, err_msg='', verbose=True): - "Checks that x is smaller than y elementwise." + """ + Checks that x is smaller than y elementwise. + + """ assert_array_compare(operator.__lt__, x, y, err_msg=err_msg, verbose=verbose, header='Arrays are not less-ordered') def assert_mask_equal(m1, m2, err_msg=''): - """Asserts the equality of two masks.""" + """ + Asserts the equality of two masks. + + """ if m1 is nomask: assert_(m2 is nomask) if m2 is nomask: diff --git a/numpy/ma/timer_comparison.py b/numpy/ma/timer_comparison.py index b1c056cfc..d03080f47 100644 --- a/numpy/ma/timer_comparison.py +++ b/numpy/ma/timer_comparison.py @@ -15,13 +15,12 @@ np.seterr(all='ignore') pi = np.pi -class moduletester(object): +class ModuleTester(object): def __init__(self, module): self.module = module self.allequal = module.allequal self.arange = module.arange self.array = module.array -# self.average = module.average self.concatenate = module.concatenate self.count = module.count self.equal = module.equal @@ -53,8 +52,10 @@ class moduletester(object): def assert_array_compare(self, comparison, x, y, err_msg='', header='', fill_value=True): - """Asserts that a comparison relation between two masked arrays is satisfied - elementwise.""" + """ + Assert that a comparison of two masked arrays is satisfied elementwise. + + """ xf = self.filled(x) yf = self.filled(y) m = self.mask_or(self.getmask(x), self.getmask(y)) @@ -74,7 +75,7 @@ class moduletester(object): elif np.isnan(y): y = 0 try: - cond = (x.shape==() or y.shape==()) or x.shape == y.shape + cond = (x.shape == () or y.shape == ()) or x.shape == y.shape if not cond: msg = build_err_msg([x, y], err_msg @@ -106,33 +107,38 @@ class moduletester(object): raise ValueError(msg) def assert_array_equal(self, x, y, err_msg=''): - """Checks the elementwise equality of two masked arrays.""" + """ + Checks the elementwise equality of two masked arrays. + + """ self.assert_array_compare(self.equal, x, y, err_msg=err_msg, header='Arrays are not equal') def test_0(self): - "Tests creation" + """ + Tests creation + + """ x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.]) m = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0] xm = self.masked_array(x, mask=m) xm[0] def test_1(self): - "Tests creation" + """ + Tests creation + + """ x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.]) y = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.]) - a10 = 10. m1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0] m2 = [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1] xm = self.masked_array(x, mask=m1) ym = self.masked_array(y, mask=m2) - z = np.array([-.5, 0., .5, .8]) - zm = self.masked_array(z, mask=[0, 1, 0, 0]) xf = np.where(m1, 1.e+20, x) xm.set_fill_value(1.e+20) assert((xm-ym).filled(0).any()) - #fail_if_equal(xm.mask.astype(int_), ym.mask.astype(int_)) s = x.shape assert(xm.size == reduce(lambda x, y:x*y, s)) assert(self.count(xm) == len(m1) - reduce(lambda x, y:x+y, m1)) @@ -143,51 +149,41 @@ class moduletester(object): xm.shape = s ym.shape = s xf.shape = s - assert(self.count(xm) == len(m1) - reduce(lambda x, y:x+y, m1)) def test_2(self): - "Tests conversions and indexing" + """ + Tests conversions and indexing. + + """ x1 = np.array([1, 2, 4, 3]) x2 = self.array(x1, mask=[1, 0, 0, 0]) x3 = self.array(x1, mask=[0, 1, 0, 1]) x4 = self.array(x1) - # test conversion to strings - junk, garbage = str(x2), repr(x2) -# assert_equal(np.sort(x1), self.sort(x2, fill_value=0)) - # tests of indexing + # test conversion to strings, no errors + str(x2) + repr(x2) + # tests of indexing assert type(x2[1]) is type(x1[1]) assert x1[1] == x2[1] -# assert self.allequal(x1[2],x2[2]) -# assert self.allequal(x1[2:5],x2[2:5]) -# assert self.allequal(x1[:],x2[:]) -# assert self.allequal(x1[1:], x3[1:]) x1[2] = 9 x2[2] = 9 self.assert_array_equal(x1, x2) x1[1:3] = 99 x2[1:3] = 99 -# assert self.allequal(x1,x2) x2[1] = self.masked -# assert self.allequal(x1,x2) x2[1:3] = self.masked -# assert self.allequal(x1,x2) x2[:] = x1 x2[1] = self.masked -# assert self.allequal(self.getmask(x2),self.array([0,1,0,0])) x3[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0]) -# assert self.allequal(self.getmask(x3), self.array([0,1,1,0])) x4[:] = self.masked_array([1, 2, 3, 4], [0, 1, 1, 0]) -# assert self.allequal(self.getmask(x4), self.array([0,1,1,0])) -# assert self.allequal(x4, self.array([1,2,3,4])) x1 = np.arange(5)*1.0 x2 = self.masked_values(x1, 3.0) -# assert self.allequal(x1,x2) -# assert self.allequal(self.array([0,0,0,1,0], self.MaskType), x2.mask) x1 = self.array([1, 'hello', 2, 3], object) x2 = np.array([1, 'hello', 2, 3], object) - s1 = x1[1] - s2 = x2[1] + # check that no error occurs. + x1[1] + x2[1] assert x1[1:1].shape == (0,) # Tests copy-size n = [0, 0, 1, 0, 0] @@ -197,9 +193,11 @@ class moduletester(object): m3 = self.make_mask(m, copy=1) assert(m is not m3) - def test_3(self): - "Tests resize/repeat" + """ + Tests resize/repeat + + """ x4 = self.arange(4) x4[2] = self.masked y4 = self.resize(x4, (8,)) @@ -214,9 +212,11 @@ class moduletester(object): y8 = x4.repeat(2, 0) assert self.allequal(y5, y8) - #---------------------------------- def test_4(self): - "Test of take, transpose, inner, outer products" + """ + Test of take, transpose, inner, outer products. + + """ x = self.arange(24) y = np.arange(24) x[5:6] = self.masked @@ -234,10 +234,12 @@ class moduletester(object): assert t[0] == 'abc' assert t[1] == 2 assert t[2] == 3 - #---------------------------------- + def test_5(self): - "Tests inplace w/ scalar" + """ + Tests inplace w/ scalar + """ x = self.arange(10) y = self.arange(10) xm = self.arange(10) @@ -282,15 +284,14 @@ class moduletester(object): x = self.arange(10).astype(float_) xm = self.arange(10) xm[2] = self.masked - id1 = self.id(x.raw_data()) x += 1. - #assert id1 == self.id(x.raw_data()) - assert self.allequal(x, y+1.) - + assert self.allequal(x, y + 1.) def test_6(self): - "Tests inplace w/ array" + """ + Tests inplace w/ array + """ x = self.arange(10, dtype=float_) y = self.arange(10) xm = self.arange(10, dtype=float_) @@ -337,7 +338,6 @@ class moduletester(object): x /= a xm /= a - #---------------------------------- def test_7(self): "Tests ufunc" d = (self.array([1.0, 0, -1, pi/2]*2, mask=[0, 1]+[0]*6), @@ -361,7 +361,6 @@ class moduletester(object): # 'less', 'greater', # 'logical_and', 'logical_or', 'logical_xor', ]: - #print f try: uf = getattr(self.umath, f) except AttributeError: @@ -373,7 +372,6 @@ class moduletester(object): self.assert_array_equal(ur.filled(0), mr.filled(0), f) self.assert_array_equal(ur._mask, mr._mask) - #---------------------------------- def test_99(self): # test average ott = self.array([0., 1., 2., 3.], mask=[1, 0, 0, 0]) @@ -411,7 +409,6 @@ class moduletester(object): m5 = [0, 1, 1, 1, 1, 1] self.assert_array_equal(self.average(self.masked_array(x, m1), axis=0), 2.5) self.assert_array_equal(self.average(self.masked_array(x, m2), axis=0), 2.5) - # assert(self.average(masked_array(x, m4),axis=0) is masked) self.assert_array_equal(self.average(self.masked_array(x, m5), axis=0), 0.0) self.assert_array_equal(self.count(self.average(self.masked_array(x, m4), axis=0)), 0) z = self.masked_array(y, m3) @@ -419,41 +416,25 @@ class moduletester(object): self.assert_array_equal(self.average(z, axis=0), [0., 1., 99., 99., 4.0, 7.5]) self.assert_array_equal(self.average(z, axis=1), [2.5, 5.0]) self.assert_array_equal(self.average(z, axis=0, weights=w2), [0., 1., 99., 99., 4.0, 10.0]) - #------------------------ + def test_A(self): x = self.arange(24) - y = np.arange(24) x[5:6] = self.masked x = x.reshape(2, 3, 4) -################################################################################ if __name__ == '__main__': - - setup_base = "from __main__ import moduletester \n"\ - "import numpy\n" \ - "tester = moduletester(module)\n" -# setup_new = "import np.ma.core_ini as module\n"+setup_base - setup_cur = "import np.ma.core as module\n"+setup_base -# setup_alt = "import np.ma.core_alt as module\n"+setup_base -# setup_tmp = "import np.ma.core_tmp as module\n"+setup_base - + setup_base = ("from __main__ import ModuleTester \n" + "import numpy\n" + "tester = ModuleTester(module)\n") + setup_cur = "import np.ma.core as module\n" + setup_base (nrepeat, nloop) = (10, 10) if 1: for i in range(1, 8): func = 'tester.test_%i()' % i -# new = timeit.Timer(func, setup_new).repeat(nrepeat, nloop*10) cur = timeit.Timer(func, setup_cur).repeat(nrepeat, nloop*10) -# alt = timeit.Timer(func, setup_alt).repeat(nrepeat, nloop*10) -# tmp = timeit.Timer(func, setup_tmp).repeat(nrepeat, nloop*10) -# new = np.sort(new) cur = np.sort(cur) -# alt = np.sort(alt) -# tmp = np.sort(tmp) - print("#%i" % i +50*'.') - print(eval("moduletester.test_%i.__doc__" % i)) -# print "core_ini : %.3f - %.3f" % (new[0], new[1]) + print("#%i" % i + 50*'.') + print(eval("ModuleTester.test_%i.__doc__" % i)) print("core_current : %.3f - %.3f" % (cur[0], cur[1])) -# print "core_alt : %.3f - %.3f" % (alt[0], alt[1]) -# print "core_tmp : %.3f - %.3f" % (tmp[0], tmp[1]) |