summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorDavid Cournapeau <cournape@gmail.com>2008-12-22 13:23:03 +0000
committerDavid Cournapeau <cournape@gmail.com>2008-12-22 13:23:03 +0000
commitd10d5631368f97af5babd503371a862eaecce8d6 (patch)
tree712d1c42f443e9ff82ebbbd55e349ac468391bf6 /numpy
parent0715c87750409afd8785367c59c524d55ba13431 (diff)
parentfbe2af255824ad463da6936ab86738429008aee9 (diff)
downloadnumpy-d10d5631368f97af5babd503371a862eaecce8d6.tar.gz
Merged revisions 6108,6110,6112-6127,6129-6134,6136-6138,6140-6149,6174-6175,6179-6182,6185-6187 via svnmerge from
http://svn.scipy.org/svn/numpy/trunk ........ r6108 | pierregm | 2008-11-26 11:13:57 +0900 (Wed, 26 Nov 2008) | 3 lines * added ma.diag * added copy, cumprod, cumsum, harden_mask, prod, round, soften_mask, squeeze to the namespace * TEMPORARILY fixed a pb of compatibility with python 2.6 (involvingin(np.nan)) ........ r6110 | pierregm | 2008-11-27 13:29:43 +0900 (Thu, 27 Nov 2008) | 5 lines * Added get_object_signature to fix missing signatures * Fixed .getdoc from _arraymethod, _frommethod, _convert2ma, _fromnxfunction * Fixed the docstrings of .trace, .mean, .argsort, .sort * Suppressed duplicated conjugate, ptp, round, expand_dims, apply_along_axis, compress_rowcols, mask_rowcols, vander, polyfit ........ r6112 | pierregm | 2008-11-27 15:56:12 +0900 (Thu, 27 Nov 2008) | 1 line Doc update ........ r6113 | jarrod.millman | 2008-11-27 19:58:51 +0900 (Thu, 27 Nov 2008) | 2 lines add release notes for 1.3 ........ r6114 | ptvirtan | 2008-11-28 05:26:04 +0900 (Fri, 28 Nov 2008) | 1 line doc: include release notes to Sphinx build ........ r6115 | charris | 2008-11-28 12:52:16 +0900 (Fri, 28 Nov 2008) | 2 lines Make numpy version of atanh more robust. Numpy log1p still needs a major overhaul. ........ r6116 | charris | 2008-11-28 14:34:33 +0900 (Fri, 28 Nov 2008) | 5 lines Add preliminary docstrings for: log2, exp2, logaddexp, logaddexp2, rad2deg, deg2rad. The complete docstring for fmin and fmax are on the web but haven't yet been merged. ........ r6117 | cdavid | 2008-11-29 01:47:34 +0900 (Sat, 29 Nov 2008) | 1 line Fix typo in core scons script. ........ r6118 | cdavid | 2008-11-29 01:50:08 +0900 (Sat, 29 Nov 2008) | 1 line Anoter typo on core scons script. ........ r6119 | stefan | 2008-11-29 21:07:07 +0900 (Sat, 29 Nov 2008) | 1 line Add memory map support to `load` [patch by Gael Varoquaux]. Closes #954. ........ r6120 | stefan | 2008-11-29 21:07:54 +0900 (Sat, 29 Nov 2008) | 1 line Add test for load's mmap_mode. ........ r6121 | stefan | 2008-11-29 21:08:29 +0900 (Sat, 29 Nov 2008) | 1 line Opening a memmap requires a filename. Raise an error otherwise. ........ r6122 | stefan | 2008-11-29 21:09:07 +0900 (Sat, 29 Nov 2008) | 1 line Reformat spacing in io tests. ........ r6123 | stefan | 2008-11-29 23:53:44 +0900 (Sat, 29 Nov 2008) | 1 line Identify file object using 'readline', rather than 'seek'. ........ r6124 | stefan | 2008-11-29 23:54:29 +0900 (Sat, 29 Nov 2008) | 1 line Add bz2 support to loadtxt [patch by Ryan May]. ........ r6125 | ptvirtan | 2008-11-30 23:44:38 +0900 (Sun, 30 Nov 2008) | 1 line Move Sphinx extensions under Numpy's SVN trunk ........ r6126 | ptvirtan | 2008-12-01 00:08:38 +0900 (Mon, 01 Dec 2008) | 1 line Rename core/.../docstrings.py to ufunc_docstrings.py ........ r6127 | pierregm | 2008-12-01 18:45:51 +0900 (Mon, 01 Dec 2008) | 1 line Fixed make_mask_descr for nested dtypes ........ r6129 | pierregm | 2008-12-02 02:56:58 +0900 (Tue, 02 Dec 2008) | 2 lines * added flatten_mask to collapse masks w/ (nested) flexible types. * fixed __getitem__ on arrays w/ nested dtype ........ r6130 | pierregm | 2008-12-02 11:40:22 +0900 (Tue, 02 Dec 2008) | 3 lines * Fixed MaskedArray for nested dtype w/ input mask * Fixed masked_all for nested dtype * Fixed masked_all_like for nested dtype ........ r6131 | pierregm | 2008-12-02 17:50:11 +0900 (Tue, 02 Dec 2008) | 1 line * Fixed make_mask_descr for dtype w/ composite names, like [(('A','B'), float)] ........ r6132 | pierregm | 2008-12-03 03:42:12 +0900 (Wed, 03 Dec 2008) | 1 line * Cleaned up make_mask_descr ........ r6133 | ptvirtan | 2008-12-04 06:52:36 +0900 (Thu, 04 Dec 2008) | 1 line Refactor plot:: directive somewhat ........ r6134 | ptvirtan | 2008-12-04 07:15:51 +0900 (Thu, 04 Dec 2008) | 1 line sphinxext: fix a small bug in plot directive ........ r6136 | cdavid | 2008-12-04 12:21:51 +0900 (Thu, 04 Dec 2008) | 1 line Add /arch option to superpack installer to override detected arch. ........ r6137 | ptvirtan | 2008-12-05 08:06:29 +0900 (Fri, 05 Dec 2008) | 1 line sphinxext: support autosummary:: directives in automodule docstrings ........ r6138 | pierregm | 2008-12-06 05:40:44 +0900 (Sat, 06 Dec 2008) | 2 lines * Added MaskError * If a bool or int ndarray is given as the explicit output of var/min/max, an exception is raised if the function should have output np.nan ........ r6140 | ptvirtan | 2008-12-14 01:18:04 +0900 (Sun, 14 Dec 2008) | 1 line Get lstsq and eigvals from numpy.linalg, not from numpy.dual. Addresses Scipy ticket #800 ........ r6141 | ptvirtan | 2008-12-14 06:02:05 +0900 (Sun, 14 Dec 2008) | 12 lines docs: fix minor issues, support htmlhelp. - Don't use :members: in automodule; it generates too much and not very useful output - Fix edit links and summarize.py - Add better htmlhelp build target - Add upload target - Fix permissions on make dist ........ r6142 | jarrod.millman | 2008-12-14 19:32:51 +0900 (Sun, 14 Dec 2008) | 2 lines wordsmithing ........ r6143 | jarrod.millman | 2008-12-16 20:21:52 +0900 (Tue, 16 Dec 2008) | 2 lines added missing THANKS for Alan's testing work this summer ........ r6144 | cdavid | 2008-12-17 03:04:24 +0900 (Wed, 17 Dec 2008) | 1 line BUG: Do not harcode fortran runtime when copying it on windows. Should fix #969. ........ r6145 | cdavid | 2008-12-17 03:26:13 +0900 (Wed, 17 Dec 2008) | 1 line Add a function to get configured target for gfortran. ........ r6146 | cdavid | 2008-12-17 03:32:41 +0900 (Wed, 17 Dec 2008) | 1 line Fix get_target. ........ r6147 | cdavid | 2008-12-17 03:41:32 +0900 (Wed, 17 Dec 2008) | 1 line Add target specific lib dir for gfortran on windows when msvc is the C compiler. ........ r6148 | cdavid | 2008-12-17 03:48:37 +0900 (Wed, 17 Dec 2008) | 1 line Fix overriding of library_dirs. ........ r6149 | cdavid | 2008-12-17 03:53:25 +0900 (Wed, 17 Dec 2008) | 1 line Add mingw32 and mingwex libraries as runtime libraries for extensions which use fortran and are built with gfortran+MS compiler. ........ r6174 | ptvirtan | 2008-12-20 02:58:57 +0900 (Sat, 20 Dec 2008) | 1 line docs: put CHM files in a zip ........ r6175 | ptvirtan | 2008-12-20 22:40:30 +0900 (Sat, 20 Dec 2008) | 1 line test_umath: don't check against cmath on branch cuts, since the behavior of our functions varies across platforms on them ........ r6179 | cdavid | 2008-12-21 15:02:29 +0900 (Sun, 21 Dec 2008) | 1 line Do not declare missing functions to avoid mismatch with potentially conflicting, undetected ones ........ r6180 | cdavid | 2008-12-21 15:02:44 +0900 (Sun, 21 Dec 2008) | 1 line Update comments in umath. ........ r6181 | cdavid | 2008-12-21 15:03:05 +0900 (Sun, 21 Dec 2008) | 1 line Do not set function to macro in umath anymore. ........ r6182 | cdavid | 2008-12-21 15:03:19 +0900 (Sun, 21 Dec 2008) | 1 line Do not define math func as static: better to have a link error when we have a config problem than having two functions with the same name. ........ r6185 | cdavid | 2008-12-22 01:19:14 +0900 (Mon, 22 Dec 2008) | 1 line Add doc sources so that sdist tarball contains them. ........ r6186 | pierregm | 2008-12-22 19:01:51 +0900 (Mon, 22 Dec 2008) | 4 lines testutils: assert_array_compare : make sure that the comparison is performed on ndarrays, and make sure we use the np version of the comparison function. core: * Try not to touch the data in unary/binary ufuncs, (including inplace) ........ r6187 | pearu | 2008-12-22 19:05:00 +0900 (Mon, 22 Dec 2008) | 1 line Fix a bug. ........
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/SConscript22
-rw-r--r--numpy/core/code_generators/generate_umath.py16
-rw-r--r--numpy/core/code_generators/ufunc_docstrings.py (renamed from numpy/core/code_generators/docstrings.py)186
-rw-r--r--numpy/core/src/umath_funcs_c99.inc.src137
-rw-r--r--numpy/core/tests/test_umath.py2
-rw-r--r--numpy/distutils/fcompiler/gnu.py37
-rwxr-xr-xnumpy/f2py/crackfortran.py4
-rw-r--r--numpy/lib/format.py8
-rw-r--r--numpy/lib/io.py52
-rw-r--r--numpy/lib/polynomial.py31
-rw-r--r--numpy/lib/tests/test_io.py153
-rw-r--r--numpy/ma/core.py604
-rw-r--r--numpy/ma/extras.py195
-rw-r--r--numpy/ma/tests/test_core.py191
-rw-r--r--numpy/ma/tests/test_extras.py56
-rw-r--r--numpy/ma/testutils.py16
16 files changed, 1122 insertions, 588 deletions
diff --git a/numpy/core/SConscript b/numpy/core/SConscript
index 0ffbb444a..70d56c902 100644
--- a/numpy/core/SConscript
+++ b/numpy/core/SConscript
@@ -1,4 +1,4 @@
-# Last Change: Fri Oct 03 04:00 PM 2008 J
+# Last Change: Sat Nov 29 01:00 AM 2008 J
# vim:syntax=python
import os
import sys
@@ -137,9 +137,9 @@ mfuncs = ('expl', 'expf', 'log1p', 'expm1', 'asinh', 'atanhf', 'atanhl',
mfuncs_defined = dict([(f, 0) for f in mfuncs])
# Check for mandatory funcs: we barf if a single one of those is not there
- mandatory_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs",
- "floor", "ceil", "sqrt", "log10", "log", "exp", "asin",
- "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp']
+mandatory_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs",
+ "floor", "ceil", "sqrt", "log10", "log", "exp", "asin",
+ "acos", "atan", "fmod", 'modf', 'frexp', 'ldexp']
if not config.CheckFuncsAtOnce(mandatory_funcs):
raise SystemError("One of the required function to build numpy is not"
@@ -159,17 +159,17 @@ def check_funcs(funcs):
# XXX: we do not test for hypot because python checks for it (HAVE_HYPOT in
# python.h... I wish they would clean their public headers someday)
- optional_stdfuncs = ["expm1", "log1p", "acosh", "asinh", "atanh",
- "rint", "trunc", "exp2", "log2"]
+optional_stdfuncs = ["expm1", "log1p", "acosh", "asinh", "atanh",
+ "rint", "trunc", "exp2", "log2"]
check_funcs(optional_stdfuncs)
# C99 functions: float and long double versions
- c99_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor",
- "ceil", "rint", "trunc", "sqrt", "log10", "log", "log1p", "exp",
- "expm1", "asin", "acos", "atan", "asinh", "acosh", "atanh",
- "hypot", "atan2", "pow", "fmod", "modf", 'frexp', 'ldexp',
- "exp2", "log2"]
+c99_funcs = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor",
+ "ceil", "rint", "trunc", "sqrt", "log10", "log", "log1p", "exp",
+ "expm1", "asin", "acos", "atan", "asinh", "acosh", "atanh",
+ "hypot", "atan2", "pow", "fmod", "modf", 'frexp', 'ldexp',
+ "exp2", "log2"]
for prec in ['l', 'f']:
fns = [f + prec for f in c99_funcs]
diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py
index 00fde1360..a34dcc540 100644
--- a/numpy/core/code_generators/generate_umath.py
+++ b/numpy/core/code_generators/generate_umath.py
@@ -1,7 +1,7 @@
import re, textwrap
import sys, os
sys.path.insert(0, os.path.dirname(__file__))
-import docstrings
+import ufunc_docstrings as docstrings
sys.path.pop(0)
Zero = "PyUFunc_Zero"
@@ -330,12 +330,12 @@ defdict = {
),
'logaddexp' :
Ufunc(2, 1, None,
- "",
+ docstrings.get('numpy.core.umath.logaddexp'),
TD(flts, f="logaddexp")
),
'logaddexp2' :
Ufunc(2, 1, None,
- "",
+ docstrings.get('numpy.core.umath.logaddexp2'),
TD(flts, f="logaddexp2")
),
'bitwise_and' :
@@ -381,7 +381,7 @@ defdict = {
),
'rad2deg' :
Ufunc(1, 1, None,
- '',
+ docstrings.get('numpy.core.umath.rad2deg'),
TD(fltsM, f='rad2deg'),
),
'radians' :
@@ -391,7 +391,7 @@ defdict = {
),
'deg2rad' :
Ufunc(1, 1, None,
- '',
+ docstrings.get('numpy.core.umath.deg2rad'),
TD(fltsM, f='deg2rad'),
),
'arccos' :
@@ -474,7 +474,7 @@ defdict = {
),
'exp2' :
Ufunc(1, 1, None,
- '',
+ docstrings.get('numpy.core.umath.exp2'),
TD(flts, f='exp2'),
TD(M, f='exp2'),
),
@@ -492,7 +492,7 @@ defdict = {
),
'log2' :
Ufunc(1, 1, None,
- '',
+ docstrings.get('numpy.core.umath.log2'),
TD(flts, f='log2'),
TD(M, f='log2'),
),
@@ -522,7 +522,7 @@ defdict = {
),
'trunc' :
Ufunc(1, 1, None,
- '',
+ docstrings.get('numpy.core.umath.trunc'),
TD(flts, f='trunc'),
TD(M, f='trunc'),
),
diff --git a/numpy/core/code_generators/docstrings.py b/numpy/core/code_generators/ufunc_docstrings.py
index 882a781a8..08d544bc5 100644
--- a/numpy/core/code_generators/docstrings.py
+++ b/numpy/core/code_generators/ufunc_docstrings.py
@@ -691,8 +691,9 @@ add_newdoc('numpy.core.umath', 'trunc',
"""
Return the truncated value of the input, element-wise.
- The truncated value of the scalar `x` is the nearest integer `i`, such
- that i is not larger than x amplitude
+ The truncated value of the scalar `x` is the nearest integer `i` which
+ is closer to zero than `x` is. In short, the fractional part of the
+ signed number `x` is discarded.
Parameters
----------
@@ -789,7 +790,9 @@ add_newdoc('numpy.core.umath', 'cosh',
add_newdoc('numpy.core.umath', 'degrees',
"""
- Convert angles from radians to degrees.
+ Convert angles from radians to degrees. This is the same
+ function as rad2deg but the latter is preferred because of
+ the more descriptive name.
Parameters
----------
@@ -804,6 +807,8 @@ add_newdoc('numpy.core.umath', 'degrees',
See Also
--------
+ rad2deg : Convert angles from radians to degrees.
+ deg2rad : Convert angles from degrees to radians.
radians : Convert angles from degrees to radians.
unwrap : Remove large jumps in angle by wrapping.
@@ -818,6 +823,41 @@ add_newdoc('numpy.core.umath', 'degrees',
""")
+add_newdoc('numpy.core.umath', 'rad2deg',
+ """
+ Convert angles from radians to degrees. This is the same
+ function as degrees but is preferred because its more
+ descriptive name.
+
+ Parameters
+ ----------
+ x : array_like
+ Angle in radians.
+
+ Returns
+ -------
+ y : ndarray
+ The corresponding angle in degrees.
+
+
+ See Also
+ --------
+ degrees : Convert angles from radians to degrees.
+ deg2rad : Convert angles from degrees to radians.
+ radians : Convert angles from degrees to radians.
+ unwrap : Remove large jumps in angle by wrapping.
+
+ Notes
+ -----
+ rad2deg(x) is ``180 * x / pi``.
+
+ Examples
+ --------
+ >>> np.rad2deg(np.pi/2)
+ 90.0
+
+ """)
+
add_newdoc('numpy.core.umath', 'divide',
"""
Divide arguments element-wise.
@@ -962,6 +1002,22 @@ add_newdoc('numpy.core.umath', 'exp',
""")
+add_newdoc('numpy.core.umath', 'exp2',
+ """
+ Calculate `2**p` for all `p` in the input array.
+
+ Parameters
+ ----------
+ x : array_like
+ Input values.
+
+ Returns
+ -------
+ out : ndarray
+ Element-wise 2 to the power `x`.
+
+ """)
+
add_newdoc('numpy.core.umath', 'expm1',
"""
Return the exponential of the elements in the array minus one.
@@ -1661,6 +1717,82 @@ add_newdoc('numpy.core.umath', 'log10',
""")
+add_newdoc('numpy.core.umath', 'log2',
+ """
+ Base-2 logarithm of `x`.
+
+ Parameters
+ ----------
+ x : array_like
+ Input values.
+
+ Returns
+ -------
+ y : ndarray
+ Base-2 logarithm of `x`.
+
+ See Also
+ --------
+ log, log10, log1p
+
+ """)
+
+add_newdoc('numpy.core.umath', 'logaddexp',
+ """
+ Logarithm of `exp(x) + exp(y)`.
+
+ This function is useful in statistics where the calculated probabilities of
+ events may be so small as to excede the range of normal floating point
+ numbers. In such cases the logarithm of the calculated probability is
+ stored. This function allows adding probabilities stored in such a fashion.
+
+ Parameters
+ ----------
+ x : array_like
+ Input values.
+ y : array_like
+ Input values.
+
+
+ Returns
+ -------
+ result : ndarray
+ Logarithm of `exp(x) + exp(y)`.
+
+ See Also
+ --------
+ logaddexp2
+
+ """)
+
+add_newdoc('numpy.core.umath', 'logaddexp2',
+ """
+ Base-2 Logarithm of `2**x + 2**y`.
+
+ This function is useful in machine learning when the calculated probabilities of
+ events may be so small as to excede the range of normal floating point
+ numbers. In such cases the base-2 logarithm of the calculated probability
+ can be used instead. This function allows adding probabilities stored in such a fashion.
+
+ Parameters
+ ----------
+ x : array_like
+ Input values.
+ y : array_like
+ Input values.
+
+
+ Returns
+ -------
+ result : ndarray
+ Base-2 logarithm of `2**x + 2**y`.
+
+ See Also
+ --------
+ logaddexp
+
+ """)
+
add_newdoc('numpy.core.umath', 'log1p',
"""
`log(1 + x)` in base `e`, elementwise.
@@ -1921,6 +2053,16 @@ add_newdoc('numpy.core.umath', 'minimum',
""")
+add_newdoc('numpy.core.umath', 'fmax',
+ """
+
+ """)
+
+add_newdoc('numpy.core.umath', 'fmin',
+ """
+
+ """)
+
add_newdoc('numpy.core.umath', 'modf',
"""
Return the fractional and integral part of a number.
@@ -2102,7 +2244,8 @@ add_newdoc('numpy.core.umath', 'power',
add_newdoc('numpy.core.umath', 'radians',
"""
- Convert angles from degrees to radians.
+ Convert angles from degrees to radians. This function is
+ the same as deg2rad, which is more descriptive..
Parameters
----------
@@ -2116,6 +2259,8 @@ add_newdoc('numpy.core.umath', 'radians',
See Also
--------
+ deg2rad : Convert angles from degrees to radians.
+ rad2deg : Convert angles from radians to degrees.
degrees : Convert angles from radians to degrees.
unwrap : Remove large jumps in angle by wrapping.
@@ -2130,6 +2275,39 @@ add_newdoc('numpy.core.umath', 'radians',
""")
+add_newdoc('numpy.core.umath', 'deg2rad',
+ """
+ Convert angles from degrees to radians. This is the same
+ function as radians, but deg2rad is a more descriptive name.
+
+ Parameters
+ ----------
+ x : array_like
+ Angles in degrees.
+
+ Returns
+ -------
+ y : ndarray
+ The corresponding angle in radians.
+
+ See Also
+ --------
+ radians : Convert angles from degrees to radians.
+ rad2deg : Convert angles from radians to degrees.
+ degrees : Convert angles from radians to degrees.
+ unwrap : Remove large jumps in angle by wrapping.
+
+ Notes
+ -----
+ ``deg2rad(x)`` is ``x * pi / 180``.
+
+ Examples
+ --------
+ >>> np.deg2rad(180)
+ 3.1415926535897931
+
+ """)
+
add_newdoc('numpy.core.umath', 'reciprocal',
"""
Return element-wise reciprocal.
diff --git a/numpy/core/src/umath_funcs_c99.inc.src b/numpy/core/src/umath_funcs_c99.inc.src
index 828331875..e0bcdebee 100644
--- a/numpy/core/src/umath_funcs_c99.inc.src
+++ b/numpy/core/src/umath_funcs_c99.inc.src
@@ -17,9 +17,7 @@
* can be linked from the math library. The result can depend on the
* optimization flags as well as the compiler, so can't be known ahead of
* time. If the function can't be linked, then either it is absent, defined
- * as a macro, or is an intrinsic (hardware) function. If it is linkable it
- * may still be the case that no prototype is available. So to cover all the
- * cases requires the following construction.
+ * as a macro, or is an intrinsic (hardware) function.
*
* i) Undefine any possible macros:
*
@@ -27,44 +25,20 @@
* #undef foo
* #endif
*
- * ii) Check if the function was in the library, If not, define the
- * function with npy_ prepended to its name to avoid conflict with any
- * intrinsic versions, then use a define so that the preprocessor will
- * replace foo with npy_foo before the compilation pass. Make the
- * function static to avoid poluting the module library.
+ * ii) Avoid as much as possible to declare any function here. Declaring
+ * functions is not portable: some platforms define some function inline
+ * with a non standard identifier, for example, or may put another
+ * idendifier which changes the calling convention of the function. If you
+ * really have to, ALWAYS declare it for the one platform you are dealing
+ * with:
*
- * #ifdef foo
- * #undef foo
- * #endif
- * #ifndef HAVE_FOO
- * static double
- * npy_foo(double x)
- * {
- * return x;
- * }
- * #define foo npy_foo
- *
- * iii) Finally, even if foo is in the library, add a prototype. Just being
- * in the library doesn't guarantee a prototype in math.h, and in any case
- * you want to make sure the prototype is what you think it is. Count on it,
- * whatever can go wrong will go wrong. Think defensively! The result:
- *
- * #ifdef foo
- * #undef foo
- * #endif
- * #ifndef HAVE_FOO
- * static double
- * npy_foo(double x)
- * {
- * return x;
- * }
- * #define foo npy_foo
- * #else
- * double foo(double x);
- * #end
- *
- * And there you have it.
+ * Not ok:
+ * double exp(double a);
*
+ * Ok:
+ * #ifdef SYMBOL_DEFINED_WEIRD_PLATFORM
+ * double exp(double);
+ * #endif
*/
/*
@@ -82,8 +56,7 @@
/* Original code by Konrad Hinsen. */
#ifndef HAVE_EXPM1
-static double
-npy_expm1(double x)
+double expm1(double x)
{
double u = exp(x);
if (u == 1.0) {
@@ -94,14 +67,10 @@ npy_expm1(double x)
return (u-1.0) * x/log(u);
}
}
-#define expm1 npy_expm1
-#else
-double expm1(double x);
#endif
#ifndef HAVE_LOG1P
-static double
-npy_log1p(double x)
+double log1p(double x)
{
double u = 1. + x;
if (u == 1.0) {
@@ -110,14 +79,10 @@ npy_log1p(double x)
return log(u) * x / (u - 1);
}
}
-#define log1p npy_log1p
-#else
-double log1p(double x);
#endif
#ifndef HAVE_HYPOT
-static double
-npy_hypot(double x, double y)
+double hypot(double x, double y)
{
double yx;
@@ -135,25 +100,17 @@ npy_hypot(double x, double y)
return x*sqrt(1.+yx*yx);
}
}
-#define hypot npy_hypot
-#else
-double hypot(double x, double y);
#endif
#ifndef HAVE_ACOSH
-static double
-npy_acosh(double x)
+double acosh(double x)
{
return 2*log(sqrt((x+1.0)/2)+sqrt((x-1.0)/2));
}
-#define acosh npy_acosh
-#else
-double acosh(double x);
#endif
#ifndef HAVE_ASINH
-static double
-npy_asinh(double xx)
+double asinh(double xx)
{
double x, d;
int sign;
@@ -172,25 +129,22 @@ npy_asinh(double xx)
}
return sign*log1p(x*(1.0 + x/(d+1)));
}
-#define asinh npy_asinh
-#else
-double asinh(double xx);
#endif
#ifndef HAVE_ATANH
-static double
-npy_atanh(double x)
+double atanh(double x)
{
- return 0.5*log1p(2.0*x/(1.0-x));
+ if (x > 0) {
+ return -0.5*log1p(-2.0*x/(1.0 + x));
+ }
+ else {
+ return 0.5*log1p(2.0*x/(1.0 - x));
+ }
}
-#define atanh npy_atanh
-#else
-double atanh(double x);
#endif
#ifndef HAVE_RINT
-static double
-npy_rint(double x)
+double rint(double x)
{
double y, r;
@@ -209,46 +163,31 @@ npy_rint(double x)
}
return y;
}
-#define rint npy_rint
-#else
-double rint(double x);
#endif
#ifndef HAVE_TRUNC
-static double
-npy_trunc(double x)
+double trunc(double x)
{
return x < 0 ? ceil(x) : floor(x);
}
-#define trunc npy_trunc
-#else
-double trunc(double x);
#endif
#ifndef HAVE_EXP2
#define LOG2 0.69314718055994530943
-static double
-npy_exp2(double x)
+double exp2(double x)
{
return exp(LOG2*x);
}
-#define exp2 npy_exp2
#undef LOG2
-#else
-double exp2(double x);
#endif
#ifndef HAVE_LOG2
#define INVLOG2 1.4426950408889634074
-static double
-npy_log2(double x)
+double log2(double x)
{
return INVLOG2*log(x);
}
-#define log2 npy_log2
#undef INVLOG2
-#else
-double log2(double x);
#endif
/*
@@ -326,14 +265,10 @@ static int signbit_ld (long double x)
#undef @kind@@c@
#endif
#ifndef HAVE_@KIND@@C@
-static @type@
-npy_@kind@@c@(@type@ x)
+@type@ @kind@@c@(@type@ x)
{
return (@type@) @kind@((double)x);
}
-#define @kind@@c@ npy_@kind@@c@
-#else
-@type@ @kind@@c@(@type@ x);
#endif
/**end repeat1**/
@@ -346,14 +281,10 @@ npy_@kind@@c@(@type@ x)
#undef @kind@@c@
#endif
#ifndef HAVE_@KIND@@C@
-static @type@
-npy_@kind@@c@(@type@ x, @type@ y)
+@type@ @kind@@c@(@type@ x, @type@ y)
{
return (@type@) @kind@((double)x, (double) y);
}
-#define @kind@@c@ npy_@kind@@c@
-#else
-@type@ @kind@@c@(@type@ x, @type@ y);
#endif
/**end repeat1**/
@@ -361,17 +292,13 @@ npy_@kind@@c@(@type@ x, @type@ y)
#undef modf@c@
#endif
#ifndef HAVE_MODF@C@
-static @type@
-npy_modf@c@(@type@ x, @type@ *iptr)
+@type@ modf@c@(@type@ x, @type@ *iptr)
{
double niptr;
double y = modf((double)x, &niptr);
*iptr = (@type@) niptr;
return (@type@) y;
}
-#define modf@c@ npy_modf@c@
-#else
-@type@ modf@c@(@type@ x, @type@ *iptr);
#endif
/**end repeat**/
diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py
index 0dab9ac3a..1b4ba97ca 100644
--- a/numpy/core/tests/test_umath.py
+++ b/numpy/core/tests/test_umath.py
@@ -404,7 +404,7 @@ class TestComplexFunctions(object):
if sys.version_info < (2,5,3):
broken_cmath_asinh = True
- points = [-2, 2j, 2, -2j, -1-1j, -1+1j, +1-1j, +1+1j]
+ points = [-1-1j, -1+1j, +1-1j, +1+1j]
name_map = {'arcsin': 'asin', 'arccos': 'acos', 'arctan': 'atan',
'arcsinh': 'asinh', 'arccosh': 'acosh', 'arctanh': 'atanh'}
atol = 4*np.finfo(np.complex).eps
diff --git a/numpy/distutils/fcompiler/gnu.py b/numpy/distutils/fcompiler/gnu.py
index bd9284ba7..7b642aff3 100644
--- a/numpy/distutils/fcompiler/gnu.py
+++ b/numpy/distutils/fcompiler/gnu.py
@@ -10,6 +10,7 @@ from numpy.distutils.misc_util import msvc_runtime_library
compilers = ['GnuFCompiler', 'Gnu95FCompiler']
+TARGET_R = re.compile("Target: ([a-zA-Z0-9_\-]*)")
class GnuFCompiler(FCompiler):
compiler_type = 'gnu'
compiler_aliases = ('g77',)
@@ -130,10 +131,10 @@ class GnuFCompiler(FCompiler):
# if windows and not cygwin, libg2c lies in a different folder
if sys.platform == 'win32' and not d.startswith('/usr/lib'):
d = os.path.normpath(d)
- if not os.path.exists(os.path.join(d, 'libg2c.a')):
+ if not os.path.exists(os.path.join(d, "lib%s.a" % self.g2c)):
d2 = os.path.abspath(os.path.join(d,
'../../../../lib'))
- if os.path.exists(os.path.join(d2, 'libg2c.a')):
+ if os.path.exists(os.path.join(d2, "lib%s.a" % self.g2c)):
opt.append(d2)
opt.append(d)
return opt
@@ -269,12 +270,44 @@ class Gnu95FCompiler(GnuFCompiler):
flags = GnuFCompiler.get_flags_linker_so(self)
return self._add_arches_for_universal_build(flags)
+ def get_library_dirs(self):
+ opt = GnuFCompiler.get_library_dirs(self)
+ if sys.platform == 'win32':
+ c_compiler = self.c_compiler
+ if c_compiler and c_compiler.compiler_type == "msvc":
+ target = self.get_target()
+ if target:
+ d = os.path.normpath(self.get_libgcc_dir())
+ root = os.path.join(d, os.pardir, os.pardir, os.pardir, os.pardir)
+ mingwdir = os.path.normpath(os.path.join(root, target, "lib"))
+ full = os.path.join(mingwdir, "libmingwex.a")
+ if os.path.exists(full):
+ opt.append(mingwdir)
+ return opt
+
def get_libraries(self):
opt = GnuFCompiler.get_libraries(self)
if sys.platform == 'darwin':
opt.remove('cc_dynamic')
+ if sys.platform == 'win32':
+ c_compiler = self.c_compiler
+ if c_compiler and c_compiler.compiler_type == "msvc":
+ if "gcc" in opt:
+ i = opt.index("gcc")
+ opt.insert(i+1, "mingwex")
+ opt.insert(i+1, "mingw32")
return opt
+ def get_target(self):
+ status, output = exec_command(self.compiler_f77 +
+ ['-v'],
+ use_tee=0)
+ if not status:
+ m = TARGET_R.search(output)
+ if m:
+ return m.group(1)
+ return ""
+
if __name__ == '__main__':
from distutils import log
log.set_verbosity(2)
diff --git a/numpy/f2py/crackfortran.py b/numpy/f2py/crackfortran.py
index 8e5f2882f..449db33a3 100755
--- a/numpy/f2py/crackfortran.py
+++ b/numpy/f2py/crackfortran.py
@@ -2446,9 +2446,9 @@ def crack2fortrangen(block,tab='\n'):
global skipfuncs, onlyfuncs
setmesstext(block)
ret=''
- if type(block) is type([]):
+ if isinstance(block, list):
for g in block:
- if g['block'] in ['function','subroutine']:
+ if g and g['block'] in ['function','subroutine']:
if g['name'] in skipfuncs:
continue
if onlyfuncs and g['name'] not in onlyfuncs:
diff --git a/numpy/lib/format.py b/numpy/lib/format.py
index 32a23ae18..28444613c 100644
--- a/numpy/lib/format.py
+++ b/numpy/lib/format.py
@@ -381,7 +381,7 @@ def read_array(fp):
def open_memmap(filename, mode='r+', dtype=None, shape=None,
- fortran_order=False, version=(1,0)):
+ fortran_order=False, version=(1,0)):
"""
Open a .npy file as a memory-mapped array.
@@ -390,7 +390,7 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None,
Parameters
----------
filename : str
- The name of the file on disk. This may not be a filelike object.
+ The name of the file on disk. This may not be a file-like object.
mode : str, optional
The mode to open the file with. In addition to the standard file modes,
'c' is also accepted to mean "copy on write". See `numpy.memmap` for
@@ -425,6 +425,10 @@ def open_memmap(filename, mode='r+', dtype=None, shape=None,
numpy.memmap
"""
+ if not isinstance(filename, basestring):
+ raise ValueError("Filename must be a string. Memmap cannot use" \
+ " existing file handles.")
+
if 'w' in mode:
# We are creating the file, not reading it.
# Check if we ought to create the file.
diff --git a/numpy/lib/io.py b/numpy/lib/io.py
index deb86fb61..e9a012db1 100644
--- a/numpy/lib/io.py
+++ b/numpy/lib/io.py
@@ -79,7 +79,7 @@ class NpzFile(object):
else:
raise KeyError, "%s is not a file in the archive" % key
-def load(file, memmap=False):
+def load(file, mmap_mode=None):
"""
Load a pickled, ``.npy``, or ``.npz`` binary file.
@@ -87,10 +87,15 @@ def load(file, memmap=False):
----------
file : file-like object or string
The file to read. It must support ``seek()`` and ``read()`` methods.
- memmap : bool
- If True, then memory-map the ``.npy`` file (or unzip the ``.npz`` file
- into a temporary directory and memory-map each component). This has
- no effect for a pickled file.
+ mmap_mode: {None, 'r+', 'r', 'w+', 'c'}, optional
+ If not None, then memory-map the file, using the given mode
+ (see `numpy.memmap`). The mode has no effect for pickled or
+ zipped files.
+ A memory-mapped array is stored on disk, and not directly loaded
+ into memory. However, it can be accessed and sliced like any
+ ndarray. Memory mapping is especially useful for accessing
+ small fragments of large files without reading the entire file
+ into memory.
Returns
-------
@@ -104,18 +109,28 @@ def load(file, memmap=False):
Notes
-----
- - If file contains pickle data, then whatever is stored in the
+ - If the file contains pickle data, then whatever is stored in the
pickle is returned.
- If the file is a ``.npy`` file, then an array is returned.
- If the file is a ``.npz`` file, then a dictionary-like object is
- returned, containing {filename: array} key-value pairs, one for
- every file in the archive.
+ returned, containing ``{filename: array}`` key-value pairs, one for
+ each file in the archive.
Examples
--------
- >>> np.save('/tmp/123', np.array([1, 2, 3])
+ Store data to disk, and load it again:
+
+ >>> np.save('/tmp/123', np.array([[1, 2, 3], [4, 5, 6]]))
>>> np.load('/tmp/123.npy')
- array([1, 2, 3])
+ array([[1, 2, 3],
+ [4, 5, 6]])
+
+ Mem-map the stored array, and then access the second row
+ directly from disk:
+
+ >>> X = np.load('/tmp/123.npy', mmap_mode='r')
+ >>> X[1, :]
+ memmap([4, 5, 6])
"""
if isinstance(file, basestring):
@@ -123,9 +138,6 @@ def load(file, memmap=False):
else:
fid = file
- if memmap:
- raise NotImplementedError
-
# Code to distinguish from NumPy binary files and pickles.
_ZIP_PREFIX = 'PK\x03\x04'
N = len(format.MAGIC_PREFIX)
@@ -134,7 +146,10 @@ def load(file, memmap=False):
if magic.startswith(_ZIP_PREFIX): # zip-file (assume .npz)
return NpzFile(fid)
elif magic == format.MAGIC_PREFIX: # .npy file
- return format.read_array(fid)
+ if mmap_mode:
+ return format.open_memmap(file, mode=mmap_mode)
+ else:
+ return format.read_array(fid)
else: # Try a pickle
try:
return _cload(fid)
@@ -264,8 +279,8 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
Parameters
----------
fname : file or string
- File or filename to read. If the filename extension is ``.gz``,
- the file is first decompressed.
+ File or filename to read. If the filename extension is ``.gz`` or
+ ``.bz2``, the file is first decompressed.
dtype : data-type
Data type of the resulting array. If this is a record data-type,
the resulting array will be 1-dimensional, and each row will be
@@ -331,9 +346,12 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
if fname.endswith('.gz'):
import gzip
fh = gzip.open(fname)
+ elif fname.endswith('.bz2'):
+ import bz2
+ fh = bz2.BZ2File(fname)
else:
fh = file(fname)
- elif hasattr(fname, 'seek'):
+ elif hasattr(fname, 'readline'):
fh = fname
else:
raise ValueError('fname must be a string or file handle')
diff --git a/numpy/lib/polynomial.py b/numpy/lib/polynomial.py
index 4a70c9fa3..504a1271f 100644
--- a/numpy/lib/polynomial.py
+++ b/numpy/lib/polynomial.py
@@ -15,36 +15,13 @@ from numpy.lib.getlimits import finfo
from numpy.lib.twodim_base import diag, vander
from numpy.lib.shape_base import hstack, atleast_1d
from numpy.lib.function_base import trim_zeros, sort_complex
-eigvals = None
-lstsq = None
+from numpy.linalg import eigvals, lstsq
class RankWarning(UserWarning):
"""Issued by polyfit when Vandermonde matrix is rank deficient.
"""
pass
-def get_linalg_funcs():
- "Look for linear algebra functions in numpy"
- global eigvals, lstsq
- from numpy.dual import eigvals, lstsq
- return
-
-def _eigvals(arg):
- "Return the eigenvalues of the argument"
- try:
- return eigvals(arg)
- except TypeError:
- get_linalg_funcs()
- return eigvals(arg)
-
-def _lstsq(X, y, rcond):
- "Do least squares on the arguments"
- try:
- return lstsq(X, y, rcond)
- except TypeError:
- get_linalg_funcs()
- return lstsq(X, y, rcond)
-
def poly(seq_of_zeros):
"""
Return polynomial coefficients given a sequence of roots.
@@ -94,7 +71,7 @@ def poly(seq_of_zeros):
seq_of_zeros = atleast_1d(seq_of_zeros)
sh = seq_of_zeros.shape
if len(sh) == 2 and sh[0] == sh[1]:
- seq_of_zeros = _eigvals(seq_of_zeros)
+ seq_of_zeros = eigvals(seq_of_zeros)
elif len(sh) ==1:
pass
else:
@@ -177,7 +154,7 @@ def roots(p):
# build companion matrix and find its eigenvalues (the roots)
A = diag(NX.ones((N-2,), p.dtype), -1)
A[0, :] = -p[1:] / p[0]
- roots = _eigvals(A)
+ roots = eigvals(A)
else:
roots = NX.array([])
@@ -500,7 +477,7 @@ def polyfit(x, y, deg, rcond=None, full=False):
# solve least squares equation for powers of x
v = vander(x, order)
- c, resids, rank, s = _lstsq(v, y, rcond)
+ c, resids, rank, s = lstsq(v, y, rcond)
# warn on rank reduction, which indicates an ill conditioned matrix
if rank != order and not full:
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index e78fd0579..885fd3616 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -2,55 +2,90 @@ from numpy.testing import *
import numpy as np
import StringIO
+from tempfile import NamedTemporaryFile
class RoundtripTest:
+ def roundtrip(self, save_func, *args, **kwargs):
+ """
+ save_func : callable
+ Function used to save arrays to file.
+ file_on_disk : bool
+ If true, store the file on disk, instead of in a
+ string buffer.
+ save_kwds : dict
+ Parameters passed to `save_func`.
+ load_kwds : dict
+ Parameters passed to `numpy.load`.
+ args : tuple of arrays
+ Arrays stored to file.
+
+ """
+ save_kwds = kwargs.get('save_kwds', {})
+ load_kwds = kwargs.get('load_kwds', {})
+ file_on_disk = kwargs.get('file_on_disk', False)
+
+ if file_on_disk:
+ target_file = NamedTemporaryFile()
+ load_file = target_file.name
+ else:
+ target_file = StringIO.StringIO()
+ load_file = target_file
+
+ arr = args
+
+ save_func(target_file, *arr, **save_kwds)
+ target_file.flush()
+ target_file.seek(0)
+
+ arr_reloaded = np.load(load_file, **load_kwds)
+
+ self.arr = arr
+ self.arr_reloaded = arr_reloaded
+
def test_array(self):
- a = np.array( [[1,2],[3,4]], float)
- self.do(a)
+ a = np.array([[1, 2], [3, 4]], float)
+ self.roundtrip(a)
- a = np.array( [[1,2],[3,4]], int)
- self.do(a)
+ a = np.array([[1, 2], [3, 4]], int)
+ self.roundtrip(a)
- a = np.array( [[1+5j,2+6j],[3+7j,4+8j]], dtype=np.csingle)
- self.do(a)
+ a = np.array([[1 + 5j, 2 + 6j], [3 + 7j, 4 + 8j]], dtype=np.csingle)
+ self.roundtrip(a)
- a = np.array( [[1+5j,2+6j],[3+7j,4+8j]], dtype=np.cdouble)
- self.do(a)
+ a = np.array([[1 + 5j, 2 + 6j], [3 + 7j, 4 + 8j]], dtype=np.cdouble)
+ self.roundtrip(a)
def test_1D(self):
- a = np.array([1,2,3,4], int)
- self.do(a)
+ a = np.array([1, 2, 3, 4], int)
+ self.roundtrip(a)
+
+ def test_mmap(self):
+ a = np.array([[1, 2.5], [4, 7.3]])
+ self.roundtrip(a, file_on_disk=True, load_kwds={'mmap_mode': 'r'})
def test_record(self):
a = np.array([(1, 2), (3, 4)], dtype=[('x', 'i4'), ('y', 'i4')])
- self.do(a)
+ self.roundtrip(a)
class TestSaveLoad(RoundtripTest, TestCase):
- def do(self, a):
- c = StringIO.StringIO()
- np.save(c, a)
- c.seek(0)
- a_reloaded = np.load(c)
- assert_equal(a, a_reloaded)
-
+ def roundtrip(self, *args, **kwargs):
+ RoundtripTest.roundtrip(self, np.save, *args, **kwargs)
+ assert_equal(self.arr[0], self.arr_reloaded)
class TestSavezLoad(RoundtripTest, TestCase):
- def do(self, *arrays):
- c = StringIO.StringIO()
- np.savez(c, *arrays)
- c.seek(0)
- l = np.load(c)
- for n, a in enumerate(arrays):
- assert_equal(a, l['arr_%d' % n])
+ def roundtrip(self, *args, **kwargs):
+ RoundtripTest.roundtrip(self, np.savez, *args, **kwargs)
+ for n, arr in enumerate(self.arr):
+ assert_equal(arr, self.arr_reloaded['arr_%d' % n])
def test_multiple_arrays(self):
- a = np.array( [[1,2],[3,4]], float)
- b = np.array( [[1+2j,2+7j],[3-6j,4+12j]], complex)
- self.do(a,b)
+ a = np.array([[1, 2], [3, 4]], float)
+ b = np.array([[1 + 2j, 2 + 7j], [3 - 6j, 4 + 12j]], complex)
+ self.roundtrip(a,b)
def test_named_arrays(self):
- a = np.array( [[1,2],[3,4]], float)
- b = np.array( [[1+2j,2+7j],[3-6j,4+12j]], complex)
+ a = np.array([[1, 2], [3, 4]], float)
+ b = np.array([[1 + 2j, 2 + 7j], [3 - 6j, 4 + 12j]], complex)
c = StringIO.StringIO()
np.savez(c, file_a=a, file_b=b)
c.seek(0)
@@ -61,7 +96,7 @@ class TestSavezLoad(RoundtripTest, TestCase):
class TestSaveTxt(TestCase):
def test_array(self):
- a =np.array( [[1,2],[3,4]], float)
+ a =np.array([[1, 2], [3, 4]], float)
c = StringIO.StringIO()
np.savetxt(c, a)
c.seek(0)
@@ -69,14 +104,14 @@ class TestSaveTxt(TestCase):
['1.000000000000000000e+00 2.000000000000000000e+00\n',
'3.000000000000000000e+00 4.000000000000000000e+00\n'])
- a =np.array( [[1,2],[3,4]], int)
+ a =np.array([[1, 2], [3, 4]], int)
c = StringIO.StringIO()
np.savetxt(c, a, fmt='%d')
c.seek(0)
assert_equal(c.readlines(), ['1 2\n', '3 4\n'])
def test_1D(self):
- a = np.array([1,2,3,4], int)
+ a = np.array([1, 2, 3, 4], int)
c = StringIO.StringIO()
np.savetxt(c, a, fmt='%d')
c.seek(0)
@@ -146,12 +181,12 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int)
- a = np.array([[1,2],[3,4]], int)
+ a = np.array([[1, 2], [3, 4]], int)
assert_array_equal(x, a)
c.seek(0)
x = np.loadtxt(c, dtype=float)
- a = np.array([[1,2],[3,4]], float)
+ a = np.array([[1, 2], [3, 4]], float)
assert_array_equal(x, a)
def test_1D(self):
@@ -159,14 +194,14 @@ class TestLoadTxt(TestCase):
c.write('1\n2\n3\n4\n')
c.seek(0)
x = np.loadtxt(c, dtype=int)
- a = np.array([1,2,3,4], int)
+ a = np.array([1, 2, 3, 4], int)
assert_array_equal(x, a)
c = StringIO.StringIO()
c.write('1,2,3,4\n')
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',')
- a = np.array([1,2,3,4], int)
+ a = np.array([1, 2, 3, 4], int)
assert_array_equal(x, a)
def test_missing(self):
@@ -175,7 +210,7 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',', \
converters={3:lambda s: int(s or -999)})
- a = np.array([1,2,3,-999,5], int)
+ a = np.array([1, 2, 3, -999, 5], int)
assert_array_equal(x, a)
def test_converters_with_usecols(self):
@@ -184,8 +219,8 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',', \
converters={3:lambda s: int(s or -999)}, \
- usecols=(1, 3, ))
- a = np.array([[2, -999],[7, 9]], int)
+ usecols=(1, 3,))
+ a = np.array([[2, -999], [7, 9]], int)
assert_array_equal(x, a)
def test_comments(self):
@@ -194,7 +229,7 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',', \
comments='#')
- a = np.array([1,2,3,5], int)
+ a = np.array([1, 2, 3, 5], int)
assert_array_equal(x, a)
def test_skiprows(self):
@@ -203,7 +238,7 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',', \
skiprows=1)
- a = np.array([1,2,3,5], int)
+ a = np.array([1, 2, 3, 5], int)
assert_array_equal(x, a)
c = StringIO.StringIO()
@@ -211,28 +246,28 @@ class TestLoadTxt(TestCase):
c.seek(0)
x = np.loadtxt(c, dtype=int, delimiter=',', \
skiprows=1)
- a = np.array([1,2,3,5], int)
+ a = np.array([1, 2, 3, 5], int)
assert_array_equal(x, a)
def test_usecols(self):
- a =np.array( [[1,2],[3,4]], float)
+ a = np.array([[1, 2], [3, 4]], float)
c = StringIO.StringIO()
np.savetxt(c, a)
c.seek(0)
x = np.loadtxt(c, dtype=float, usecols=(1,))
assert_array_equal(x, a[:,1])
- a =np.array( [[1,2,3],[3,4,5]], float)
+ a =np.array([[1, 2, 3], [3, 4, 5]], float)
c = StringIO.StringIO()
np.savetxt(c, a)
c.seek(0)
- x = np.loadtxt(c, dtype=float, usecols=(1,2))
- assert_array_equal(x, a[:,1:])
+ x = np.loadtxt(c, dtype=float, usecols=(1, 2))
+ assert_array_equal(x, a[:, 1:])
# Testing with arrays instead of tuples.
c.seek(0)
- x = np.loadtxt(c, dtype=float, usecols=np.array([1,2]))
- assert_array_equal(x, a[:,1:])
+ x = np.loadtxt(c, dtype=float, usecols=np.array([1, 2]))
+ assert_array_equal(x, a[:, 1:])
# Checking with dtypes defined converters.
data = '''JOE 70.1 25.3
@@ -241,9 +276,9 @@ class TestLoadTxt(TestCase):
c = StringIO.StringIO(data)
names = ['stid', 'temp']
dtypes = ['S4', 'f8']
- arr = np.loadtxt(c, usecols=(0,2),dtype=zip(names,dtypes))
- assert_equal(arr['stid'], ["JOE", "BOB"])
- assert_equal(arr['temp'], [25.3, 27.9])
+ arr = np.loadtxt(c, usecols=(0, 2), dtype=zip(names, dtypes))
+ assert_equal(arr['stid'], ["JOE", "BOB"])
+ assert_equal(arr['temp'], [25.3, 27.9])
def test_fancy_dtype(self):
c = StringIO.StringIO()
@@ -251,7 +286,7 @@ class TestLoadTxt(TestCase):
c.seek(0)
dt = np.dtype([('x', int), ('y', [('t', int), ('s', float)])])
x = np.loadtxt(c, dtype=dt, delimiter=',')
- a = np.array([(1,(2,3.0)),(4,(5,6.0))], dt)
+ a = np.array([(1, (2, 3.0)), (4, (5, 6.0))], dt)
assert_array_equal(x, a)
def test_empty_file(self):
@@ -262,11 +297,13 @@ class TestLoadTxt(TestCase):
c = StringIO.StringIO()
c.writelines(['1 21\n', '3 42\n'])
c.seek(0)
- data = np.loadtxt(c, usecols=(1,), converters={0: lambda s: int(s, 16)})
+ data = np.loadtxt(c, usecols=(1,),
+ converters={0: lambda s: int(s, 16)})
assert_array_equal(data, [21, 42])
c.seek(0)
- data = np.loadtxt(c, usecols=(1,), converters={1: lambda s: int(s, 16)})
+ data = np.loadtxt(c, usecols=(1,),
+ converters={1: lambda s: int(s, 16)})
assert_array_equal(data, [33, 66])
class Testfromregex(TestCase):
@@ -277,7 +314,8 @@ class Testfromregex(TestCase):
dt = [('num', np.float64), ('val', 'S3')]
x = np.fromregex(c, r"([0-9.]+)\s+(...)", dt)
- a = np.array([(1.312, 'foo'), (1.534, 'bar'), (4.444, 'qux')], dtype=dt)
+ a = np.array([(1.312, 'foo'), (1.534, 'bar'), (4.444, 'qux')],
+ dtype=dt)
assert_array_equal(x, a)
def test_record_2(self):
@@ -288,7 +326,8 @@ class Testfromregex(TestCase):
dt = [('num', np.int32), ('val', 'S3')]
x = np.fromregex(c, r"(\d+)\s+(...)", dt)
- a = np.array([(1312, 'foo'), (1534, 'bar'), (4444, 'qux')], dtype=dt)
+ a = np.array([(1312, 'foo'), (1534, 'bar'), (4444, 'qux')],
+ dtype=dt)
assert_array_equal(x, a)
def test_record_3(self):
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 7bf71ca13..6b4dc98e6 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -19,7 +19,7 @@ Improvements suggested by Reggie Dugard (reggie_AT_merfinllc_DOT_com)
__author__ = "Pierre GF Gerard-Marchant"
__docformat__ = "restructuredtext en"
-__all__ = ['MAError', 'MaskType', 'MaskedArray',
+__all__ = ['MAError', 'MaskError', 'MaskType', 'MaskedArray',
'bool_',
'abs', 'absolute', 'add', 'all', 'allclose', 'allequal', 'alltrue',
'amax', 'amin', 'anom', 'anomalies', 'any', 'arange',
@@ -28,13 +28,14 @@ __all__ = ['MAError', 'MaskType', 'MaskedArray',
'array', 'asarray','asanyarray',
'bitwise_and', 'bitwise_or', 'bitwise_xor',
'ceil', 'choose', 'clip', 'common_fill_value', 'compress',
- 'compressed', 'concatenate', 'conjugate', 'cos', 'cosh', 'count',
- 'default_fill_value', 'diagonal', 'divide', 'dump', 'dumps',
- 'empty', 'empty_like', 'equal', 'exp',
- 'fabs', 'fmod', 'filled', 'floor', 'floor_divide','fix_invalid',
- 'frombuffer', 'fromfunction',
+ 'compressed', 'concatenate', 'conjugate', 'copy', 'cos', 'cosh',
+ 'count', 'cumprod', 'cumsum',
+ 'default_fill_value', 'diag', 'diagonal', 'divide', 'dump', 'dumps',
+ 'empty', 'empty_like', 'equal', 'exp', 'expand_dims',
+ 'fabs', 'flatten_mask', 'fmod', 'filled', 'floor', 'floor_divide',
+ 'fix_invalid', 'frombuffer', 'fromfunction',
'getdata','getmask', 'getmaskarray', 'greater', 'greater_equal',
- 'hypot',
+ 'harden_mask', 'hypot',
'identity', 'ids', 'indices', 'inner', 'innerproduct',
'isMA', 'isMaskedArray', 'is_mask', 'is_masked', 'isarray',
'left_shift', 'less', 'less_equal', 'load', 'loads', 'log', 'log10',
@@ -49,12 +50,13 @@ __all__ = ['MAError', 'MaskType', 'MaskedArray',
'mod', 'multiply',
'negative', 'nomask', 'nonzero', 'not_equal',
'ones', 'outer', 'outerproduct',
- 'power', 'product', 'ptp', 'put', 'putmask',
+ 'power', 'prod', 'product', 'ptp', 'put', 'putmask',
'rank', 'ravel', 'remainder', 'repeat', 'reshape', 'resize',
- 'right_shift', 'round_',
- 'set_fill_value', 'shape', 'sin', 'sinh', 'size', 'sometrue', 'sort',
- 'sqrt', 'std', 'subtract', 'sum', 'swapaxes',
- 'take', 'tan', 'tanh', 'transpose', 'true_divide',
+ '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']
@@ -95,12 +97,31 @@ def doc_note(initialdoc, note):
"""
return newdoc % (initialdoc, note)
+def get_object_signature(obj):
+ """
+ Get the signature from obj
+ """
+ import inspect
+ try:
+ sig = inspect.formatargspec(*inspect.getargspec(obj))
+ except TypeError, errmsg:
+ msg = "Unable to retrieve the signature of %s '%s'\n"\
+ "(Initial error message: %s)"
+# warnings.warn(msg % (type(obj),
+# getattr(obj, '__name__', '???'),
+# errmsg))
+ sig = ''
+ return sig
+
#####--------------------------------------------------------------------------
#---- --- Exceptions ---
#####--------------------------------------------------------------------------
class MAError(Exception):
"Class for MA related errors."
pass
+class MaskError(MAError):
+ "Class for mask related errors."
+ pass
#####--------------------------------------------------------------------------
@@ -514,17 +535,20 @@ class _MaskedUnaryOperation:
# ... but np.putmask looks more efficient, despite the copy.
np.putmask(d1, dm, self.fill)
# Take care of the masked singletong first ...
- if not m.ndim and m:
+ if (not m.ndim) and m:
return masked
- # Get the result class .......................
- if isinstance(a, MaskedArray):
- subtype = type(a)
+ elif m is nomask:
+ result = self.f(d1, *args, **kwargs)
else:
- subtype = MaskedArray
- # Get the result as a view of the subtype ...
- result = self.f(d1, *args, **kwargs).view(subtype)
- # Fix the mask if we don't have a scalar
- if result.ndim > 0:
+ result = np.where(m, d1, self.f(d1, *args, **kwargs))
+ # If result is not a scalar
+ if result.ndim:
+ # Get the result subclass:
+ if isinstance(a, MaskedArray):
+ subtype = type(a)
+ else:
+ subtype = MaskedArray
+ result = result.view(subtype)
result._mask = m
result._update_from(a)
return result
@@ -563,19 +587,45 @@ class _MaskedBinaryOperation:
def __call__ (self, a, b, *args, **kwargs):
"Execute the call behavior."
m = mask_or(getmask(a), getmask(b))
- (d1, d2) = (get_data(a), get_data(b))
- result = self.f(d1, d2, *args, **kwargs).view(get_masked_subclass(a, b))
- if len(result.shape):
- if m is not nomask:
- result._mask = make_mask_none(result.shape)
- result._mask.flat = m
+ (da, db) = (getdata(a), getdata(b))
+ # Easy case: there's no mask...
+ if m is nomask:
+ result = self.f(da, db, *args, **kwargs)
+ # There are some masked elements: run only on the unmasked
+ else:
+ result = np.where(m, da, self.f(da, db, *args, **kwargs))
+ # Transforms to a (subclass of) MaskedArray if we don't have a scalar
+ if result.shape:
+ result = result.view(get_masked_subclass(a, b))
+ result._mask = make_mask_none(result.shape)
+ result._mask.flat = m
if isinstance(a, MaskedArray):
result._update_from(a)
if isinstance(b, MaskedArray):
result._update_from(b)
+ # ... or return masked if we have a scalar and the common mask is True
elif m:
return masked
return result
+#
+# result = self.f(d1, d2, *args, **kwargs).view(get_masked_subclass(a, b))
+# if len(result.shape):
+# if m is not nomask:
+# result._mask = make_mask_none(result.shape)
+# result._mask.flat = m
+# #!!!!!
+# # Force m to be at least 1D
+# m.shape = m.shape or (1,)
+# print "Resetting data"
+# result.data[m].flat = d1.flat
+# #!!!!!
+# if isinstance(a, MaskedArray):
+# result._update_from(a)
+# if isinstance(b, MaskedArray):
+# result._update_from(b)
+# elif m:
+# return masked
+# return result
def reduce(self, target, axis=0, dtype=None):
"""Reduce `target` along the given `axis`."""
@@ -618,11 +668,13 @@ class _MaskedBinaryOperation:
m = umath.logical_or.outer(ma, mb)
if (not m.ndim) and m:
return masked
- rcls = get_masked_subclass(a, b)
- # We could fill the arguments first, butis it useful ?
- # d = self.f.outer(filled(a, self.fillx), filled(b, self.filly)).view(rcls)
- d = self.f.outer(getdata(a), getdata(b)).view(rcls)
- if d.ndim > 0:
+ (da, db) = (getdata(a), getdata(b))
+ if m is nomask:
+ d = self.f.outer(da, db)
+ else:
+ d = np.where(m, da, self.f.outer(da, db))
+ if d.shape:
+ d = d.view(get_masked_subclass(a, b))
d._mask = m
return d
@@ -634,7 +686,7 @@ class _MaskedBinaryOperation:
if isinstance(target, MaskedArray):
tclass = type(target)
else:
- tclass = masked_array
+ tclass = MaskedArray
t = filled(target, self.filly)
return self.f.accumulate(t, axis).view(tclass)
@@ -643,7 +695,8 @@ class _MaskedBinaryOperation:
#..............................................................................
class _DomainedBinaryOperation:
- """Define binary operations that have a domain, like divide.
+ """
+ Define binary operations that have a domain, like divide.
They have no reduce, outer or accumulate.
@@ -668,25 +721,29 @@ class _DomainedBinaryOperation:
ufunc_domain[dbfunc] = domain
ufunc_fills[dbfunc] = (fillx, filly)
- def __call__(self, a, b):
+ def __call__(self, a, b, *args, **kwargs):
"Execute the call behavior."
ma = getmask(a)
mb = getmask(b)
- d1 = getdata(a)
- d2 = get_data(b)
- t = narray(self.domain(d1, d2), copy=False)
+ da = getdata(a)
+ db = getdata(b)
+ t = narray(self.domain(da, db), copy=False)
if t.any(None):
mb = mask_or(mb, t)
# The following line controls the domain filling
- if t.size == d2.size:
- d2 = np.where(t, self.filly, d2)
+ if t.size == db.size:
+ db = np.where(t, self.filly, db)
else:
- d2 = np.where(np.resize(t, d2.shape), self.filly, d2)
+ db = np.where(np.resize(t, db.shape), self.filly, db)
m = mask_or(ma, mb)
if (not m.ndim) and m:
return masked
- result = self.f(d1, d2).view(get_masked_subclass(a, b))
- if result.ndim > 0:
+ elif (m is nomask):
+ result = self.f(da, db, *args, **kwargs)
+ else:
+ result = np.where(m, da, self.f(da, db, *args, **kwargs))
+ if result.shape:
+ result = result.view(get_masked_subclass(a, b))
result._mask = m
if isinstance(a, MaskedArray):
result._update_from(a)
@@ -780,22 +837,29 @@ def make_mask_descr(ndtype):
Each field is set to a bool.
"""
+ def _make_descr(datatype):
+ "Private function allowing recursion."
+ # Do we have some name fields ?
+ if datatype.names:
+ descr = []
+ for name in datatype.names:
+ field = datatype.fields[name]
+ if len(field) == 3:
+ # Prepend the title to the name
+ name = (field[-1], name)
+ descr.append((name, _make_descr(field[0])))
+ return descr
+ # Is this some kind of composite a la (np.float,2)
+ elif datatype.subdtype:
+ mdescr = list(datatype.subdtype)
+ mdescr[0] = np.dtype(bool)
+ return tuple(mdescr)
+ else:
+ return np.bool
# Make sure we do have a dtype
if not isinstance(ndtype, np.dtype):
ndtype = np.dtype(ndtype)
- # Do we have some name fields ?
- if ndtype.names:
- mdescr = [list(_) for _ in ndtype.descr]
- for m in mdescr:
- m[1] = '|b1'
- return np.dtype([tuple(_) for _ in mdescr])
- # Is this some kind of composite a la (np.float,2)
- elif ndtype.subdtype:
- mdescr = list(ndtype.subdtype)
- mdescr[0] = np.dtype(bool)
- return np.dtype(tuple(mdescr))
- else:
- return MaskType
+ return np.dtype(_make_descr(ndtype))
def get_mask(a):
"""Return the mask of a, if any, or nomask.
@@ -944,6 +1008,61 @@ def mask_or (m1, m2, copy=False, shrink=True):
return make_mask(umath.logical_or(m1, m2), copy=copy, shrink=shrink)
+def flatten_mask(mask):
+ """
+ Returns a completely flattened version of the mask, where nested fields
+ are collapsed.
+
+ Parameters
+ ----------
+ mask : array_like
+ Array of booleans
+
+ Returns
+ -------
+ flattened_mask : ndarray
+ Boolean array.
+
+ Examples
+ --------
+ >>> mask = np.array([0, 0, 1], dtype=np.bool)
+ >>> flatten_mask(mask)
+ array([False, False, True], dtype=bool)
+ >>> mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)])
+ >>> flatten_mask(mask)
+ array([False, False, False, True], dtype=bool)
+ >>> mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])]
+ >>> mask = np.array([(0, (0, 0)), (0, (0, 1))], dtype=mdtype)
+ >>> 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
+ if mnames:
+ return [flatten_mask(mask[name]) for name in mnames]
+ else:
+ return mask
+ #
+ def _flatsequence(sequence):
+ "Generates a flattened version of the sequence."
+ try:
+ for element in sequence:
+ if hasattr(element, '__iter__'):
+ for f in _flatsequence(element):
+ yield f
+ else:
+ yield element
+ except TypeError:
+ yield sequence
+ #
+ mask = np.asarray(mask)
+ flattened = _flatsequence(_flatmask(mask))
+ return np.array([_ for _ in flattened], dtype=bool)
+
+
#####--------------------------------------------------------------------------
#--- --- Masking functions ---
#####--------------------------------------------------------------------------
@@ -1208,8 +1327,8 @@ class _arraymethod(object):
#
def getdoc(self):
"Return the doc of the function (from the doc of the method)."
- methdoc = getattr(ndarray, self.__name__, None)
- methdoc = getattr(np, self.__name__, methdoc)
+ methdoc = getattr(ndarray, self.__name__, None) or \
+ getattr(np, self.__name__, None)
if methdoc is not None:
return methdoc.__doc__
#
@@ -1327,7 +1446,7 @@ class MaskedArray(ndarray):
# Process data............
_data = np.array(data, dtype=dtype, copy=copy, subok=True, ndmin=ndmin)
_baseclass = getattr(data, '_baseclass', type(_data))
- # Check that we'ew 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...
@@ -1359,7 +1478,13 @@ class MaskedArray(ndarray):
_data._mask = np.zeros(_data.shape, dtype=mdtype)
# Check whether we missed something
elif isinstance(data, (tuple,list)):
- mask = np.array([getmaskarray(m) for m in data], dtype=mdtype)
+ try:
+ # If data is a sequence of masked array
+ mask = np.array([getmaskarray(m) for m in data],
+ dtype=mdtype)
+ except ValueError:
+ # If data is nested
+ mask = nomask
# Force shrinking of the mask if needed (and possible)
if (mdtype == MaskType) and mask.any():
_data._mask = mask
@@ -1392,7 +1517,7 @@ class MaskedArray(ndarray):
else:
msg = "Mask and data not compatible: data size is %i, "+\
"mask size is %i."
- raise MAError, msg % (nd, nm)
+ raise MaskError, msg % (nd, nm)
copy = True
# Set the mask to the new value
if _data._mask is nomask:
@@ -1404,8 +1529,16 @@ class MaskedArray(ndarray):
_data._sharedmask = not copy
else:
if names_:
- for n in names_:
- _data._mask[n] |= mask[n]
+ def _recursive_or(a, b):
+ "do a|=b on each field of a, recursively"
+ for name in a.dtype.names:
+ (af, bf) = (a[name], b[name])
+ if af.dtype.names:
+ _recursive_or(af, bf)
+ else:
+ af |= bf
+ return
+ _recursive_or(_data._mask, mask)
else:
_data._mask = np.logical_or(mask, _data._mask)
_data._sharedmask = False
@@ -1601,7 +1734,7 @@ class MaskedArray(ndarray):
# A record ................
if isinstance(dout, np.void):
mask = _mask[indx]
- if mask.view((bool, len(mask.dtype))).any():
+ if flatten_mask(mask).any():
dout = masked_array(dout, mask=mask)
else:
return dout
@@ -1633,7 +1766,7 @@ class MaskedArray(ndarray):
"""
if self is masked:
- raise MAError, 'Cannot alter the masked element.'
+ 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!"
@@ -2146,32 +2279,33 @@ masked_%(name)s(data = %(data)s,
#............................................
def __iadd__(self, other):
"Add other to self in-place."
- ndarray.__iadd__(self._data, getdata(other))
m = getmask(other)
if self._mask is nomask:
self._mask = m
- elif m is not nomask:
- self._mask += m
+ else:
+ if m is not nomask:
+ self._mask += m
+ ndarray.__iadd__(self._data, np.where(self._mask, 0, getdata(other)))
return self
#....
def __isub__(self, other):
"Subtract other from self in-place."
- ndarray.__isub__(self._data, getdata(other))
m = getmask(other)
if self._mask is nomask:
self._mask = m
elif m is not nomask:
self._mask += m
+ ndarray.__isub__(self._data, np.where(self._mask, 0, getdata(other)))
return self
#....
def __imul__(self, other):
"Multiply self by other in-place."
- ndarray.__imul__(self._data, getdata(other))
m = getmask(other)
if self._mask is nomask:
self._mask = m
elif m is not nomask:
self._mask += m
+ ndarray.__imul__(self._data, np.where(self._mask, 1, getdata(other)))
return self
#....
def __idiv__(self, other):
@@ -2184,21 +2318,25 @@ masked_%(name)s(data = %(data)s,
if dom_mask.any():
(_, fval) = ufunc_fills[np.divide]
other_data = np.where(dom_mask, fval, other_data)
- ndarray.__idiv__(self._data, other_data)
- self._mask = mask_or(self._mask, new_mask)
+# self._mask = mask_or(self._mask, new_mask)
+ self._mask |= new_mask
+ ndarray.__idiv__(self._data, np.where(self._mask, 1, other_data))
return self
#...
def __ipow__(self, other):
"Raise self to the power other, in place"
- _data = self._data
other_data = getdata(other)
other_mask = getmask(other)
- ndarray.__ipow__(_data, other_data)
- invalid = np.logical_not(np.isfinite(_data))
+ ndarray.__ipow__(self._data, np.where(self._mask, 1, other_data))
+ invalid = np.logical_not(np.isfinite(self._data))
+ if invalid.any():
+ if self._mask is not nomask:
+ self._mask |= invalid
+ else:
+ self._mask = invalid
+ np.putmask(self._data, invalid, self.fill_value)
new_mask = mask_or(other_mask, invalid)
self._mask = mask_or(self._mask, new_mask)
- # The following line is potentially problematic, as we change _data...
- np.putmask(self._data, invalid, self.fill_value)
return self
#............................................
def __float__(self):
@@ -2217,7 +2355,7 @@ masked_%(name)s(data = %(data)s,
raise TypeError("Only length-1 arrays can be converted "\
"to Python scalars")
elif self._mask:
- raise MAError, 'Cannot convert masked element to a Python int.'
+ raise MaskError, 'Cannot convert masked element to a Python int.'
return int(self.item())
#............................................
def get_imag(self):
@@ -2560,9 +2698,7 @@ masked_%(name)s(data = %(data)s,
def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None):
"""
- Return the sum along the offset diagonal of the array's
- indicated `axis1` and `axis2`.
-
+ (this docstring should be overwritten)
"""
#!!!: implement out + test!
m = self._mask
@@ -2573,7 +2709,7 @@ masked_%(name)s(data = %(data)s,
else:
D = self.diagonal(offset=offset, axis1=axis1, axis2=axis2)
return D.astype(dtype).filled(0).sum(axis=None, out=out)
-
+ trace.__doc__ = ndarray.trace.__doc__
def sum(self, axis=None, dtype=None, out=None):
"""
@@ -2668,8 +2804,8 @@ masked_%(name)s(data = %(data)s,
have the same shape and buffer length as the expected output
but the type will be cast if necessary.
- Warning
- -------
+ Warnings
+ --------
The mask is lost if out is not a valid :class:`MaskedArray` !
Returns
@@ -2678,8 +2814,8 @@ masked_%(name)s(data = %(data)s,
A new array holding the result is returned unless ``out`` is
specified, in which case a reference to ``out`` is returned.
- Example
- -------
+ Examples
+ --------
>>> marr = np.ma.array(np.arange(10), mask=[0,0,0,1,1,1,0,0,0,0])
>>> print marr.cumsum()
[0 1 3 -- -- -- 9 16 24 33]
@@ -2824,7 +2960,14 @@ masked_%(name)s(data = %(data)s,
def mean(self, axis=None, dtype=None, out=None):
- ""
+ """
+ Returns the average of the array elements along given axis.
+ Refer to `numpy.mean` for full documentation.
+
+ See Also
+ --------
+ numpy.mean : equivalent function'
+ """
if self._mask is nomask:
result = super(MaskedArray, self).mean(axis=axis, dtype=dtype)
else:
@@ -2840,7 +2983,6 @@ masked_%(name)s(data = %(data)s,
outmask.flat = getattr(result, '_mask', nomask)
return out
return result
- mean.__doc__ = ndarray.mean.__doc__
def anom(self, axis=None, dtype=None):
"""
@@ -2885,6 +3027,10 @@ masked_%(name)s(data = %(data)s,
if out is not None:
if isinstance(out, MaskedArray):
out.__setmask__(True)
+ elif out.dtype.kind in 'biu':
+ errmsg = "Masked data information would be lost in one or "\
+ "more location."
+ raise MaskError(errmsg)
else:
out.flat = np.nan
return out
@@ -2937,47 +3083,36 @@ masked_%(name)s(data = %(data)s,
#............................................
def argsort(self, axis=None, fill_value=None, kind='quicksort',
order=None):
- """Return an ndarray of indices that sort the array along the
- specified axis. Masked values are filled beforehand to
- fill_value.
+ """
+ Return an ndarray of indices that sort the array along the
+ specified axis. Masked values are filled beforehand to
+ fill_value.
- Parameters
- ----------
- axis : int, optional
- Axis to be indirectly sorted.
- If not given, uses a flatten version of the array.
- fill_value : {var}
- Value used to fill in the masked values.
- If not given, self.fill_value is used instead.
- kind : {string}
- Sorting algorithm (default 'quicksort')
- Possible values: 'quicksort', 'mergesort', or 'heapsort'
+ Parameters
+ ----------
+ axis : int, optional
+ Axis along which to sort. If not given, the flattened array is used.
+ kind : {'quicksort', 'mergesort', 'heapsort'}, optional
+ Sorting algorithm.
+ order : list, optional
+ When `a` is an array with fields defined, this argument specifies
+ which fields to compare first, second, etc. Not all fields need be
+ specified.
+ Returns
+ -------
+ index_array : ndarray, int
+ Array of indices that sort `a` along the specified axis.
+ In other words, ``a[index_array]`` yields a sorted `a`.
+
+ See Also
+ --------
+ sort : Describes sorting algorithms used.
+ lexsort : Indirect stable sort with multiple keys.
+ ndarray.sort : Inplace sort.
- Notes
- -----
- This method executes an indirect sort along the given axis
- using the algorithm specified by the kind keyword. It returns
- an array of indices of the same shape as 'a' that index data
- along the given axis in sorted order.
-
- The various sorts are characterized by average speed, worst
- case performance need for work space, and whether they are
- stable. A stable sort keeps items with the same key in the
- same relative order. The three available algorithms have the
- following properties:
-
- |------------------------------------------------------|
- | kind | speed | worst case | work space | stable|
- |------------------------------------------------------|
- |'quicksort'| 1 | O(n^2) | 0 | no |
- |'mergesort'| 2 | O(n*log(n)) | ~n/2 | yes |
- |'heapsort' | 3 | O(n*log(n)) | 0 | no |
- |------------------------------------------------------|
-
- All the sort algorithms make temporary copies of the data when
- the sort is not along the last axis. Consequently, sorts along
- the last axis are faster and use less space than sorts along
- other axis.
+ Notes
+ -----
+ See `sort` for notes on the different sorting algorithms.
"""
if fill_value is None:
@@ -3069,19 +3204,21 @@ masked_%(name)s(data = %(data)s,
def sort(self, axis=-1, kind='quicksort', order=None,
endwith=True, fill_value=None):
"""
- Sort along the given axis.
+ Return a sorted copy of an array.
Parameters
----------
- axis : {int}, optional
- Axis to be indirectly sorted.
- kind : {'quicksort', 'mergesort', or 'heapsort'}, optional
- Sorting algorithm (default 'quicksort')
- Possible values: 'quicksort', 'mergesort', or 'heapsort'.
- order : {None, var}
- If a has fields defined, then the order keyword can be the field name
- to sort on or a list (or tuple) of field names to indicate the order
- that fields should be used to define the sort.
+ a : array_like
+ Array to be sorted.
+ axis : int or None, 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).
@@ -3091,29 +3228,67 @@ masked_%(name)s(data = %(data)s,
Returns
-------
- - When used as method, returns None.
- - When used as a function, returns an array.
+ 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.
Notes
-----
- This method sorts 'a' in place along the given axis using
- the algorithm specified by the kind keyword.
-
- The various sorts may characterized by average speed,
- worst case performance need for work space, and whether
- they are stable. A stable sort keeps items with the same
- key in the same relative order and is most useful when
- used w/ argsort where the key might differ from the items
- being sorted. The three available algorithms have the
- following properties:
-
- |------------------------------------------------------|
- | kind | speed | worst case | work space | stable|
- |------------------------------------------------------|
- |'quicksort'| 1 | O(n^2) | 0 | no |
- |'mergesort'| 2 | O(n*log(n)) | ~n/2 | yes |
- |'heapsort' | 3 | O(n*log(n)) | 0 | no |
- |------------------------------------------------------|
+ The various sorting algorithms are characterized by their average speed,
+ worst case performance, work space size, and whether they are stable. A
+ stable sort keeps items with the same key in the same relative
+ order. The three available algorithms have the following
+ properties:
+
+ =========== ======= ============= ============ =======
+ kind speed worst case work space stable
+ =========== ======= ============= ============ =======
+ 'quicksort' 1 O(n^2) 0 no
+ 'mergesort' 2 O(n*log(n)) ~n/2 yes
+ 'heapsort' 3 O(n*log(n)) 0 no
+ =========== ======= ============= ============ =======
+
+ All the sort algorithms make temporary copies of the data when
+ sorting along any but the last axis. Consequently, sorting along
+ the last axis is faster and uses less space than sorting along
+ any other axis.
+
+ Examples
+ --------
+ >>> a = np.array([[1,4],[3,1]])
+ >>> np.sort(a) # sort along the last axis
+ array([[1, 4],
+ [1, 3]])
+ >>> np.sort(a, axis=None) # sort the flattened array
+ array([1, 1, 3, 4])
+ >>> np.sort(a, axis=0) # sort along the first axis
+ array([[1, 1],
+ [3, 4]])
+
+ Use the `order` keyword to specify a field to use when sorting a
+ structured array:
+
+ >>> dtype = [('name', 'S10'), ('height', float), ('age', int)]
+ >>> values = [('Arthur', 1.8, 41), ('Lancelot', 1.9, 38),
+ ... ('Galahad', 1.7, 38)]
+ >>> a = np.array(values, dtype=dtype) # create a structured array
+ >>> np.sort(a, order='height') # doctest: +SKIP
+ array([('Galahad', 1.7, 38), ('Arthur', 1.8, 41),
+ ('Lancelot', 1.8999999999999999, 38)],
+ dtype=[('name', '|S10'), ('height', '<f8'), ('age', '<i4')])
+
+ Sort by age, then height if ages are equal:
+
+ >>> np.sort(a, order=['age', 'height']) # doctest: +SKIP
+ array([('Galahad', 1.7, 38), ('Lancelot', 1.8999999999999999, 38),
+ ('Arthur', 1.8, 41)],
+ dtype=[('name', '|S10'), ('height', '<f8'), ('age', '<i4')])
"""
if self._mask is nomask:
@@ -3189,6 +3364,10 @@ masked_%(name)s(data = %(data)s,
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
else:
+ if out.dtype.kind in 'biu':
+ errmsg = "Masked data information would be lost in one or more"\
+ " location."
+ raise MaskError(errmsg)
np.putmask(out, newmask, np.nan)
return out
@@ -3251,6 +3430,11 @@ masked_%(name)s(data = %(data)s,
outmask = out._mask = make_mask_none(out.shape)
outmask.flat = newmask
else:
+
+ if out.dtype.kind in 'biu':
+ errmsg = "Masked data information would be lost in one or more"\
+ " location."
+ raise MaskError(errmsg)
np.putmask(out, newmask, np.nan)
return out
@@ -3633,12 +3817,16 @@ class _frommethod:
def __init__(self, methodname):
self.__name__ = methodname
self.__doc__ = self.getdoc()
+ #
def getdoc(self):
"Return the doc of the function (from the doc of the method)."
- try:
- return getattr(MaskedArray, self.__name__).__doc__
- except:
- return getattr(np, self.__name__).__doc__
+ meth = getattr(MaskedArray, self.__name__, None) or\
+ 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))
+ return doc
+ #
def __call__(self, a, *args, **params):
if isinstance(a, MaskedArray):
return getattr(a, self.__name__).__call__(*args, **params)
@@ -3657,25 +3845,29 @@ class _frommethod:
all = _frommethod('all')
anomalies = anom = _frommethod('anom')
any = _frommethod('any')
-conjugate = _frommethod('conjugate')
-ids = _frommethod('ids')
-nonzero = _frommethod('nonzero')
+compress = _frommethod('compress')
+cumprod = _frommethod('cumprod')
+cumsum = _frommethod('cumsum')
+copy = _frommethod('copy')
diagonal = _frommethod('diagonal')
+harden_mask = _frommethod('harden_mask')
+ids = _frommethod('ids')
maximum = _maximum_operation()
mean = _frommethod('mean')
minimum = _minimum_operation ()
+nonzero = _frommethod('nonzero')
+prod = _frommethod('prod')
product = _frommethod('prod')
-ptp = _frommethod('ptp')
ravel = _frommethod('ravel')
repeat = _frommethod('repeat')
-round = _frommethod('round')
+shrink_mask = _frommethod('shrink_mask')
+soften_mask = _frommethod('soften_mask')
std = _frommethod('std')
sum = _frommethod('sum')
swapaxes = _frommethod('swapaxes')
take = _frommethod('take')
trace = _frommethod('trace')
var = _frommethod('var')
-compress = _frommethod('compress')
#..............................................................................
def power(a, b, third=None):
@@ -3683,7 +3875,7 @@ def power(a, b, third=None):
"""
if third is not None:
- raise MAError, "3-argument power not supported."
+ raise MaskError, "3-argument power not supported."
# Get the masks
ma = getmask(a)
mb = getmask(b)
@@ -3697,22 +3889,22 @@ def power(a, b, third=None):
else:
basetype = MaskedArray
# Get the result and view it as a (subclass of) MaskedArray
- result = umath.power(fa, fb).view(basetype)
+ result = np.where(m, fa, umath.power(fa, fb)).view(basetype)
+ result._update_from(a)
# Find where we're in trouble w/ NaNs and Infs
invalid = np.logical_not(np.isfinite(result.view(ndarray)))
- # Retrieve some extra attributes if needed
- if isinstance(result, MaskedArray):
- result._update_from(a)
# Add the initial mask
if m is not nomask:
- if np.isscalar(result):
+ if not (result.ndim):
return masked
+ m |= invalid
result._mask = m
# Fix the invalid parts
if invalid.any():
if not result.ndim:
return masked
- result[invalid] = masked
+ elif result._mask is nomask:
+ result._mask = invalid
result._data[invalid] = result.fill_value
return result
@@ -3825,6 +4017,40 @@ def count(a, axis = None):
count.__doc__ = MaskedArray.count.__doc__
+def diag(v, k=0):
+ """
+ Extract a diagonal or construct a diagonal array.
+
+ Parameters
+ ----------
+ v : array_like
+ If `v` is a 2-dimensional array, return a copy of
+ its `k`-th diagonal. If `v` is a 1-dimensional array,
+ return a 2-dimensional array with `v` on the `k`-th diagonal.
+ k : int, optional
+ Diagonal in question. The defaults is 0.
+
+ Examples
+ --------
+ >>> x = np.arange(9).reshape((3,3))
+ >>> x
+ array([[0, 1, 2],
+ [3, 4, 5],
+ [6, 7, 8]])
+ >>> np.diag(x)
+ array([0, 4, 8])
+ >>> np.diag(np.diag(x))
+ array([[0, 0, 0],
+ [0, 4, 0],
+ [0, 0, 8]])
+
+ """
+ output = np.diag(v, k).view(MaskedArray)
+ if getmask(v) is not nomask:
+ output._mask = np.diag(v._mask, k)
+ return output
+
+
def expand_dims(x, axis):
"""
Expand the shape of the array by including a new axis before
@@ -4085,7 +4311,8 @@ def choose (indices, choices, out=None, mode='raise'):
def round_(a, decimals=0, out=None):
- """Return a copy of a, rounded to 'decimals' places.
+ """
+ Return a copy of a, rounded to 'decimals' places.
When 'decimals' is negative, it specifies the number of positions
to the left of the decimal point. The real and imaginary parts of
@@ -4114,9 +4341,20 @@ def round_(a, decimals=0, out=None):
if hasattr(out, '_mask'):
out._mask = getmask(a)
return out
-
+round = round_
def inner(a, b):
+ """
+ Returns the inner product of a and b for arrays of floating point types.
+
+ Like the generic NumPy equivalent the product sum is over the last dimension
+ of a and b.
+
+ Notes
+ -----
+ The first argument is not conjugated.
+
+ """
fa = filled(a, 0)
fb = filled(b, 0)
if len(fa.shape) == 0:
@@ -4167,7 +4405,7 @@ def allequal (a, b, fill_value=True):
def allclose (a, b, masked_equal=True, rtol=1.e-5, atol=1.e-8, fill_value=None):
"""
- Returns True if two arrays are element-wise equal within a tolerance.
+ Returns True if two arrays are element-wise equal within a tolerance.
The tolerance values are positive, typically very small numbers. The
relative difference (`rtol` * `b`) and the absolute difference (`atol`)
@@ -4332,9 +4570,18 @@ class _convert2ma:
def __init__(self, funcname):
self._func = getattr(np, funcname)
self.__doc__ = self.getdoc()
+ #
def getdoc(self):
"Return the doc of the function (from the doc of the method)."
- return self._func.__doc__
+ doc = getattr(self._func, '__doc__', None)
+ sig = get_object_signature(self._func)
+ if doc:
+ # Add the signature of the function at the beginning of the doc
+ if sig:
+ sig = "%s%s\n" % (self._func.__name__, sig)
+ doc = sig + doc
+ return doc
+ #
def __call__(self, a, *args, **params):
return self._func.__call__(a, *args, **params).view(MaskedArray)
@@ -4348,5 +4595,6 @@ identity = _convert2ma('identity')
indices = np.indices
ones = _convert2ma('ones')
zeros = _convert2ma('zeros')
+squeeze = np.squeeze
###############################################################################
diff --git a/numpy/ma/extras.py b/numpy/ma/extras.py
index d88022888..cf80180e4 100644
--- a/numpy/ma/extras.py
+++ b/numpy/ma/extras.py
@@ -16,15 +16,15 @@ __all__ = ['apply_along_axis', 'atleast_1d', 'atleast_2d', 'atleast_3d',
'column_stack','compress_cols','compress_rowcols', 'compress_rows',
'count_masked', 'corrcoef', 'cov',
'diagflat', 'dot','dstack',
- 'ediff1d','expand_dims',
- 'flatnotmasked_contiguous','flatnotmasked_edges',
- 'hsplit','hstack',
- 'mask_cols','mask_rowcols','mask_rows','masked_all','masked_all_like',
- 'median','mr_',
- 'notmasked_contiguous','notmasked_edges',
+ 'ediff1d',
+ 'flatnotmasked_contiguous', 'flatnotmasked_edges',
+ 'hsplit', 'hstack',
+ 'mask_cols', 'mask_rowcols', 'mask_rows', 'masked_all',
+ 'masked_all_like', 'median', 'mr_',
+ 'notmasked_contiguous', 'notmasked_edges',
'polyfit',
'row_stack',
- 'vander','vstack',
+ 'vander', 'vstack',
]
from itertools import groupby
@@ -32,15 +32,15 @@ import warnings
import core as ma
from core import MaskedArray, MAError, add, array, asarray, concatenate, count,\
- filled, getmask, getmaskarray, masked, masked_array, mask_or, nomask, ones,\
- sort, zeros
+ filled, getmask, getmaskarray, make_mask_descr, masked, masked_array,\
+ mask_or, nomask, ones, sort, zeros
#from core import *
import numpy as np
from numpy import ndarray, array as nxarray
import numpy.core.umath as umath
from numpy.lib.index_tricks import AxisConcatenator
-from numpy.lib.polynomial import _lstsq
+from numpy.linalg import lstsq
#...............................................................................
def issequence(seq):
@@ -77,7 +77,7 @@ def masked_all(shape, dtype=float):
"""
a = masked_array(np.empty(shape, dtype),
- mask=np.ones(shape, bool))
+ mask=np.ones(shape, make_mask_descr(dtype)))
return a
def masked_all_like(arr):
@@ -85,8 +85,8 @@ def masked_all_like(arr):
the array `a`, where all the data are masked.
"""
- a = masked_array(np.empty_like(arr),
- mask=np.ones(arr.shape, bool))
+ a = np.empty_like(arr).view(MaskedArray)
+ a._mask = np.ones(a.shape, dtype=make_mask_descr(a.dtype))
return a
@@ -102,11 +102,13 @@ class _fromnxfunction:
def getdoc(self):
"Retrieves the __doc__ string from the function."
- inidoc = getattr(np, self.__name__).__doc__
- if inidoc:
+ npfunc = getattr(np, self.__name__, None)
+ doc = getattr(npfunc, '__doc__', None)
+ if doc:
+ sig = self.__name__ + ma.get_object_signature(npfunc)
locdoc = "Notes\n-----\nThe function is applied to both the _data"\
" and the _mask, if any."
- return '\n'.join((inidoc, locdoc))
+ return '\n'.join((sig, doc, locdoc))
return
@@ -147,16 +149,6 @@ hsplit = _fromnxfunction('hsplit')
diagflat = _fromnxfunction('diagflat')
-def expand_dims(a, axis):
- """Expands the shape of a by including newaxis before axis.
- """
- if not isinstance(a, MaskedArray):
- return np.expand_dims(a, axis)
- elif getmask(a) is nomask:
- return np.expand_dims(a, axis).view(MaskedArray)
- m = getmaskarray(a)
- return masked_array(np.expand_dims(a, axis),
- mask=np.expand_dims(m, axis))
#####--------------------------------------------------------------------------
#----
@@ -172,9 +164,8 @@ def flatten_inplace(seq):
def apply_along_axis(func1d, axis, arr, *args, **kwargs):
- """Execute func1d(arr[i],*args) where func1d takes 1-D arrays and
- arr is an N-d array. i varies so as to apply the function along
- the given axis for each 1-d subarray in arr.
+ """
+ (This docstring should be overwritten)
"""
arr = array(arr, copy=False, subok=True)
nd = arr.ndim
@@ -257,6 +248,8 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
result = asarray(outarr, dtype=max_dtypes)
result.fill_value = ma.default_fill_value(result)
return result
+apply_along_axis.__doc__ = np.apply_along_axis.__doc__
+
def average(a, axis=None, weights=None, returned=False):
"""Average the array over the given axis.
@@ -446,23 +439,25 @@ def median(a, axis=None, out=None, overwrite_input=False):
#..............................................................................
def compress_rowcols(x, axis=None):
- """Suppress the rows and/or columns of a 2D array that contains
+ """
+ Suppress the rows and/or columns of a 2D array that contains
masked values.
The suppression behavior is selected with the `axis`parameter.
+
- If axis is None, rows and columns are suppressed.
- If axis is 0, only rows are suppressed.
- If axis is 1 or -1, only columns are suppressed.
Parameters
----------
- axis : int, optional
- Axis along which to perform the operation.
- If None, applies to a flattened version of the array.
+ axis : int, optional
+ Axis along which to perform the operation.
+ If None, applies to a flattened version of the array.
Returns
-------
- compressed_array : an ndarray.
+ compressed_array : an ndarray.
"""
x = asarray(x)
@@ -499,9 +494,10 @@ def compress_cols(a):
return compress_rowcols(a, 1)
def mask_rowcols(a, axis=None):
- """Mask whole rows and/or columns of a 2D array that contain
+ """
+ Mask whole rows and/or columns of a 2D array that contain
masked values. The masking behavior is selected with the
- `axis`parameter.
+ `axis` parameter.
- If axis is None, rows and columns are masked.
- If axis is 0, only rows are masked.
@@ -509,13 +505,13 @@ def mask_rowcols(a, axis=None):
Parameters
----------
- axis : int, optional
- Axis along which to perform the operation.
- If None, applies to a flattened version of the array.
+ axis : int, optional
+ Axis along which to perform the operation.
+ If None, applies to a flattened version of the array.
Returns
-------
- a *pure* ndarray.
+ a *pure* ndarray.
"""
a = asarray(a)
@@ -996,128 +992,20 @@ def notmasked_contiguous(a, axis=None):
#####--------------------------------------------------------------------------
def vander(x, n=None):
- """%s
- Notes
- -----
- Masked values in x will result in rows of zeros.
+ """
+ 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):
"""
- Least squares polynomial fit.
-
- Do a best fit polynomial of degree 'deg' of 'x' to 'y'. Return value is a
- vector of polynomial coefficients [pk ... p1 p0]. Eg, for ``deg = 2``::
-
- p2*x0^2 + p1*x0 + p0 = y1
- p2*x1^2 + p1*x1 + p0 = y1
- p2*x2^2 + p1*x2 + p0 = y2
- .....
- p2*xk^2 + p1*xk + p0 = yk
-
- Parameters
- ----------
- x : array_like
- 1D vector of sample points.
- y : array_like
- 1D vector or 2D array of values to fit. The values should run down the
- columns in the 2D case.
- deg : integer
- Degree of the fitting polynomial
- rcond: {None, float}, optional
- Relative condition number of the fit. Singular values smaller than this
- relative to the largest singular value will be ignored. The defaul value
- is len(x)*eps, where eps is the relative precision of the float type,
- about 2e-16 in most cases.
- full : {False, boolean}, optional
- Switch determining nature of return value. When it is False just the
- coefficients are returned, when True diagnostic information from the
- singular value decomposition is also returned.
-
- Returns
- -------
- coefficients, [residuals, rank, singular_values, rcond] : variable
- When full=False, only the coefficients are returned, running down the
- appropriate colume when y is a 2D array. When full=True, the rank of the
- scaled Vandermonde matrix, its effective rank in light of the rcond
- value, its singular values, and the specified value of rcond are also
- returned.
-
- Warns
- -----
- RankWarning : if rank is reduced and not full output
- The warnings can be turned off by:
- >>> import warnings
- >>> warnings.simplefilter('ignore',np.RankWarning)
-
-
- See Also
- --------
- polyval : computes polynomial values.
-
- Notes
- -----
- If X is a the Vandermonde Matrix computed from x (see
- http://mathworld.wolfram.com/VandermondeMatrix.html), then the
- polynomial least squares solution is given by the 'p' in
-
- X*p = y
-
- where X.shape is a matrix of dimensions (len(x), deg + 1), p is a vector of
- dimensions (deg + 1, 1), and y is a vector of dimensions (len(x), 1).
-
- This equation can be solved as
-
- p = (XT*X)^-1 * XT * y
-
- where XT is the transpose of X and -1 denotes the inverse. However, this
- method is susceptible to rounding errors and generally the singular value
- decomposition of the matrix X is preferred and that is what is done here.
- The singular value method takes a paramenter, 'rcond', which sets a limit on
- the relative size of the smallest singular value to be used in solving the
- equation. This may result in lowering the rank of the Vandermonde matrix, in
- which case a RankWarning is issued. If polyfit issues a RankWarning, try a
- fit of lower degree or replace x by x - x.mean(), both of which will
- generally improve the condition number. The routine already normalizes the
- vector x by its maximum absolute value to help in this regard. The rcond
- parameter can be set to a value smaller than its default, but the resulting
- fit may be spurious. The current default value of rcond is len(x)*eps, where
- eps is the relative precision of the floating type being used, generally
- around 1e-7 and 2e-16 for IEEE single and double precision respectively.
- This value of rcond is fairly conservative but works pretty well when x -
- x.mean() is used in place of x.
-
-
- DISCLAIMER: Power series fits are full of pitfalls for the unwary once the
- degree of the fit becomes large or the interval of sample points is badly
- centered. The problem is that the powers x**n are generally a poor basis for
- the polynomial functions on the sample interval, resulting in a Vandermonde
- matrix is ill conditioned and coefficients sensitive to rounding erros. The
- computation of the polynomial values will also sensitive to rounding errors.
- Consequently, the quality of the polynomial fit should be checked against
- the data whenever the condition number is large. The quality of polynomial
- fits *can not* be taken for granted. If all you want to do is draw a smooth
- curve through the y values and polyfit is not doing the job, try centering
- the sample range or look into scipy.interpolate, which includes some nice
- spline fitting functions that may be of use.
-
- For more info, see
- http://mathworld.wolfram.com/LeastSquaresFittingPolynomial.html,
- but note that the k's and n's in the superscripts and subscripts
- on that page. The linear algebra is correct, however.
-
-
-
- Notes
- -----
- Any masked values in x is propagated in y, and vice-versa.
-
+ Any masked values in x is propagated in y, and vice-versa.
"""
order = int(deg) + 1
x = asarray(x)
@@ -1145,7 +1033,7 @@ def polyfit(x, y, deg, rcond=None, full=False):
x = x / scale
# solve least squares equation for powers of x
v = vander(x, order)
- c, resids, rank, s = _lstsq(v, y.filled(0), rcond)
+ c, resids, rank, s = lstsq(v, y.filled(0), rcond)
# warn on rank reduction, which indicates an ill conditioned matrix
if rank != order and not full:
warnings.warn("Polyfit may be poorly conditioned", np.RankWarning)
@@ -1159,5 +1047,6 @@ def polyfit(x, y, deg, rcond=None, full=False):
return c, resids, rank, s, rcond
else :
return c
+polyfit.__doc__ = ma.doc_note(np.polyfit.__doc__, polyfit.__doc__)
################################################################################
diff --git a/numpy/ma/tests/test_core.py b/numpy/ma/tests/test_core.py
index b51a90712..8a0ca08ac 100644
--- a/numpy/ma/tests/test_core.py
+++ b/numpy/ma/tests/test_core.py
@@ -693,7 +693,7 @@ class TestMaskedArrayArithmetic(TestCase):
def test_minmax_funcs_with_output(self):
"Tests the min/max functions with explicit outputs"
mask = np.random.rand(12).round()
- xm = array(np.random.uniform(0,10,12),mask=mask)
+ xm = array(np.random.uniform(0,10,12), mask=mask)
xm.shape = (3,4)
for funcname in ('min', 'max'):
# Initialize
@@ -701,11 +701,16 @@ class TestMaskedArrayArithmetic(TestCase):
mafunc = getattr(numpy.ma.core, funcname)
# Use the np version
nout = np.empty((4,), dtype=int)
- result = npfunc(xm,axis=0,out=nout)
+ try:
+ result = npfunc(xm, axis=0, out=nout)
+ except MaskError:
+ pass
+ nout = np.empty((4,), dtype=float)
+ result = npfunc(xm, axis=0, out=nout)
self.failUnless(result is nout)
# Use the ma version
nout.fill(-999)
- result = mafunc(xm,axis=0,out=nout)
+ result = mafunc(xm, axis=0, out=nout)
self.failUnless(result is nout)
@@ -820,6 +825,7 @@ class TestMaskedArrayArithmetic(TestCase):
self.failUnless(result is output)
self.failUnless(output[0] is masked)
+
#------------------------------------------------------------------------------
class TestMaskedArrayAttributes(TestCase):
@@ -1235,22 +1241,131 @@ class TestMaskedArrayInPlaceArithmetics(TestCase):
def test_inplace_division_misc(self):
#
- 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.])
- 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]
+ 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, [0.2,1.,1./3.,-1.,-pi/2.,-1.,5.,1.,1.,1.,2.,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])
- assert_equal(xm._data, [1/5.,1.,1./3.,-1.,-pi/2.,-1.,5.,1.,1.,1.,2.,1.])
-
+ assert_equal(z._data, [1.,1.,1.,-1.,-pi/2.,4.,5.,1.,1.,1.,2.,3.])
+ #assert_equal(xm._data, [1/5.,1.,1./3.,-1.,-pi/2.,-1.,5.,1.,1.,1.,2.,1.])
+
+
+ def test_datafriendly_add(self):
+ "Test keeping data w/ (inplace) addition"
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ # Test add w/ scalar
+ xx = x + 1
+ assert_equal(xx.data, [2, 3, 3])
+ assert_equal(xx.mask, [0, 0, 1])
+ # Test iadd w/ scalar
+ x += 1
+ assert_equal(x.data, [2, 3, 3])
+ assert_equal(x.mask, [0, 0, 1])
+ # Test add w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x + array([1, 2, 3], mask=[1, 0, 0])
+ assert_equal(xx.data, [1, 4, 3])
+ assert_equal(xx.mask, [1, 0, 1])
+ # Test iadd w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ x += array([1, 2, 3], mask=[1, 0, 0])
+ assert_equal(x.data, [1, 4, 3])
+ assert_equal(x.mask, [1, 0, 1])
+
+
+ def test_datafriendly_sub(self):
+ "Test keeping data w/ (inplace) subtraction"
+ # Test sub w/ scalar
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x - 1
+ assert_equal(xx.data, [0, 1, 3])
+ assert_equal(xx.mask, [0, 0, 1])
+ # Test isub w/ scalar
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ x -= 1
+ assert_equal(x.data, [0, 1, 3])
+ assert_equal(x.mask, [0, 0, 1])
+ # Test sub w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x - array([1, 2, 3], mask=[1, 0, 0])
+ assert_equal(xx.data, [1, 0, 3])
+ assert_equal(xx.mask, [1, 0, 1])
+ # Test isub w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ x -= array([1, 2, 3], mask=[1, 0, 0])
+ assert_equal(x.data, [1, 0, 3])
+ assert_equal(x.mask, [1, 0, 1])
+
+
+ def test_datafriendly_mul(self):
+ "Test keeping data w/ (inplace) multiplication"
+ # Test mul w/ scalar
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x * 2
+ assert_equal(xx.data, [2, 4, 3])
+ assert_equal(xx.mask, [0, 0, 1])
+ # Test imul w/ scalar
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ x *= 2
+ assert_equal(x.data, [2, 4, 3])
+ assert_equal(x.mask, [0, 0, 1])
+ # Test mul w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x * array([10, 20, 30], mask=[1, 0, 0])
+ assert_equal(xx.data, [1, 40, 3])
+ assert_equal(xx.mask, [1, 0, 1])
+ # Test imul w/ array
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ x *= array([10, 20, 30], mask=[1, 0, 0])
+ assert_equal(x.data, [1, 40, 3])
+ assert_equal(x.mask, [1, 0, 1])
+
+
+ def test_datafriendly_div(self):
+ "Test keeping data w/ (inplace) division"
+ # Test div on scalar
+ x = array([1, 2, 3], mask=[0, 0, 1])
+ xx = x / 2.
+ assert_equal(xx.data, [1/2., 2/2., 3])
+ assert_equal(xx.mask, [0, 0, 1])
+ # Test idiv on scalar
+ x = array([1., 2., 3.], mask=[0, 0, 1])
+ x /= 2.
+ assert_equal(x.data, [1/2., 2/2., 3])
+ assert_equal(x.mask, [0, 0, 1])
+ # Test div on array
+ x = array([1., 2., 3.], mask=[0, 0, 1])
+ xx = x / array([10., 20., 30.], mask=[1, 0, 0])
+ assert_equal(xx.data, [1., 2./20., 3.])
+ assert_equal(xx.mask, [1, 0, 1])
+ # Test idiv on array
+ x = array([1., 2., 3.], mask=[0, 0, 1])
+ x /= array([10., 20., 30.], mask=[1, 0, 0])
+ assert_equal(x.data, [1., 2/20., 3.])
+ assert_equal(x.mask, [1, 0, 1])
+
+
+ def test_datafriendly_pow(self):
+ "Test keeping data w/ (inplace) power"
+ # Test pow on scalar
+ x = array([1., 2., 3.], mask=[0, 0, 1])
+ xx = x ** 2.5
+ assert_equal(xx.data, [1., 2.**2.5, 3.])
+ assert_equal(xx.mask, [0, 0, 1])
+ # Test ipow on scalar
+ x **= 2.5
+ assert_equal(x.data, [1., 2.**2.5, 3])
+ assert_equal(x.mask, [0, 0, 1])
#------------------------------------------------------------------------------
@@ -1952,6 +2067,22 @@ class TestMaskArrayMathMethod(TestCase):
_ = method(out=nout, ddof=1)
self.failUnless(np.isnan(nout))
+
+ def test_diag(self):
+ "Test diag"
+ x = arange(9).reshape((3,3))
+ x[1,1] = masked
+ out = np.diag(x)
+ assert_equal(out, [0, 4, 8])
+ out = diag(x)
+ assert_equal(out, [0, 4, 8])
+ assert_equal(out.mask, [0, 1, 0])
+ out = diag(out)
+ control = array([[0, 0, 0], [0, 4, 0], [0, 0, 8]],
+ mask = [[0, 0, 0], [0, 1, 0], [0, 0, 0]])
+ assert_equal(out, control)
+
+
#------------------------------------------------------------------------------
class TestMaskedArrayMathMethodsComplex(TestCase):
@@ -2132,8 +2263,8 @@ class TestMaskedArrayFunctions(TestCase):
def test_power(self):
x = -1.1
- assert_almost_equal(power(x,2.), 1.21)
- self.failUnless(power(x,masked) is masked)
+ assert_almost_equal(power(x, 2.), 1.21)
+ self.failUnless(power(x, masked) is masked)
x = array([-1.1,-1.1,1.1,1.1,0.])
b = array([0.5,2.,0.5,2.,-1.], mask=[0,0,0,0,1])
y = power(x,b)
@@ -2312,17 +2443,31 @@ class TestMaskedArrayFunctions(TestCase):
def test_make_mask_descr(self):
"Test make_mask_descr"
+ # Flexible
ntype = [('a',np.float), ('b',np.float)]
test = make_mask_descr(ntype)
assert_equal(test, [('a',np.bool),('b',np.bool)])
- #
+ # Standard w/ shape
ntype = (np.float, 2)
test = make_mask_descr(ntype)
assert_equal(test, (np.bool,2))
- #
+ # Standard standard
ntype = np.float
test = make_mask_descr(ntype)
assert_equal(test, np.dtype(np.bool))
+ # Nested
+ ntype = [('a', np.float), ('b', [('ba', np.float), ('bb', np.float)])]
+ test = make_mask_descr(ntype)
+ control = np.dtype([('a', 'b1'), ('b', [('ba', 'b1'), ('bb', 'b1')])])
+ assert_equal(test, control)
+ # Named+ shape
+ ntype = [('a', (np.float, 2))]
+ test = make_mask_descr(ntype)
+ assert_equal(test, np.dtype([('a', (np.bool, 2))]))
+ # 2 names
+ ntype = [(('A', 'a'), float)]
+ test = make_mask_descr(ntype)
+ assert_equal(test, np.dtype([(('A', 'a'), bool)]))
def test_make_mask(self):
@@ -2388,6 +2533,24 @@ class TestMaskedArrayFunctions(TestCase):
pass
+ def test_flatten_mask(self):
+ "Tests flatten mask"
+ # Standarad dtype
+ mask = np.array([0, 0, 1], dtype=np.bool)
+ assert_equal(flatten_mask(mask), mask)
+ # Flexible dtype
+ mask = np.array([(0, 0), (0, 1)], dtype=[('a', bool), ('b', bool)])
+ test = flatten_mask(mask)
+ control = np.array([0, 0, 0, 1], dtype=bool)
+ assert_equal(test, control)
+
+ mdtype = [('a', bool), ('b', [('ba', bool), ('bb', bool)])]
+ data = [(0, (0, 0)), (0, (0, 1))]
+ mask = np.array(data, dtype=mdtype)
+ test = flatten_mask(mask)
+ control = np.array([ 0, 0, 0, 0, 0, 1], dtype=bool)
+ assert_equal(test, control)
+
#------------------------------------------------------------------------------
class TestMaskedFields(TestCase):
diff --git a/numpy/ma/tests/test_extras.py b/numpy/ma/tests/test_extras.py
index f41cff952..344dfce5a 100644
--- a/numpy/ma/tests/test_extras.py
+++ b/numpy/ma/tests/test_extras.py
@@ -17,6 +17,62 @@ from numpy.ma.testutils import *
from numpy.ma.core import *
from numpy.ma.extras import *
+
+class TestGeneric(TestCase):
+ #
+ def test_masked_all(self):
+ "Tests masked_all"
+ # Standard dtype
+ test = masked_all((2,), dtype=float)
+ control = array([1, 1], mask=[1, 1], dtype=float)
+ assert_equal(test, control)
+ # Flexible dtype
+ dt = np.dtype({'names': ['a', 'b'], 'formats': ['f', 'f']})
+ test = masked_all((2,), dtype=dt)
+ control = array([(0, 0), (0, 0)], mask=[(1, 1), (1, 1)], dtype=dt)
+ assert_equal(test, control)
+ test = masked_all((2,2), dtype=dt)
+ control = array([[(0, 0), (0, 0)], [(0, 0), (0, 0)]],
+ mask=[[(1, 1), (1, 1)], [(1, 1), (1, 1)]],
+ dtype=dt)
+ assert_equal(test, control)
+ # Nested dtype
+ dt = np.dtype([('a','f'), ('b', [('ba', 'f'), ('bb', 'f')])])
+ test = masked_all((2,), dtype=dt)
+ control = array([(1, (1, 1)), (1, (1, 1))],
+ mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt)
+ assert_equal(test, control)
+ test = masked_all((2,), dtype=dt)
+ control = array([(1, (1, 1)), (1, (1, 1))],
+ mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt)
+ assert_equal(test, control)
+ test = masked_all((1,1), dtype=dt)
+ control = array([[(1, (1, 1))]], mask=[[(1, (1, 1))]], dtype=dt)
+ assert_equal(test, control)
+
+
+ def test_masked_all_like(self):
+ "Tests masked_all"
+ # Standard dtype
+ base = array([1, 2], dtype=float)
+ test = masked_all_like(base)
+ control = array([1, 1], mask=[1, 1], dtype=float)
+ assert_equal(test, control)
+ # Flexible dtype
+ dt = np.dtype({'names': ['a', 'b'], 'formats': ['f', 'f']})
+ base = array([(0, 0), (0, 0)], mask=[(1, 1), (1, 1)], dtype=dt)
+ test = masked_all_like(base)
+ control = array([(10, 10), (10, 10)], mask=[(1, 1), (1, 1)], dtype=dt)
+ assert_equal(test, control)
+ # Nested dtype
+ dt = np.dtype([('a','f'), ('b', [('ba', 'f'), ('bb', 'f')])])
+ control = array([(1, (1, 1)), (1, (1, 1))],
+ mask=[(1, (1, 1)), (1, (1, 1))], dtype=dt)
+ test = masked_all_like(control)
+ assert_equal(test, control)
+ #
+
+
class TestAverage(TestCase):
"Several tests of average. Why so many ? Good point..."
def test_testAverage1(self):
diff --git a/numpy/ma/testutils.py b/numpy/ma/testutils.py
index 28754bccc..df7484f0a 100644
--- a/numpy/ma/testutils.py
+++ b/numpy/ma/testutils.py
@@ -167,22 +167,24 @@ def assert_array_compare(comparison, x, y, err_msg='', verbose=True, header='',
"""Asserts that a comparison relation between two masked arrays is satisfied
elementwise."""
# Fill the data first
- xf = filled(x)
- yf = filled(y)
+# xf = filled(x)
+# yf = filled(y)
# Allocate a common mask and refill
m = mask_or(getmask(x), getmask(y))
- x = masked_array(xf, copy=False, mask=m)
- y = masked_array(yf, copy=False, mask=m)
+ x = masked_array(x, copy=False, mask=m, subok=False)
+ y = masked_array(y, copy=False, mask=m, subok=False)
if ((x is masked) and not (y is masked)) or \
((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)
# OK, now run the basic tests on filled versions
+ comparison = getattr(np, comparison.__name__, lambda x,y: True)
return utils.assert_array_compare(comparison,
- x.filled(fill_value), y.filled(fill_value),
- err_msg=err_msg,
- verbose=verbose, header=header)
+ x.filled(fill_value),
+ y.filled(fill_value),
+ err_msg=err_msg,
+ verbose=verbose, header=header)
def assert_array_equal(x, y, err_msg='', verbose=True):