summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
authorDavid Cournapeau <cournape@gmail.com>2009-02-20 16:37:01 +0000
committerDavid Cournapeau <cournape@gmail.com>2009-02-20 16:37:01 +0000
commitda364a18e447c334dfa2ca5083b08e1b6a7c0d10 (patch)
tree7783575e8fe37f8e13ddfc050e9c9d94529bca8e /numpy/lib
parent745cfe4c60a59c01a8c2fd6ef68a8ca87f2180f5 (diff)
parenta271ac2e41aacab2903864cf371c4ba94cf4ec3f (diff)
downloadnumpy-da364a18e447c334dfa2ca5083b08e1b6a7c0d10.tar.gz
Merged revisions 6185-6187,6191-6221,6235-6238,6240-6241,6244,6250-6251,6253,6256,6258,6260-6261,6263,6265-6266,6268,6271,6283-6286,6291-6316,6320-6352,6354,6356,6358-6368,6370-6373,6398-6400,6410,6421-6424 via svnmerge from
http://svn.scipy.org/svn/numpy/trunk ................ 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. ................ r6191 | cdavid | 2008-12-23 13:10:59 +0900 (Tue, 23 Dec 2008) | 1 line Fix typos in the comments for manifest. ................ r6192 | cdavid | 2008-12-23 13:11:12 +0900 (Tue, 23 Dec 2008) | 1 line Use msvcrt values if available for manifest generation: only there starting from python 2.6.1. ................ r6193 | pearu | 2008-12-23 18:02:15 +0900 (Tue, 23 Dec 2008) | 1 line Fix issue 964: f2py python 2.6, 2.6.1 support. ................ r6194 | pierregm | 2008-12-24 08:43:43 +0900 (Wed, 24 Dec 2008) | 12 lines testutils: * assert_equal : use assert_equal_array on records * assert_array_compare : prevent the common mask to be back-propagated to the initial input arrays. * assert_equal_array : use operator.__eq__ instead of ma.equal * assert_equal_less: use operator.__less__ instead of ma.less core: * Fixed _check_fill_value for nested flexible types * Add a ndtype option to _make_mask_descr * Fixed mask_or for nested flexible types * Fixed the printing of masked arrays w/ flexible types. ................ r6195 | cdavid | 2008-12-26 21:16:45 +0900 (Fri, 26 Dec 2008) | 1 line Update to handle numscons 0.10.0 and above. ................ r6196 | cdavid | 2008-12-26 21:36:19 +0900 (Fri, 26 Dec 2008) | 1 line Do not import msvcrt globally in mingw32compiler module, since the module is imported on all platforms. ................ r6197 | cdavid | 2008-12-26 23:39:55 +0900 (Fri, 26 Dec 2008) | 1 line Do not test for functions already tested by python configure script. ................ r6198 | cdavid | 2008-12-27 14:56:58 +0900 (Sat, 27 Dec 2008) | 1 line BUG: Add a runtime check about endianness, to detect bug 4728 in python on Mac OS X. ................ r6199 | cdavid | 2008-12-27 19:06:25 +0900 (Sat, 27 Dec 2008) | 1 line Fix some typo/syntax errors when converting dict access to a function in manifest generation. ................ r6200 | cdavid | 2008-12-27 19:15:30 +0900 (Sat, 27 Dec 2008) | 1 line BUG (#970): fix a python 2.6 bug in distutils which caused an unhelpful Error:None message when trying to build with no VS installed and without the -c mingw32 option. ................ r6201 | cdavid | 2008-12-27 19:30:49 +0900 (Sat, 27 Dec 2008) | 1 line Improve the error message when initializing compiler failed. ................ r6202 | cdavid | 2008-12-27 19:32:05 +0900 (Sat, 27 Dec 2008) | 1 line Try to initialize the msvc compiler before the general code to detect the error early. ................ r6203 | cdavid | 2008-12-27 19:43:41 +0900 (Sat, 27 Dec 2008) | 1 line BUG (#970): this commit should fix the actual bug, which albeeit linked to commir r6200, was caused in anoter code path. ................ r6204 | cdavid | 2008-12-27 19:57:05 +0900 (Sat, 27 Dec 2008) | 1 line Fix manifest generation. ................ r6205 | cdavid | 2008-12-27 20:46:08 +0900 (Sat, 27 Dec 2008) | 1 line BUG (#827): close temp file before reopning them on windows, and make sure they are not automatically deleted on close either (2.6and higher specific). ................ r6206 | cdavid | 2008-12-27 21:18:47 +0900 (Sat, 27 Dec 2008) | 1 line Do not define the union for runtime endianness detection if we don't check endianness. ................ r6207 | cdavid | 2008-12-27 22:48:52 +0900 (Sat, 27 Dec 2008) | 1 line Start working on formatting failure on 2.6: copy how python does complex formatting. ................ r6208 | cdavid | 2008-12-27 23:44:11 +0900 (Sat, 27 Dec 2008) | 1 line Fix formatting for purely imaginary complex numbers. ................ r6209 | cdavid | 2008-12-27 23:53:15 +0900 (Sat, 27 Dec 2008) | 1 line More work on formatting float. ................ r6210 | cdavid | 2008-12-27 23:59:41 +0900 (Sat, 27 Dec 2008) | 1 line Finish formatting fixes for float scalar arrays. ................ r6211 | cdavid | 2008-12-28 00:12:20 +0900 (Sun, 28 Dec 2008) | 1 line Include umath_funcs_c99 in multiarray so that we can use isinf and co macros. ................ r6212 | cdavid | 2008-12-28 01:15:04 +0900 (Sun, 28 Dec 2008) | 1 line Include config.h before our C99 math compat layer. ................ r6213 | cdavid | 2008-12-28 01:15:41 +0900 (Sun, 28 Dec 2008) | 1 line Fix formatting. ................ r6214 | cdavid | 2008-12-28 01:16:18 +0900 (Sun, 28 Dec 2008) | 1 line Do not define FMTR and FMTI macros, as those are already defined on some platforms. ................ r6215 | cdavid | 2008-12-28 01:16:52 +0900 (Sun, 28 Dec 2008) | 1 line More formatting fixes. ................ r6216 | cdavid | 2008-12-28 01:17:27 +0900 (Sun, 28 Dec 2008) | 1 line Remove undef of removed macro. ................ r6217 | cdavid | 2008-12-28 01:33:40 +0900 (Sun, 28 Dec 2008) | 1 line Do not use PyOS_ascii_formatd, as it does not handle long double correctly. ................ r6218 | cdavid | 2008-12-28 02:19:40 +0900 (Sun, 28 Dec 2008) | 1 line Try ugly hack to circumvent long double brokenness with mingw. ................ r6219 | cdavid | 2008-12-28 02:25:50 +0900 (Sun, 28 Dec 2008) | 1 line Use ugly hack for mingw long double pb with complex format function as well. ................ r6220 | cdavid | 2008-12-28 12:18:20 +0900 (Sun, 28 Dec 2008) | 1 line Revert formatting changes: ascii_formatd only works for double, so we can't use it as it is for our formatting needs. ................ r6221 | cdavid | 2008-12-28 15:44:06 +0900 (Sun, 28 Dec 2008) | 1 line Do not add doc sources through add_data_dir: it will put the docs alongside numpy, as a separate package, which is not what we want. Use the manifest instead, since that's the only way I know of to include something in sdist-generated tarballs. ................ r6235 | cdavid | 2008-12-29 16:57:52 +0900 (Mon, 29 Dec 2008) | 13 lines Merged revisions 6233-6234 via svnmerge from http://svn.scipy.org/svn/numpy/branches/fix_float_format ........ r6233 | cdavid | 2008-12-29 12:49:09 +0900 (Mon, 29 Dec 2008) | 1 line Use parametric tests for format tests so that it is clearer which type is failing. ........ r6234 | cdavid | 2008-12-29 12:49:27 +0900 (Mon, 29 Dec 2008) | 1 line Fix formatting tests: cfloat and cdouble as well as np.float and np.double are the same; make sure we test 4 bytes float. ........ ................ r6236 | cdavid | 2008-12-29 17:02:15 +0900 (Mon, 29 Dec 2008) | 1 line Add nan/inf tests for formatting. ................ r6237 | cdavid | 2008-12-29 17:26:04 +0900 (Mon, 29 Dec 2008) | 1 line Add test for real float types locale independance. ................ r6238 | cdavid | 2008-12-29 17:35:06 +0900 (Mon, 29 Dec 2008) | 1 line Clearer error messages for formatting failures. ................ r6240 | cdavid | 2008-12-30 12:48:11 +0900 (Tue, 30 Dec 2008) | 1 line Add tests for print of float types. ................ r6241 | cdavid | 2008-12-30 12:56:54 +0900 (Tue, 30 Dec 2008) | 1 line Add print tests for complex types. ................ r6244 | cdavid | 2008-12-30 13:20:48 +0900 (Tue, 30 Dec 2008) | 1 line Fix test for print: forgot to make sure the value is a float before comparing it. ................ r6250 | cdavid | 2008-12-30 14:02:28 +0900 (Tue, 30 Dec 2008) | 17 lines Merged revisions 6247-6249 via svnmerge from http://svn.scipy.org/svn/numpy/branches/fix_float_format ........ r6247 | cdavid | 2008-12-30 13:41:37 +0900 (Tue, 30 Dec 2008) | 1 line Handle 1e10 specially, as it is the limit where exp notation is shorter than decimal for single precision, but not for double (python native one). ........ r6248 | cdavid | 2008-12-30 13:47:38 +0900 (Tue, 30 Dec 2008) | 1 line Refactor a bit redirected output print test. ........ r6249 | cdavid | 2008-12-30 13:49:31 +0900 (Tue, 30 Dec 2008) | 1 line Fix test for single precision print. ........ ................ r6251 | cdavid | 2008-12-30 14:12:50 +0900 (Tue, 30 Dec 2008) | 1 line Use np.inf instead of float('inf'), as the later does not work on windows for python < 2.6. ................ r6253 | cdavid | 2008-12-30 14:15:09 +0900 (Tue, 30 Dec 2008) | 1 line Fix typo in test. ................ r6256 | cdavid | 2008-12-30 14:34:22 +0900 (Tue, 30 Dec 2008) | 1 line Special case float tests on windows: python 2.5 and below have >=3 digits in the exp. ................ r6258 | cdavid | 2008-12-30 14:42:03 +0900 (Tue, 30 Dec 2008) | 1 line Hardcode reference for inf/nan-involved values. ................ r6260 | cdavid | 2008-12-30 14:50:18 +0900 (Tue, 30 Dec 2008) | 1 line Fix more formatting tests on win32. ................ r6261 | cdavid | 2008-12-30 14:52:16 +0900 (Tue, 30 Dec 2008) | 1 line Fix some more redirected output print tests. ................ r6263 | cdavid | 2008-12-30 15:01:31 +0900 (Tue, 30 Dec 2008) | 1 line More fixes for print tests. ................ r6265 | cdavid | 2008-12-30 15:03:56 +0900 (Tue, 30 Dec 2008) | 1 line Fix typo. ................ r6266 | cdavid | 2008-12-30 15:08:06 +0900 (Tue, 30 Dec 2008) | 1 line Fix typo. ................ r6268 | cdavid | 2008-12-30 15:12:26 +0900 (Tue, 30 Dec 2008) | 1 line complex scalar arrays cannot be created from real/imag args: wrap init values in a complex. ................ r6271 | cdavid | 2008-12-30 15:32:03 +0900 (Tue, 30 Dec 2008) | 1 line Do not use dict for reference: hashing on scalar arrays does not work as I expected. ................ r6283 | ptvirtan | 2008-12-31 10:14:47 +0900 (Wed, 31 Dec 2008) | 1 line Fix #951: make tests to clean temp files properly ................ r6284 | jarrod.millman | 2009-01-01 08:25:03 +0900 (Thu, 01 Jan 2009) | 2 lines ran reindent ................ r6285 | alan.mcintyre | 2009-01-01 08:46:34 +0900 (Thu, 01 Jan 2009) | 15 lines Remove the following deprecated items from numpy.testing: - ParametricTestCase - The following arguments from numpy.testing.Tester.test(): level, verbosity, all, sys_argv, testcase_pattern - Path manipulation functions: set_package_path, set_local_path, restore_path - NumpyTestCase, NumpyTest Also separated testing parameter setup from NoseTester.test into NoseTester.prepare_test_args for use in a utility script for valgrind testing (see NumPy ticket #784). ................ r6286 | jarrod.millman | 2009-01-01 16:56:53 +0900 (Thu, 01 Jan 2009) | 2 lines add default include dir for Fedora/Red Hat (see SciPy ticket 817) ................ r6291 | cdavid | 2009-01-04 19:57:39 +0900 (Sun, 04 Jan 2009) | 1 line Do not import md5 on python >= 2.6; use hashlib instead. ................ r6292 | cdavid | 2009-01-04 20:08:16 +0900 (Sun, 04 Jan 2009) | 1 line Do not use popen* but subprocess.Popen instead. ................ r6293 | cdavid | 2009-01-04 21:03:29 +0900 (Sun, 04 Jan 2009) | 1 line Revert md5 change: hashlib.md5 is not a drop-in replacement for md5. ................ r6294 | pierregm | 2009-01-05 05:16:00 +0900 (Mon, 05 Jan 2009) | 2 lines * adapted default_fill_value for flexible datatype * fixed max/minimum_fill_value for flexible datatype ................ r6295 | stefan | 2009-01-06 06:51:18 +0900 (Tue, 06 Jan 2009) | 1 line Credit more developers. ................ r6296 | pierregm | 2009-01-06 07:52:21 +0900 (Tue, 06 Jan 2009) | 1 line *moved the printing templates out of MaskedArray.__repr__ ................ r6297 | stefan | 2009-01-06 19:09:00 +0900 (Tue, 06 Jan 2009) | 1 line Use new-style classes with multiple-inheritance to address bug in IronPython. ................ r6298 | pierregm | 2009-01-07 05:35:37 +0900 (Wed, 07 Jan 2009) | 1 line * Bugfix #961 ................ r6299 | pierregm | 2009-01-08 03:14:12 +0900 (Thu, 08 Jan 2009) | 1 line * Fixed iadd/isub/imul when the base array has no mask but the other array does ................ r6300 | pierregm | 2009-01-08 07:34:51 +0900 (Thu, 08 Jan 2009) | 3 lines * Renamed `torecords` to `toflex`, keeping `torecords` as an alias * Introduced `fromflex`, to reconstruct a masked_array from the output of `toflex` (can?\226?\128?\153t `use fromrecords` as it would clash with `numpy.ma.mrecords.fromrecords`) * Fixed a bug in MaskedBinaryOperation (#979) (wrong array broadcasting) ................ r6301 | cdavid | 2009-01-08 18:19:00 +0900 (Thu, 08 Jan 2009) | 1 line Avoid putting things into stderr when errors occurs in f2py wrappers; put all the info in the python error string instead. ................ r6302 | cdavid | 2009-01-09 00:11:32 +0900 (Fri, 09 Jan 2009) | 1 line Fix python 2.4 issue. ................ r6303 | chanley | 2009-01-09 01:30:01 +0900 (Fri, 09 Jan 2009) | 1 line Fix test_print.py function _test_locale_independance() since str(1.2) does not use the LC_NUMERIC locale to convert numbers. Fix from Mark Sienkiewicz. ................ r6304 | cdavid | 2009-01-09 04:22:21 +0900 (Fri, 09 Jan 2009) | 1 line Revert buggy test fix for locale independecce. ................ r6305 | pierregm | 2009-01-09 05:02:29 +0900 (Fri, 09 Jan 2009) | 2 lines * Add __eq__ and __ne__ for support of flexible arrays. * Fixed .filled for nested structures ................ r6306 | pierregm | 2009-01-09 06:51:04 +0900 (Fri, 09 Jan 2009) | 1 line * Remove a debugging print statement. ................ r6307 | jarrod.millman | 2009-01-09 11:14:35 +0900 (Fri, 09 Jan 2009) | 2 lines Updated license file ................ r6308 | cdavid | 2009-01-09 14:26:58 +0900 (Fri, 09 Jan 2009) | 1 line Tag formatting unit tests as known failures. ................ r6309 | jarrod.millman | 2009-01-09 17:59:29 +0900 (Fri, 09 Jan 2009) | 2 lines should be more reliable way to determine what bit platform ................ r6310 | jarrod.millman | 2009-01-09 18:14:17 +0900 (Fri, 09 Jan 2009) | 2 lines better default library paths for 64bit arch ................ r6311 | jarrod.millman | 2009-01-09 18:57:15 +0900 (Fri, 09 Jan 2009) | 2 lines simplification suggested by stefan ................ r6312 | jarrod.millman | 2009-01-09 19:02:09 +0900 (Fri, 09 Jan 2009) | 2 lines switch the order [lib,lib64] --> [lib64,lib] ................ r6313 | jarrod.millman | 2009-01-09 19:18:29 +0900 (Fri, 09 Jan 2009) | 2 lines removed unneeded import ................ r6314 | jarrod.millman | 2009-01-10 04:37:16 +0900 (Sat, 10 Jan 2009) | 2 lines can't use append an int to a string ................ r6315 | pierregm | 2009-01-10 05:18:12 +0900 (Sat, 10 Jan 2009) | 2 lines * Added flatten_structured_arrays * Fixed _get_recordarray for nested structures ................ r6316 | pierregm | 2009-01-10 10:53:05 +0900 (Sat, 10 Jan 2009) | 1 line * Add flatten_structured_array to the namespace ................ r6320 | pierregm | 2009-01-14 06:01:58 +0900 (Wed, 14 Jan 2009) | 9 lines numpy.ma.core: * introduced baseclass, sharedmask and hardmask as readonly properties of MaskedArray * docstrings update numpy.ma.extras: * docstring updates docs/reference * introduced maskedarray, maskedarray.baseclass, maskedarray.generic ................ r6321 | stefan | 2009-01-14 16:14:27 +0900 (Wed, 14 Jan 2009) | 2 lines Docstring: remove old floating point arithmetic, parallel execution and postponed import references. ................ r6322 | stefan | 2009-01-14 16:55:16 +0900 (Wed, 14 Jan 2009) | 1 line Fix printing of limits. ................ r6323 | stefan | 2009-01-14 16:56:10 +0900 (Wed, 14 Jan 2009) | 1 line Fix finfo to work on all instances, not just NumPy scalars. ................ r6324 | pierregm | 2009-01-17 09:15:15 +0900 (Sat, 17 Jan 2009) | 1 line * fixed _arraymethod.__call__ for structured arrays ................ r6325 | ptvirtan | 2009-01-18 06:24:13 +0900 (Sun, 18 Jan 2009) | 3 lines Make `trapz` accept 1-D `x` parameter for n-d `y`, even if axis != -1. Additional tests included. ................ r6326 | pierregm | 2009-01-19 17:53:53 +0900 (Mon, 19 Jan 2009) | 3 lines * renamed FlatIter to MaskedIterator * added __getitem__ to MaskedIterator ................ r6327 | pierregm | 2009-01-19 18:01:24 +0900 (Mon, 19 Jan 2009) | 2 lines * replace np.asarray by np.asanyarray in unique1d ................ r6328 | pierregm | 2009-01-19 18:04:20 +0900 (Mon, 19 Jan 2009) | 2 lines * add intersect1d, intersect1d_nu, setdiff1d, setmember1d, setxor1d, unique1d, union1d * use np.atleast1d instead of ma.atleast1d ................ r6329 | pierregm | 2009-01-20 06:22:52 +0900 (Tue, 20 Jan 2009) | 3 lines * lib : introduced _iotools * lib.io : introduced genfromtxt, ndfromtxt, mafromtxt, recfromtxt, recfromcsv. ................ r6330 | pierregm | 2009-01-22 14:37:36 +0900 (Thu, 22 Jan 2009) | 1 line * genfromtxt : if names is True, accept a line starting with a comment character as header. ................ r6331 | pierregm | 2009-01-22 14:40:25 +0900 (Thu, 22 Jan 2009) | 1 line * added recfunctions, a collection of utilities to manipulate structured arrays. ................ r6332 | pierregm | 2009-01-23 03:21:32 +0900 (Fri, 23 Jan 2009) | 2 lines * fixed a machine-dependent issue on default int ('<i4' on OS X, '<i8' on linux) ? * fixed an machine-dependent issue on argsort ? ................ r6333 | cdavid | 2009-01-24 17:02:14 +0900 (Sat, 24 Jan 2009) | 1 line Fix compilation error on 2.4. ................ r6334 | pierregm | 2009-01-27 06:04:26 +0900 (Tue, 27 Jan 2009) | 7 lines * _iotools.StringConverter : - add a _checked attribute to indicate whether the converter has been upgraded or not. - switched the default value for bool to False * io.genfromtxt: - fixed for the case where a whole column is masked: switch to bool or the common dtype (if needed) ................ r6335 | pierregm | 2009-01-27 11:46:26 +0900 (Tue, 27 Jan 2009) | 1 line * prevent MaskedBinaryOperation and DomainedBinaryOperation to shrink the mask of the output when at least one of the inputs has a mask full of False ................ r6336 | matthew.brett@gmail.com | 2009-01-30 09:26:44 +0900 (Fri, 30 Jan 2009) | 1 line New docstrings for byteorder and newbyteorder() ................ r6337 | pierregm | 2009-02-02 14:20:17 +0900 (Mon, 02 Feb 2009) | 2 lines * Added a 'autoconvert' option to stack_arrays. * Fixed 'stack_arrays' to work with fields with titles. ................ r6338 | pierregm | 2009-02-04 02:11:44 +0900 (Wed, 04 Feb 2009) | 1 line * Make sure that StringConverter.update sets the type to object if it can't define it. ................ r6339 | pierregm | 2009-02-05 05:52:36 +0900 (Thu, 05 Feb 2009) | 2 lines * test__iotools : prevent test_upgrademapper if dateutil is not installed * MaskedArray.__rmul__ : switch to multiply(self, other) ................ r6340 | pierregm | 2009-02-05 06:53:05 +0900 (Thu, 05 Feb 2009) | 1 line test_upgrademapper : got rid of the dateutil import ................ r6341 | pierregm | 2009-02-05 13:31:51 +0900 (Thu, 05 Feb 2009) | 2 lines * genfromtxt : Fixed when a dtype involving objects is explicitly given. Raise a NotImplementedError if the dtype is nested. * _iotools : make sure StringConverter gets properly initiated when a function returning a np.object is used as input parameter. ................ r6342 | alan.mcintyre | 2009-02-06 05:11:40 +0900 (Fri, 06 Feb 2009) | 6 lines Issue #957: - Fix problems with test decorators when used on test generators. - The skip/fail arguments for skipif and knownfailureif can now be either a bool or a callable that returns a bool. - Added tests for the test decorators. ................ r6343 | ptvirtan | 2009-02-06 09:27:08 +0900 (Fri, 06 Feb 2009) | 1 line doc/numpydoc: work better together with Sphinx's config option ................ r6344 | ptvirtan | 2009-02-06 09:51:41 +0900 (Fri, 06 Feb 2009) | 1 line doc: Move maskedarray docs upward in TOC ................ r6345 | oliphant | 2009-02-06 15:25:50 +0900 (Fri, 06 Feb 2009) | 1 line Avoid re-creating the sequence when there is only one field in the regular expression. ................ r6346 | oliphant | 2009-02-06 15:31:11 +0900 (Fri, 06 Feb 2009) | 1 line Removed an unneccessary return statement in a unit test. ................ r6347 | pearu | 2009-02-06 23:36:58 +0900 (Fri, 06 Feb 2009) | 1 line Fix a bug: python system_info.py failed because _pkg_config_info defined section to be None. ................ r6348 | pearu | 2009-02-06 23:38:57 +0900 (Fri, 06 Feb 2009) | 1 line Fix another bug, see last commit. ................ r6349 | pierregm | 2009-02-07 18:19:12 +0900 (Sat, 07 Feb 2009) | 2 lines MaskedArray.resize : systematically raise a TypeError exception, as a masked array never owns its data MaskedIterator : fixed to allow .flat on masked matrices ................ r6350 | pierregm | 2009-02-08 03:51:31 +0900 (Sun, 08 Feb 2009) | 1 line ................ r6351 | ptvirtan | 2009-02-10 05:18:08 +0900 (Tue, 10 Feb 2009) | 1 line Fix #955: fix errobj leak in scalarmath floating point error handling ................ r6352 | pierregm | 2009-02-10 09:42:40 +0900 (Tue, 10 Feb 2009) | 1 line * prevent modifications to the mask to be back-propagated w/ __array_wrap__ ................ r6354 | cdavid | 2009-02-10 19:44:01 +0900 (Tue, 10 Feb 2009) | 1 line Fix hyphen (patch from debian package). ................ r6356 | pierregm | 2009-02-11 10:51:28 +0900 (Wed, 11 Feb 2009) | 1 line * MaskedArray.__array_wrap__ : forces the domain (if any) to a ndarray (fill with True) ................ r6358 | oliphant | 2009-02-12 13:22:03 +0900 (Thu, 12 Feb 2009) | 1 line Add multiple-field access by making a copy of the array and filling with the selected fields. ................ r6359 | stefan | 2009-02-12 14:44:07 +0900 (Thu, 12 Feb 2009) | 2 lines Trust user's specification of MACOSX_DEPLOYMENT_TARGET [patch by Brian Granger]. ................ r6360 | cdavid | 2009-02-14 23:54:26 +0900 (Sat, 14 Feb 2009) | 1 line Merge fix_float_format branch into the trunk. ................ r6361 | cdavid | 2009-02-15 00:02:39 +0900 (Sun, 15 Feb 2009) | 1 line Fix typo in multiarray tests. ................ r6362 | cdavid | 2009-02-15 00:03:22 +0900 (Sun, 15 Feb 2009) | 1 line Remove leftover in TestIO. ................ r6363 | cdavid | 2009-02-15 02:03:51 +0900 (Sun, 15 Feb 2009) | 1 line Include C99 math compatbility layer in multiarray - isnan and co needed by numpyos.c ................ r6364 | ptvirtan | 2009-02-15 07:09:26 +0900 (Sun, 15 Feb 2009) | 1 line More add_newdocs entries, and make add_newdoc capable of adding docs also to normal Python objects. ................ r6365 | ptvirtan | 2009-02-15 07:10:24 +0900 (Sun, 15 Feb 2009) | 1 line Move (un)packbits docstrings to add_newdocs.py. Fix typos. ................ r6366 | ptvirtan | 2009-02-15 07:11:19 +0900 (Sun, 15 Feb 2009) | 1 line Document constants in numpy.doc.constants ................ r6367 | ptvirtan | 2009-02-15 07:38:32 +0900 (Sun, 15 Feb 2009) | 1 line Move numpy.lib __doc__ back to info.py; was moved to __init__.py by mistake. ................ r6368 | pierregm | 2009-02-15 07:42:29 +0900 (Sun, 15 Feb 2009) | 1 line * genfromtxt : fixed case when using explicit converters and explicit dtype. ................ r6370 | ptvirtan | 2009-02-16 00:44:47 +0900 (Mon, 16 Feb 2009) | 1 line sphinxext: clean up plot directive, and merge some features from matplotlib ................ r6371 | charris | 2009-02-18 06:19:10 +0900 (Wed, 18 Feb 2009) | 2 lines Coding style cleanups. ................ r6372 | cdavid | 2009-02-18 14:06:57 +0900 (Wed, 18 Feb 2009) | 1 line Fix some const issues in NumPyOs_ascii_strtod. ................ r6373 | charris | 2009-02-18 14:36:35 +0900 (Wed, 18 Feb 2009) | 1 line Coding style cleanups. ................ r6398 | charris | 2009-02-19 05:54:52 +0900 (Thu, 19 Feb 2009) | 2 lines Coding style cleanups. ................ r6399 | charris | 2009-02-19 09:45:14 +0900 (Thu, 19 Feb 2009) | 2 lines Coding style cleanups. ................ r6400 | charris | 2009-02-19 13:58:23 +0900 (Thu, 19 Feb 2009) | 1 line Coding style cleanups. ................ r6410 | cdavid | 2009-02-19 19:05:28 +0900 (Thu, 19 Feb 2009) | 1 line Tag known failure on win32. ................ r6421 | stefan | 2009-02-20 04:28:08 +0900 (Fri, 20 Feb 2009) | 1 line Fix tests using strptime to be Python 2.4 compatible. ................ r6422 | charris | 2009-02-20 08:25:01 +0900 (Fri, 20 Feb 2009) | 2 lines Coding style cleanups. ................ r6423 | charris | 2009-02-20 12:40:53 +0900 (Fri, 20 Feb 2009) | 1 line Coding style cleanups. ................ r6424 | cdavid | 2009-02-20 22:30:20 +0900 (Fri, 20 Feb 2009) | 1 line Unhelpful message for compaq fortran compiler. ................
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/__init__.py148
-rw-r--r--numpy/lib/_iotools.py493
-rw-r--r--numpy/lib/arraysetops.py10
-rw-r--r--numpy/lib/function_base.py77
-rw-r--r--numpy/lib/getlimits.py48
-rw-r--r--numpy/lib/index_tricks.py2
-rw-r--r--numpy/lib/info.py251
-rw-r--r--numpy/lib/io.py521
-rw-r--r--numpy/lib/recfunctions.py942
-rw-r--r--numpy/lib/src/_compiled_base.c84
-rw-r--r--numpy/lib/tests/test__iotools.py167
-rw-r--r--numpy/lib/tests/test_function_base.py38
-rw-r--r--numpy/lib/tests/test_getlimits.py4
-rw-r--r--numpy/lib/tests/test_io.py476
-rw-r--r--numpy/lib/tests/test_recfunctions.py606
-rw-r--r--numpy/lib/utils.py8
16 files changed, 3466 insertions, 409 deletions
diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py
index 296ca7135..07f6d5c27 100644
--- a/numpy/lib/__init__.py
+++ b/numpy/lib/__init__.py
@@ -1,151 +1,3 @@
-"""
-Basic functions used by several sub-packages and
-useful to have in the main name-space.
-
-Type Handling
--------------
-================ ===================
-iscomplexobj Test for complex object, scalar result
-isrealobj Test for real object, scalar result
-iscomplex Test for complex elements, array result
-isreal Test for real elements, array result
-imag Imaginary part
-real Real part
-real_if_close Turns complex number with tiny imaginary part to real
-isneginf Tests for negative infinity, array result
-isposinf Tests for positive infinity, array result
-isnan Tests for nans, array result
-isinf Tests for infinity, array result
-isfinite Tests for finite numbers, array result
-isscalar True if argument is a scalar
-nan_to_num Replaces NaN's with 0 and infinities with large numbers
-cast Dictionary of functions to force cast to each type
-common_type Determine the minimum common type code for a group
- of arrays
-mintypecode Return minimal allowed common typecode.
-================ ===================
-
-Index Tricks
-------------
-================ ===================
-mgrid Method which allows easy construction of N-d
- 'mesh-grids'
-``r_`` Append and construct arrays: turns slice objects into
- ranges and concatenates them, for 2d arrays appends rows.
-index_exp Konrad Hinsen's index_expression class instance which
- can be useful for building complicated slicing syntax.
-================ ===================
-
-Useful Functions
-----------------
-================ ===================
-select Extension of where to multiple conditions and choices
-extract Extract 1d array from flattened array according to mask
-insert Insert 1d array of values into Nd array according to mask
-linspace Evenly spaced samples in linear space
-logspace Evenly spaced samples in logarithmic space
-fix Round x to nearest integer towards zero
-mod Modulo mod(x,y) = x % y except keeps sign of y
-amax Array maximum along axis
-amin Array minimum along axis
-ptp Array max-min along axis
-cumsum Cumulative sum along axis
-prod Product of elements along axis
-cumprod Cumluative product along axis
-diff Discrete differences along axis
-angle Returns angle of complex argument
-unwrap Unwrap phase along given axis (1-d algorithm)
-sort_complex Sort a complex-array (based on real, then imaginary)
-trim_zeros Trim the leading and trailing zeros from 1D array.
-vectorize A class that wraps a Python function taking scalar
- arguments into a generalized function which can handle
- arrays of arguments using the broadcast rules of
- numerix Python.
-================ ===================
-
-Shape Manipulation
-------------------
-================ ===================
-squeeze Return a with length-one dimensions removed.
-atleast_1d Force arrays to be > 1D
-atleast_2d Force arrays to be > 2D
-atleast_3d Force arrays to be > 3D
-vstack Stack arrays vertically (row on row)
-hstack Stack arrays horizontally (column on column)
-column_stack Stack 1D arrays as columns into 2D array
-dstack Stack arrays depthwise (along third dimension)
-split Divide array into a list of sub-arrays
-hsplit Split into columns
-vsplit Split into rows
-dsplit Split along third dimension
-================ ===================
-
-Matrix (2D Array) Manipulations
--------------------------------
-================ ===================
-fliplr 2D array with columns flipped
-flipud 2D array with rows flipped
-rot90 Rotate a 2D array a multiple of 90 degrees
-eye Return a 2D array with ones down a given diagonal
-diag Construct a 2D array from a vector, or return a given
- diagonal from a 2D array.
-mat Construct a Matrix
-bmat Build a Matrix from blocks
-================ ===================
-
-Polynomials
------------
-================ ===================
-poly1d A one-dimensional polynomial class
-poly Return polynomial coefficients from roots
-roots Find roots of polynomial given coefficients
-polyint Integrate polynomial
-polyder Differentiate polynomial
-polyadd Add polynomials
-polysub Substract polynomials
-polymul Multiply polynomials
-polydiv Divide polynomials
-polyval Evaluate polynomial at given argument
-================ ===================
-
-Import Tricks
--------------
-================ ===================
-ppimport Postpone module import until trying to use it
-ppimport_attr Postpone module import until trying to use its attribute
-ppresolve Import postponed module and return it.
-================ ===================
-
-Machine Arithmetics
--------------------
-================ ===================
-machar_single Single precision floating point arithmetic parameters
-machar_double Double precision floating point arithmetic parameters
-================ ===================
-
-Threading Tricks
-----------------
-================ ===================
-ParallelExec Execute commands in parallel thread.
-================ ===================
-
-1D Array Set Operations
------------------------
-Set operations for 1D numeric arrays based on sort() function.
-
-================ ===================
-ediff1d Array difference (auxiliary function).
-unique1d Unique elements of 1D array.
-intersect1d Intersection of 1D arrays with unique elements.
-intersect1d_nu Intersection of 1D arrays with any elements.
-setxor1d Set exclusive-or of 1D arrays with unique elements.
-setmember1d Return an array of shape of ar1 containing 1 where
- the elements of ar1 are in ar2 and 0 otherwise.
-union1d Union of 1D arrays with unique elements.
-setdiff1d Set difference of 1D arrays with unique elements.
-================ ===================
-
-"""
from info import __doc__
from numpy.version import version as __version__
diff --git a/numpy/lib/_iotools.py b/numpy/lib/_iotools.py
new file mode 100644
index 000000000..23053bf4d
--- /dev/null
+++ b/numpy/lib/_iotools.py
@@ -0,0 +1,493 @@
+"""
+A collection of functions designed to help I/O with ascii file.
+
+"""
+__docformat__ = "restructuredtext en"
+
+import numpy as np
+import numpy.core.numeric as nx
+from __builtin__ import bool, int, long, float, complex, object, unicode, str
+
+
+def _is_string_like(obj):
+ """
+ Check whether obj behaves like a string.
+ """
+ try:
+ obj + ''
+ except (TypeError, ValueError):
+ return False
+ return True
+
+
+def _to_filehandle(fname, flag='r', return_opened=False):
+ """
+ Returns the filehandle corresponding to a string or a file.
+ If the string ends in '.gz', the file is automatically unzipped.
+
+ Parameters
+ ----------
+ fname : string, filehandle
+ Name of the file whose filehandle must be returned.
+ flag : string, optional
+ Flag indicating the status of the file ('r' for read, 'w' for write).
+ return_opened : boolean, optional
+ Whether to return the opening status of the file.
+ """
+ if _is_string_like(fname):
+ if fname.endswith('.gz'):
+ import gzip
+ fhd = gzip.open(fname, flag)
+ elif fname.endswith('.bz2'):
+ import bz2
+ fhd = bz2.BZ2File(fname)
+ else:
+ fhd = file(fname, flag)
+ opened = True
+ elif hasattr(fname, 'seek'):
+ fhd = fname
+ opened = False
+ else:
+ raise ValueError('fname must be a string or file handle')
+ if return_opened:
+ return fhd, opened
+ return fhd
+
+
+def has_nested_fields(ndtype):
+ """
+ Returns whether one or several fields of a structured array are nested.
+ """
+ for name in ndtype.names or ():
+ if ndtype[name].names:
+ return True
+ return False
+
+
+def flatten_dtype(ndtype):
+ """
+ Unpack a structured data-type.
+
+ """
+ names = ndtype.names
+ if names is None:
+ return [ndtype]
+ else:
+ types = []
+ for field in names:
+ (typ, _) = ndtype.fields[field]
+ flat_dt = flatten_dtype(typ)
+ types.extend(flat_dt)
+ return types
+
+
+class LineSplitter:
+ """
+ Defines a function to split a string at a given delimiter or at given places.
+
+ Parameters
+ ----------
+ comment : {'#', string}
+ Character used to mark the beginning of a comment.
+ delimiter : var, optional
+ If a string, character used to delimit consecutive fields.
+ If an integer or a sequence of integers, width(s) of each field.
+ autostrip : boolean, optional
+ Whether to strip each individual fields
+ """
+
+ def autostrip(self, method):
+ "Wrapper to strip each member of the output of `method`."
+ return lambda input: [_.strip() for _ in method(input)]
+ #
+ def __init__(self, delimiter=None, comments='#', autostrip=True):
+ self.comments = comments
+ # Delimiter is a character
+ if (delimiter is None) or _is_string_like(delimiter):
+ delimiter = delimiter or None
+ _handyman = self._delimited_splitter
+ # Delimiter is a list of field widths
+ elif hasattr(delimiter, '__iter__'):
+ _handyman = self._variablewidth_splitter
+ idx = np.cumsum([0]+list(delimiter))
+ delimiter = [slice(i,j) for (i,j) in zip(idx[:-1], idx[1:])]
+ # Delimiter is a single integer
+ elif int(delimiter):
+ (_handyman, delimiter) = (self._fixedwidth_splitter, int(delimiter))
+ else:
+ (_handyman, delimiter) = (self._delimited_splitter, None)
+ self.delimiter = delimiter
+ if autostrip:
+ self._handyman = self.autostrip(_handyman)
+ else:
+ self._handyman = _handyman
+ #
+ def _delimited_splitter(self, line):
+ line = line.split(self.comments)[0].strip()
+ if not line:
+ return []
+ return line.split(self.delimiter)
+ #
+ def _fixedwidth_splitter(self, line):
+ line = line.split(self.comments)[0]
+ if not line:
+ return []
+ fixed = self.delimiter
+ slices = [slice(i, i+fixed) for i in range(len(line))[::fixed]]
+ return [line[s] for s in slices]
+ #
+ def _variablewidth_splitter(self, line):
+ line = line.split(self.comments)[0]
+ if not line:
+ return []
+ slices = self.delimiter
+ return [line[s] for s in slices]
+ #
+ def __call__(self, line):
+ return self._handyman(line)
+
+
+
+class NameValidator:
+ """
+ Validates a list of strings to use as field names.
+ The strings are stripped of any non alphanumeric character, and spaces
+ are replaced by `_`. If the optional input parameter `case_sensitive`
+ is False, the strings are set to upper case.
+
+ During instantiation, the user can define a list of names to exclude, as
+ well as a list of invalid characters. Names in the exclusion list
+ are appended a '_' character.
+
+ Once an instance has been created, it can be called with a list of names
+ and a list of valid names will be created.
+ The `__call__` method accepts an optional keyword, `default`, that sets
+ the default name in case of ambiguity. By default, `default = 'f'`, so
+ that names will default to `f0`, `f1`
+
+ Parameters
+ ----------
+ excludelist : sequence, optional
+ A list of names to exclude. This list is appended to the default list
+ ['return','file','print']. Excluded names are appended an underscore:
+ for example, `file` would become `file_`.
+ deletechars : string, optional
+ A string combining invalid characters that must be deleted from the names.
+ casesensitive : {True, False, 'upper', 'lower'}, optional
+ If True, field names are case_sensitive.
+ If False or 'upper', field names are converted to upper case.
+ If 'lower', field names are converted to lower case.
+ """
+ #
+ defaultexcludelist = ['return','file','print']
+ defaultdeletechars = set("""~!@#$%^&*()-=+~\|]}[{';: /?.>,<""")
+ #
+ def __init__(self, excludelist=None, deletechars=None, case_sensitive=None):
+ #
+ if excludelist is None:
+ excludelist = []
+ excludelist.extend(self.defaultexcludelist)
+ self.excludelist = excludelist
+ #
+ if deletechars is None:
+ delete = self.defaultdeletechars
+ else:
+ delete = set(deletechars)
+ delete.add('"')
+ self.deletechars = delete
+
+ if (case_sensitive is None) or (case_sensitive is True):
+ self.case_converter = lambda x: x
+ elif (case_sensitive is False) or ('u' in case_sensitive):
+ self.case_converter = lambda x: x.upper()
+ elif 'l' in case_sensitive:
+ self.case_converter = lambda x: x.lower()
+ else:
+ self.case_converter = lambda x: x
+ #
+ def validate(self, names, default='f'):
+ #
+ if names is None:
+ return
+ #
+ validatednames = []
+ seen = dict()
+ #
+ deletechars = self.deletechars
+ excludelist = self.excludelist
+ #
+ case_converter = self.case_converter
+ #
+ for i, item in enumerate(names):
+ item = case_converter(item)
+ item = item.strip().replace(' ', '_')
+ item = ''.join([c for c in item if c not in deletechars])
+ if not len(item):
+ item = '%s%d' % (default, i)
+ elif item in excludelist:
+ item += '_'
+ cnt = seen.get(item, 0)
+ if cnt > 0:
+ validatednames.append(item + '_%d' % cnt)
+ else:
+ validatednames.append(item)
+ seen[item] = cnt+1
+ return validatednames
+ #
+ def __call__(self, names, default='f'):
+ return self.validate(names, default)
+
+
+
+def str2bool(value):
+ """
+ Tries to transform a string supposed to represent a boolean to a boolean.
+
+ Raises
+ ------
+ ValueError
+ If the string is not 'True' or 'False' (case independent)
+ """
+ value = value.upper()
+ if value == 'TRUE':
+ return True
+ elif value == 'FALSE':
+ return False
+ else:
+ raise ValueError("Invalid boolean")
+
+
+
+class StringConverter:
+ """
+ Factory class for function transforming a string into another object (int,
+ float).
+
+ After initialization, an instance can be called to transform a string
+ into another object. If the string is recognized as representing a missing
+ value, a default value is returned.
+
+ Parameters
+ ----------
+ dtype_or_func : {None, dtype, function}, optional
+ Input data type, used to define a basic function and a default value
+ for missing data. For example, when `dtype` is float, the :attr:`func`
+ attribute is set to ``float`` and the default value to `np.nan`.
+ Alternatively, function used to convert a string to another object.
+ In that later case, it is recommended to give an associated default
+ value as input.
+ default : {None, var}, optional
+ Value to return by default, that is, when the string to be converted
+ is flagged as missing.
+ missing_values : {sequence}, optional
+ Sequence of strings indicating a missing value.
+ locked : {boolean}, optional
+ Whether the StringConverter should be locked to prevent automatic
+ upgrade or not.
+
+ Attributes
+ ----------
+ func : function
+ Function used for the conversion
+ default : var
+ Default value to return when the input corresponds to a missing value.
+ type : type
+ Type of the output.
+ _status : integer
+ Integer representing the order of the conversion.
+ _mapper : sequence of tuples
+ Sequence of tuples (dtype, function, default value) to evaluate in order.
+ _locked : boolean
+ Whether the StringConverter is locked, thereby preventing automatic any
+ upgrade or not.
+
+ """
+ #
+ _mapper = [(nx.bool_, str2bool, False),
+ (nx.integer, int, -1),
+ (nx.floating, float, nx.nan),
+ (complex, complex, nx.nan+0j),
+ (nx.string_, str, '???')]
+ (_defaulttype, _defaultfunc, _defaultfill) = zip(*_mapper)
+ #
+ @classmethod
+ def _getsubdtype(cls, val):
+ """Returns the type of the dtype of the input variable."""
+ return np.array(val).dtype.type
+ #
+ @classmethod
+ def upgrade_mapper(cls, func, default=None):
+ """
+ Upgrade the mapper of a StringConverter by adding a new function and its
+ corresponding default.
+
+ The input function (or sequence of functions) and its associated default
+ value (if any) is inserted in penultimate position of the mapper.
+ The corresponding type is estimated from the dtype of the default value.
+
+ Parameters
+ ----------
+ func : var
+ Function, or sequence of functions
+
+ Examples
+ --------
+ >>> import dateutil.parser
+ >>> import datetime
+ >>> dateparser = datetutil.parser.parse
+ >>> defaultdate = datetime.date(2000, 1, 1)
+ >>> StringConverter.upgrade_mapper(dateparser, default=defaultdate)
+ """
+ # Func is a single functions
+ if hasattr(func, '__call__'):
+ cls._mapper.insert(-1, (cls._getsubdtype(default), func, default))
+ return
+ elif hasattr(func, '__iter__'):
+ if isinstance(func[0], (tuple, list)):
+ for _ in func:
+ cls._mapper.insert(-1, _)
+ return
+ if default is None:
+ default = [None] * len(func)
+ else:
+ default = list(default)
+ default.append([None] * (len(func)-len(default)))
+ for (fct, dft) in zip(func, default):
+ cls._mapper.insert(-1, (cls._getsubdtype(dft), fct, dft))
+ #
+ def __init__(self, dtype_or_func=None, default=None, missing_values=None,
+ locked=False):
+ # Defines a lock for upgrade
+ self._locked = bool(locked)
+ # No input dtype: minimal initialization
+ if dtype_or_func is None:
+ self.func = str2bool
+ self._status = 0
+ self.default = default or False
+ ttype = np.bool
+ else:
+ # Is the input a np.dtype ?
+ try:
+ self.func = None
+ ttype = np.dtype(dtype_or_func).type
+ except TypeError:
+ # dtype_or_func must be a function, then
+ if not hasattr(dtype_or_func, '__call__'):
+ errmsg = "The input argument `dtype` is neither a function"\
+ " or a dtype (got '%s' instead)"
+ raise TypeError(errmsg % type(dtype_or_func))
+ # Set the function
+ self.func = dtype_or_func
+ # If we don't have a default, try to guess it or set it to None
+ if default is None:
+ try:
+ default = self.func('0')
+ except ValueError:
+ default = None
+ ttype = self._getsubdtype(default)
+ # Set the status according to the dtype
+ _status = -1
+ for (i, (deftype, func, default_def)) in enumerate(self._mapper):
+ if np.issubdtype(ttype, deftype):
+ _status = i
+ self.default = default or default_def
+ break
+ if _status == -1:
+ # We never found a match in the _mapper...
+ _status = 0
+ self.default = default
+ self._status = _status
+ # If the input was a dtype, set the function to the last we saw
+ if self.func is None:
+ self.func = func
+ # If the status is 1 (int), change the function to smthg more robust
+ if self.func == self._mapper[1][1]:
+ self.func = lambda x : int(float(x))
+ # Store the list of strings corresponding to missing values.
+ if missing_values is None:
+ self.missing_values = set([''])
+ else:
+ self.missing_values = set(list(missing_values) + [''])
+ #
+ self._callingfunction = self._strict_call
+ self.type = ttype
+ self._checked = False
+ #
+ def _loose_call(self, value):
+ try:
+ return self.func(value)
+ except ValueError:
+ return self.default
+ #
+ def _strict_call(self, value):
+ try:
+ return self.func(value)
+ except ValueError:
+ if value.strip() in self.missing_values:
+ if not self._status:
+ self._checked = False
+ return self.default
+ raise ValueError("Cannot convert string '%s'" % value)
+ #
+ def __call__(self, value):
+ return self._callingfunction(value)
+ #
+ def upgrade(self, value):
+ """
+ Tries to find the best converter for `value`, by testing different
+ converters in order.
+ The order in which the converters are tested is read from the
+ :attr:`_status` attribute of the instance.
+ """
+ self._checked = True
+ try:
+ self._strict_call(value)
+ except ValueError:
+ # Raise an exception if we locked the converter...
+ if self._locked:
+ raise ValueError("Converter is locked and cannot be upgraded")
+ _statusmax = len(self._mapper)
+ # Complains if we try to upgrade by the maximum
+ if self._status == _statusmax:
+ raise ValueError("Could not find a valid conversion function")
+ elif self._status < _statusmax - 1:
+ self._status += 1
+ (self.type, self.func, self.default) = self._mapper[self._status]
+ self.upgrade(value)
+ #
+ def update(self, func, default=None, missing_values='', locked=False):
+ """
+ Sets the :attr:`func` and :attr:`default` attributes directly.
+
+ Parameters
+ ----------
+ func : function
+ Conversion function.
+ default : {var}, optional
+ Default value to return when a missing value is encountered.
+ missing_values : {var}, optional
+ Sequence of strings representing missing values.
+ locked : {False, True}, optional
+ Whether the status should be locked to prevent automatic upgrade.
+ """
+ self.func = func
+ self._locked = locked
+ # Don't reset the default to None if we can avoid it
+ if default is not None:
+ self.default = default
+ # Add the missing values to the existing set
+ if missing_values is not None:
+ if _is_string_like(missing_values):
+ self.missing_values.add(missing_values)
+ elif hasattr(missing_values, '__iter__'):
+ for val in missing_values:
+ self.missing_values.add(val)
+ else:
+ self.missing_values = []
+ # Update the type
+ try:
+ tester = func('0')
+ except ValueError:
+ tester = None
+ self.type = self._getsubdtype(tester)
+
diff --git a/numpy/lib/arraysetops.py b/numpy/lib/arraysetops.py
index 49a1d3e89..f023f6027 100644
--- a/numpy/lib/arraysetops.py
+++ b/numpy/lib/arraysetops.py
@@ -52,13 +52,19 @@ def ediff1d(ary, to_end=None, to_begin=None):
If provided, this number will be taked onto the beginning of the
returned differences.
+ Notes
+ -----
+ When applied to masked arrays, this function drops the mask information
+ if the `to_begin` and/or `to_end` parameters are used
+
+
Returns
-------
ed : array
The differences. Loosely, this will be (ary[1:] - ary[:-1]).
"""
- ary = np.asarray(ary).flat
+ ary = np.asanyarray(ary).flat
ed = ary[1:] - ary[:-1]
arrays = [ed]
if to_begin is not None:
@@ -132,7 +138,7 @@ def unique1d(ar1, return_index=False, return_inverse=False):
"the output was (indices, unique_arr), but "
"has now been reversed to be more consistent.")
- ar = np.asarray(ar1).flatten()
+ ar = np.asanyarray(ar1).flatten()
if ar.size == 0:
if return_inverse and return_index:
return ar, np.empty(0, np.bool), np.empty(0, np.bool)
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 8bf20d3fb..283e3faff 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -228,10 +228,10 @@ def histogram(a, bins=10, range=None, normed=False, weights=None, new=None):
* None : the new behaviour is used, no warning is printed.
* True : the new behaviour is used and a warning is raised about
the future removal of the `new` keyword.
- * False : the old behaviour is used and a DeprecationWarning
+ * False : the old behaviour is used and a DeprecationWarning
is raised.
- As of NumPy 1.3, this keyword should not be used explicitly since it
- will disappear in NumPy 1.4.
+ As of NumPy 1.3, this keyword should not be used explicitly since it
+ will disappear in NumPy 1.4.
Returns
-------
@@ -267,9 +267,9 @@ def histogram(a, bins=10, range=None, normed=False, weights=None, new=None):
# Old behavior
if new == False:
warnings.warn("""
- The histogram semantics being used is now deprecated and
- will disappear in NumPy 1.4. Please update your code to
- use the default semantics.
+ The histogram semantics being used is now deprecated and
+ will disappear in NumPy 1.4. Please update your code to
+ use the default semantics.
""", DeprecationWarning)
a = asarray(a).ravel()
@@ -320,8 +320,8 @@ def histogram(a, bins=10, range=None, normed=False, weights=None, new=None):
elif new in [True, None]:
if new is True:
warnings.warn("""
- The new semantics of histogram is now the default and the `new`
- keyword will be removed in NumPy 1.4.
+ The new semantics of histogram is now the default and the `new`
+ keyword will be removed in NumPy 1.4.
""", Warning)
a = asarray(a)
if weights is not None:
@@ -1073,53 +1073,6 @@ def diff(a, n=1, axis=-1):
else:
return a[slice1]-a[slice2]
-try:
- add_docstring(digitize,
-r"""digitize(x,bins)
-
-Return the index of the bin to which each value of x belongs.
-
-Each index i returned is such that bins[i-1] <= x < bins[i] if
-bins is monotonically increasing, or bins [i-1] > x >= bins[i] if
-bins is monotonically decreasing.
-
-Beyond the bounds of the bins 0 or len(bins) is returned as appropriate.
-
-""")
-except RuntimeError:
- pass
-
-try:
- add_docstring(bincount,
-r"""bincount(x,weights=None)
-
-Return the number of occurrences of each value in x.
-
-x must be a list of non-negative integers. The output, b[i],
-represents the number of times that i is found in x. If weights
-is specified, every occurrence of i at a position p contributes
-weights[p] instead of 1.
-
-See also: histogram, digitize, unique.
-
-""")
-except RuntimeError:
- pass
-
-try:
- add_docstring(add_docstring,
-r"""docstring(obj, docstring)
-
-Add a docstring to a built-in obj if possible.
-If the obj already has a docstring raise a RuntimeError
-If this routine does not know how to add a docstring to the object
-raise a TypeError
-
-""")
-except RuntimeError:
- pass
-
-
def interp(x, xp, fp, left=None, right=None):
"""
One-dimensional linear interpolation.
@@ -2818,9 +2771,9 @@ def trapz(y, x=None, dx=1.0, axis=-1):
y : array_like
Input array to integrate.
x : array_like, optional
- If `x` is None, then spacing between all `y` elements is 1.
+ If `x` is None, then spacing between all `y` elements is `dx`.
dx : scalar, optional
- If `x` is None, spacing given by `dx` is assumed.
+ If `x` is None, spacing given by `dx` is assumed. Default is 1.
axis : int, optional
Specify the axis.
@@ -2836,7 +2789,15 @@ def trapz(y, x=None, dx=1.0, axis=-1):
if x is None:
d = dx
else:
- d = diff(x,axis=axis)
+ x = asarray(x)
+ if x.ndim == 1:
+ d = diff(x)
+ # reshape to correct shape
+ shape = [1]*y.ndim
+ shape[axis] = d.shape[0]
+ d = d.reshape(shape)
+ else:
+ d = diff(x, axis=axis)
nd = len(y.shape)
slice1 = [slice(None)]*nd
slice2 = [slice(None)]*nd
diff --git a/numpy/lib/getlimits.py b/numpy/lib/getlimits.py
index bc5fbbf5e..ccb0e2b3d 100644
--- a/numpy/lib/getlimits.py
+++ b/numpy/lib/getlimits.py
@@ -88,6 +88,12 @@ class finfo(object):
_finfo_cache = {}
def __new__(cls, dtype):
+ try:
+ dtype = np.dtype(dtype)
+ except TypeError:
+ # In case a float instance was given
+ dtype = np.dtype(type(dtype))
+
obj = cls._finfo_cache.get(dtype,None)
if obj is not None:
return obj
@@ -115,7 +121,7 @@ class finfo(object):
return obj
def _init(self, dtype):
- self.dtype = dtype
+ self.dtype = np.dtype(dtype)
if dtype is ntypes.double:
itype = ntypes.int64
fmt = '%24.16e'
@@ -149,23 +155,23 @@ class finfo(object):
self.nexp = machar.iexp
self.nmant = machar.it
self.machar = machar
- self._str_tiny = machar._str_xmin
- self._str_max = machar._str_xmax
- self._str_epsneg = machar._str_epsneg
- self._str_eps = machar._str_eps
- self._str_resolution = machar._str_resolution
+ self._str_tiny = machar._str_xmin.strip()
+ self._str_max = machar._str_xmax.strip()
+ self._str_epsneg = machar._str_epsneg.strip()
+ self._str_eps = machar._str_eps.strip()
+ self._str_resolution = machar._str_resolution.strip()
return self
def __str__(self):
return '''\
Machine parameters for %(dtype)s
---------------------------------------------------------------------
-precision=%(precision)3s resolution=%(_str_resolution)s
-machep=%(machep)6s eps= %(_str_eps)s
-negep =%(negep)6s epsneg= %(_str_epsneg)s
-minexp=%(minexp)6s tiny= %(_str_tiny)s
-maxexp=%(maxexp)6s max= %(_str_max)s
-nexp =%(nexp)6s min= -max
+precision=%(precision)3s resolution= %(_str_resolution)s
+machep=%(machep)6s eps= %(_str_eps)s
+negep =%(negep)6s epsneg= %(_str_epsneg)s
+minexp=%(minexp)6s tiny= %(_str_tiny)s
+maxexp=%(maxexp)6s max= %(_str_max)s
+nexp =%(nexp)6s min= -max
---------------------------------------------------------------------
''' % self.__dict__
@@ -220,8 +226,11 @@ class iinfo:
_min_vals = {}
_max_vals = {}
- def __init__(self, type):
- self.dtype = np.dtype(type)
+ def __init__(self, int_type):
+ try:
+ self.dtype = np.dtype(int_type)
+ except TypeError:
+ self.dtype = np.dtype(type(int_type))
self.kind = self.dtype.kind
self.bits = self.dtype.itemsize * 8
self.key = "%s%d" % (self.kind, self.bits)
@@ -256,6 +265,17 @@ class iinfo:
max = property(max)
+ def __str__(self):
+ """String representation."""
+ return '''\
+Machine parameters for %(dtype)s
+---------------------------------------------------------------------
+min = %(min)s
+max = %(max)s
+---------------------------------------------------------------------
+''' % {'dtype': self.dtype, 'min': self.min, 'max': self.max}
+
+
if __name__ == '__main__':
f = finfo(ntypes.single)
print 'single epsilon:',f.eps
diff --git a/numpy/lib/index_tricks.py b/numpy/lib/index_tricks.py
index 3021635dc..fcd3909af 100644
--- a/numpy/lib/index_tricks.py
+++ b/numpy/lib/index_tricks.py
@@ -212,6 +212,8 @@ class nd_grid(object):
mgrid = nd_grid(sparse=False)
ogrid = nd_grid(sparse=True)
+mgrid.__doc__ = None # set in numpy.add_newdocs
+ogrid.__doc__ = None # set in numpy.add_newdocs
class AxisConcatenator(object):
"""Translates slice objects to concatenation along an axis.
diff --git a/numpy/lib/info.py b/numpy/lib/info.py
index 0944fa9b5..f93234d57 100644
--- a/numpy/lib/info.py
+++ b/numpy/lib/info.py
@@ -1,134 +1,149 @@
-__doc_title__ = """Basic functions used by several sub-packages and
-useful to have in the main name-space."""
-__doc__ = __doc_title__ + """
-
-Type handling
-==============
-iscomplexobj -- Test for complex object, scalar result
-isrealobj -- Test for real object, scalar result
-iscomplex -- Test for complex elements, array result
-isreal -- Test for real elements, array result
-imag -- Imaginary part
-real -- Real part
-real_if_close -- Turns complex number with tiny imaginary part to real
-isneginf -- Tests for negative infinity ---|
-isposinf -- Tests for positive infinity |
-isnan -- Tests for nans |---- array results
-isinf -- Tests for infinity |
-isfinite -- Tests for finite numbers ---|
-isscalar -- True if argument is a scalar
-nan_to_num -- Replaces NaN's with 0 and infinities with large numbers
-cast -- Dictionary of functions to force cast to each type
-common_type -- Determine the 'minimum common type code' for a group
- of arrays
-mintypecode -- Return minimal allowed common typecode.
+"""
+Basic functions used by several sub-packages and
+useful to have in the main name-space.
-Index tricks
-==================
-mgrid -- Method which allows easy construction of N-d 'mesh-grids'
-r_ -- Append and construct arrays: turns slice objects into
- ranges and concatenates them, for 2d arrays appends
- rows.
-index_exp -- Konrad Hinsen's index_expression class instance which
- can be useful for building complicated slicing syntax.
+Type Handling
+-------------
+================ ===================
+iscomplexobj Test for complex object, scalar result
+isrealobj Test for real object, scalar result
+iscomplex Test for complex elements, array result
+isreal Test for real elements, array result
+imag Imaginary part
+real Real part
+real_if_close Turns complex number with tiny imaginary part to real
+isneginf Tests for negative infinity, array result
+isposinf Tests for positive infinity, array result
+isnan Tests for nans, array result
+isinf Tests for infinity, array result
+isfinite Tests for finite numbers, array result
+isscalar True if argument is a scalar
+nan_to_num Replaces NaN's with 0 and infinities with large numbers
+cast Dictionary of functions to force cast to each type
+common_type Determine the minimum common type code for a group
+ of arrays
+mintypecode Return minimal allowed common typecode.
+================ ===================
-Useful functions
-==================
-select -- Extension of where to multiple conditions and choices
-extract -- Extract 1d array from flattened array according to mask
-insert -- Insert 1d array of values into Nd array according to mask
-linspace -- Evenly spaced samples in linear space
-logspace -- Evenly spaced samples in logarithmic space
-fix -- Round x to nearest integer towards zero
-mod -- Modulo mod(x,y) = x % y except keeps sign of y
-amax -- Array maximum along axis
-amin -- Array minimum along axis
-ptp -- Array max-min along axis
-cumsum -- Cumulative sum along axis
-prod -- Product of elements along axis
-cumprod -- Cumluative product along axis
-diff -- Discrete differences along axis
-angle -- Returns angle of complex argument
-unwrap -- Unwrap phase along given axis (1-d algorithm)
-sort_complex -- Sort a complex-array (based on real, then imaginary)
-trim_zeros -- trim the leading and trailing zeros from 1D array.
+Index Tricks
+------------
+================ ===================
+mgrid Method which allows easy construction of N-d
+ 'mesh-grids'
+``r_`` Append and construct arrays: turns slice objects into
+ ranges and concatenates them, for 2d arrays appends rows.
+index_exp Konrad Hinsen's index_expression class instance which
+ can be useful for building complicated slicing syntax.
+================ ===================
-vectorize -- a class that wraps a Python function taking scalar
- arguments into a generalized function which
- can handle arrays of arguments using the broadcast
- rules of numerix Python.
+Useful Functions
+----------------
+================ ===================
+select Extension of where to multiple conditions and choices
+extract Extract 1d array from flattened array according to mask
+insert Insert 1d array of values into Nd array according to mask
+linspace Evenly spaced samples in linear space
+logspace Evenly spaced samples in logarithmic space
+fix Round x to nearest integer towards zero
+mod Modulo mod(x,y) = x % y except keeps sign of y
+amax Array maximum along axis
+amin Array minimum along axis
+ptp Array max-min along axis
+cumsum Cumulative sum along axis
+prod Product of elements along axis
+cumprod Cumluative product along axis
+diff Discrete differences along axis
+angle Returns angle of complex argument
+unwrap Unwrap phase along given axis (1-d algorithm)
+sort_complex Sort a complex-array (based on real, then imaginary)
+trim_zeros Trim the leading and trailing zeros from 1D array.
+vectorize A class that wraps a Python function taking scalar
+ arguments into a generalized function which can handle
+ arrays of arguments using the broadcast rules of
+ numerix Python.
+================ ===================
-Shape manipulation
-===================
-squeeze -- Return a with length-one dimensions removed.
-atleast_1d -- Force arrays to be > 1D
-atleast_2d -- Force arrays to be > 2D
-atleast_3d -- Force arrays to be > 3D
-vstack -- Stack arrays vertically (row on row)
-hstack -- Stack arrays horizontally (column on column)
-column_stack -- Stack 1D arrays as columns into 2D array
-dstack -- Stack arrays depthwise (along third dimension)
-split -- Divide array into a list of sub-arrays
-hsplit -- Split into columns
-vsplit -- Split into rows
-dsplit -- Split along third dimension
+Shape Manipulation
+------------------
+================ ===================
+squeeze Return a with length-one dimensions removed.
+atleast_1d Force arrays to be > 1D
+atleast_2d Force arrays to be > 2D
+atleast_3d Force arrays to be > 3D
+vstack Stack arrays vertically (row on row)
+hstack Stack arrays horizontally (column on column)
+column_stack Stack 1D arrays as columns into 2D array
+dstack Stack arrays depthwise (along third dimension)
+split Divide array into a list of sub-arrays
+hsplit Split into columns
+vsplit Split into rows
+dsplit Split along third dimension
+================ ===================
-Matrix (2d array) manipluations
-===============================
-fliplr -- 2D array with columns flipped
-flipud -- 2D array with rows flipped
-rot90 -- Rotate a 2D array a multiple of 90 degrees
-eye -- Return a 2D array with ones down a given diagonal
-diag -- Construct a 2D array from a vector, or return a given
- diagonal from a 2D array.
-mat -- Construct a Matrix
-bmat -- Build a Matrix from blocks
+Matrix (2D Array) Manipulations
+-------------------------------
+================ ===================
+fliplr 2D array with columns flipped
+flipud 2D array with rows flipped
+rot90 Rotate a 2D array a multiple of 90 degrees
+eye Return a 2D array with ones down a given diagonal
+diag Construct a 2D array from a vector, or return a given
+ diagonal from a 2D array.
+mat Construct a Matrix
+bmat Build a Matrix from blocks
+================ ===================
Polynomials
-============
-poly1d -- A one-dimensional polynomial class
-
-poly -- Return polynomial coefficients from roots
-roots -- Find roots of polynomial given coefficients
-polyint -- Integrate polynomial
-polyder -- Differentiate polynomial
-polyadd -- Add polynomials
-polysub -- Substract polynomials
-polymul -- Multiply polynomials
-polydiv -- Divide polynomials
-polyval -- Evaluate polynomial at given argument
+-----------
+================ ===================
+poly1d A one-dimensional polynomial class
+poly Return polynomial coefficients from roots
+roots Find roots of polynomial given coefficients
+polyint Integrate polynomial
+polyder Differentiate polynomial
+polyadd Add polynomials
+polysub Substract polynomials
+polymul Multiply polynomials
+polydiv Divide polynomials
+polyval Evaluate polynomial at given argument
+================ ===================
-Import tricks
-=============
-ppimport -- Postpone module import until trying to use it
-ppimport_attr -- Postpone module import until trying to use its
- attribute
-ppresolve -- Import postponed module and return it.
+Import Tricks
+-------------
+================ ===================
+ppimport Postpone module import until trying to use it
+ppimport_attr Postpone module import until trying to use its attribute
+ppresolve Import postponed module and return it.
+================ ===================
-Machine arithmetics
-===================
-machar_single -- MachAr instance storing the parameters of system
- single precision floating point arithmetics
-machar_double -- MachAr instance storing the parameters of system
- double precision floating point arithmetics
+Machine Arithmetics
+-------------------
+================ ===================
+machar_single Single precision floating point arithmetic parameters
+machar_double Double precision floating point arithmetic parameters
+================ ===================
-Threading tricks
-================
-ParallelExec -- Execute commands in parallel thread.
+Threading Tricks
+----------------
+================ ===================
+ParallelExec Execute commands in parallel thread.
+================ ===================
-1D array set operations
-=======================
+1D Array Set Operations
+-----------------------
Set operations for 1D numeric arrays based on sort() function.
-ediff1d -- Array difference (auxiliary function).
-unique1d -- Unique elements of 1D array.
-intersect1d -- Intersection of 1D arrays with unique elements.
-intersect1d_nu -- Intersection of 1D arrays with any elements.
-setxor1d -- Set exclusive-or of 1D arrays with unique elements.
-setmember1d -- Return an array of shape of ar1 containing 1 where
- the elements of ar1 are in ar2 and 0 otherwise.
-union1d -- Union of 1D arrays with unique elements.
-setdiff1d -- Set difference of 1D arrays with unique elements.
+================ ===================
+ediff1d Array difference (auxiliary function).
+unique1d Unique elements of 1D array.
+intersect1d Intersection of 1D arrays with unique elements.
+intersect1d_nu Intersection of 1D arrays with any elements.
+setxor1d Set exclusive-or of 1D arrays with unique elements.
+setmember1d Return an array of shape of ar1 containing 1 where
+ the elements of ar1 are in ar2 and 0 otherwise.
+union1d Union of 1D arrays with unique elements.
+setdiff1d Set difference of 1D arrays with unique elements.
+================ ===================
"""
diff --git a/numpy/lib/io.py b/numpy/lib/io.py
index e9a012db1..12765e17c 100644
--- a/numpy/lib/io.py
+++ b/numpy/lib/io.py
@@ -1,4 +1,5 @@
__all__ = ['savetxt', 'loadtxt',
+ 'genfromtxt', 'ndfromtxt', 'mafromtxt', 'recfromtxt', 'recfromcsv',
'load', 'loads',
'save', 'savez',
'packbits', 'unpackbits',
@@ -15,7 +16,11 @@ from cPickle import load as _cload, loads
from _datasource import DataSource
from _compiled_base import packbits, unpackbits
+from _iotools import LineSplitter, NameValidator, StringConverter, \
+ _is_string_like, has_nested_fields, flatten_dtype
+
_file = file
+_string_like = _is_string_like
class BagObj(object):
"""A simple class that converts attribute lookups to
@@ -264,10 +269,6 @@ def _getconv(dtype):
return str
-def _string_like(obj):
- try: obj + ''
- except (TypeError, ValueError): return 0
- return 1
def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
skiprows=0, usecols=None, unpack=False):
@@ -342,7 +343,7 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None, converters=None,
if usecols is not None:
usecols = list(usecols)
- if _string_like(fname):
+ if _is_string_like(fname):
if fname.endswith('.gz'):
import gzip
fh = gzip.open(fname)
@@ -520,7 +521,7 @@ def savetxt(fname, X, fmt='%.18e',delimiter=' '):
"""
- if _string_like(fname):
+ if _is_string_like(fname):
if fname.endswith('.gz'):
import gzip
fh = gzip.open(fname,'wb')
@@ -603,8 +604,508 @@ def fromregex(file, regexp, dtype):
seq = regexp.findall(file.read())
if seq and not isinstance(seq[0], tuple):
- # make sure np.array doesn't interpret strings as binary data
- # by always producing a list of tuples
- seq = [(x,) for x in seq]
- output = np.array(seq, dtype=dtype)
+ # Only one group is in the regexp.
+ # Create the new array as a single data-type and then
+ # re-interpret as a single-field structured array.
+ newdtype = np.dtype(dtype[dtype.names[0]])
+ output = np.array(seq, dtype=newdtype)
+ output.dtype = dtype
+ else:
+ output = np.array(seq, dtype=dtype)
+
return output
+
+
+
+
+#####--------------------------------------------------------------------------
+#---- --- ASCII functions ---
+#####--------------------------------------------------------------------------
+
+
+
+def genfromtxt(fname, dtype=float, comments='#', delimiter=None, skiprows=0,
+ converters=None, missing='', missing_values=None, usecols=None,
+ names=None, excludelist=None, deletechars=None,
+ case_sensitive=True, unpack=None, usemask=False, loose=True):
+ """
+ Load data from a text file.
+
+ Each line past the first `skiprows` ones is split at the `delimiter`
+ character, and characters following the `comments` character are discarded.
+
+
+
+ Parameters
+ ----------
+ fname : file or string
+ 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 flexible data-type,
+ the resulting array will be 1-dimensional, and each row will be
+ interpreted as an element of the array. In this case, the number
+ of columns used must match the number of fields in the data-type,
+ and the names of each field will be set by the corresponding name
+ of the dtype.
+ If None, the dtypes will be determined by the contents of each
+ column, individually.
+ comments : {string}, optional
+ The character used to indicate the start of a comment.
+ All the characters occurring on a line after a comment are discarded
+ delimiter : {string}, optional
+ The string used to separate values. By default, any consecutive
+ whitespace act as delimiter.
+ skiprows : {int}, optional
+ Numbers of lines to skip at the beginning of the file.
+ converters : {None, dictionary}, optional
+ A dictionary mapping column number to a function that will convert
+ values in the column to a number. Converters can also be used to
+ provide a default value for missing data:
+ ``converters = {3: lambda s: float(s or 0)}``.
+ missing : {string}, optional
+ A string representing a missing value, irrespective of the column where
+ it appears (e.g., `'missing'` or `'unused'`).
+ missing_values : {None, dictionary}, optional
+ A dictionary mapping a column number to a string indicating whether the
+ corresponding field should be masked.
+ usecols : {None, sequence}, optional
+ Which columns to read, with 0 being the first. For example,
+ ``usecols = (1,4,5)`` will extract the 2nd, 5th and 6th columns.
+ names : {None, True, string, sequence}, optional
+ If `names` is True, the field names are read from the first valid line
+ after the first `skiprows` lines.
+ If `names` is a sequence or a single-string of comma-separated names,
+ the names will be used to define the field names in a flexible dtype.
+ If `names` is None, the names of the dtype fields will be used, if any.
+ excludelist : {sequence}, optional
+ A list of names to exclude. This list is appended to the default list
+ ['return','file','print']. Excluded names are appended an underscore:
+ for example, `file` would become `file_`.
+ deletechars : {string}, optional
+ A string combining invalid characters that must be deleted from the names.
+ case_sensitive : {True, False, 'upper', 'lower'}, optional
+ If True, field names are case_sensitive.
+ If False or 'upper', field names are converted to upper case.
+ If 'lower', field names are converted to lower case.
+ unpack : {bool}, optional
+ If True, the returned array is transposed, so that arguments may be
+ unpacked using ``x, y, z = loadtxt(...)``
+ usemask : {bool}, optional
+ If True, returns a masked array.
+ If False, return a regular standard array.
+
+ Returns
+ -------
+ out : MaskedArray
+ Data read from the text file.
+
+ Notes
+ --------
+ * When spaces are used as delimiters, or when no delimiter has been given
+ as input, there should not be any missing data between two fields.
+ * When the variable are named (either by a flexible dtype or with `names`,
+ there must not be any header in the file (else a :exc:ValueError exception
+ is raised).
+
+ Warnings
+ --------
+ * Individual values are not stripped of spaces by default.
+ When using a custom converter, make sure the function does remove spaces.
+
+ See Also
+ --------
+ numpy.loadtxt : equivalent function when no data is missing.
+
+ """
+ #
+ if usemask:
+ from numpy.ma import MaskedArray, make_mask_descr
+ # Check the input dictionary of converters
+ user_converters = converters or {}
+ if not isinstance(user_converters, dict):
+ errmsg = "The input argument 'converter' should be a valid dictionary "\
+ "(got '%s' instead)"
+ raise TypeError(errmsg % type(user_converters))
+ # Check the input dictionary of missing values
+ user_missing_values = missing_values or {}
+ if not isinstance(user_missing_values, dict):
+ errmsg = "The input argument 'missing_values' should be a valid "\
+ "dictionary (got '%s' instead)"
+ raise TypeError(errmsg % type(missing_values))
+ defmissing = [_.strip() for _ in missing.split(',')] + ['']
+
+ # Initialize the filehandle, the LineSplitter and the NameValidator
+# fhd = _to_filehandle(fname)
+ if isinstance(fname, basestring):
+ fhd = np.lib._datasource.open(fname)
+ elif not hasattr(fname, 'read'):
+ raise TypeError("The input should be a string or a filehandle. "\
+ "(got %s instead)" % type(fname))
+ else:
+ fhd = fname
+ split_line = LineSplitter(delimiter=delimiter, comments=comments,
+ autostrip=False)._handyman
+ validate_names = NameValidator(excludelist=excludelist,
+ deletechars=deletechars,
+ case_sensitive=case_sensitive)
+
+ # Get the first valid lines after the first skiprows ones
+ for i in xrange(skiprows):
+ fhd.readline()
+ first_values = None
+ while not first_values:
+ first_line = fhd.readline()
+ if first_line == '':
+ raise IOError('End-of-file reached before encountering data.')
+ if names is True:
+ first_values = first_line.strip().split(delimiter)
+ else:
+ first_values = split_line(first_line)
+ if names is True:
+ fval = first_values[0].strip()
+ if fval in comments:
+ del first_values[0]
+
+ # Check the columns to use
+ if usecols is not None:
+ usecols = list(usecols)
+ nbcols = len(usecols or first_values)
+
+ # Check the names and overwrite the dtype.names if needed
+ if dtype is not None:
+ dtype = np.dtype(dtype)
+ dtypenames = getattr(dtype, 'names', None)
+ if names is True:
+ names = validate_names([_.strip() for _ in first_values])
+ first_line =''
+ elif _is_string_like(names):
+ names = validate_names([_.strip() for _ in names.split(',')])
+ elif names:
+ names = validate_names(names)
+ elif dtypenames:
+ dtype.names = validate_names(dtypenames)
+ if names and dtypenames:
+ dtype.names = names
+
+ # If usecols is a list of names, convert to a list of indices
+ if usecols:
+ for (i, current) in enumerate(usecols):
+ if _is_string_like(current):
+ usecols[i] = names.index(current)
+
+ # If user_missing_values has names as keys, transform them to indices
+ missing_values = {}
+ for (key, val) in user_missing_values.iteritems():
+ # If val is a list, flatten it. In any case, add missing &'' to the list
+ if isinstance(val, (list, tuple)):
+ val = [str(_) for _ in val]
+ else:
+ val = [str(val),]
+ val.extend(defmissing)
+ if _is_string_like(key):
+ try:
+ missing_values[names.index(key)] = val
+ except ValueError:
+ pass
+ else:
+ missing_values[key] = val
+
+
+ # Initialize the default converters
+ if dtype is None:
+ # Note: we can't use a [...]*nbcols, as we would have 3 times the same
+ # ... converter, instead of 3 different converters.
+ converters = [StringConverter(None,
+ missing_values=missing_values.get(_, defmissing))
+ for _ in range(nbcols)]
+ else:
+ flatdtypes = flatten_dtype(dtype)
+ # Initialize the converters
+ if len(flatdtypes) > 1:
+ # Flexible type : get a converter from each dtype
+ converters = [StringConverter(dt,
+ missing_values=missing_values.get(i, defmissing),
+ locked=True)
+ for (i, dt) in enumerate(flatdtypes)]
+ else:
+ # Set to a default converter (but w/ different missing values)
+ converters = [StringConverter(dtype,
+ missing_values=missing_values.get(_, defmissing),
+ locked=True)
+ for _ in range(nbcols)]
+ missing_values = [_.missing_values for _ in converters]
+
+ # Update the converters to use the user-defined ones
+ uc_update = []
+ for (i, conv) in user_converters.iteritems():
+ # If the converter is specified by column names, use the index instead
+ if _is_string_like(i):
+ i = names.index(i)
+ if usecols:
+ try:
+ i = usecols.index(i)
+ except ValueError:
+ # Unused converter specified
+ continue
+ converters[i].update(conv, default=None,
+ missing_values=missing_values[i],
+ locked=True)
+ uc_update.append((i, conv))
+ # Make sure we have the corrected keys in user_converters...
+ user_converters.update(uc_update)
+
+ # Reset the names to match the usecols
+ if (not first_line) and usecols:
+ names = [names[_] for _ in usecols]
+
+ rows = []
+ append_to_rows = rows.append
+ if usemask:
+ masks = []
+ append_to_masks = masks.append
+ # Parse each line
+ for line in itertools.chain([first_line,], fhd):
+ values = split_line(line)
+ # Skip an empty line
+ if len(values) == 0:
+ continue
+ # Select only the columns we need
+ if usecols:
+ values = [values[_] for _ in usecols]
+ # Check whether we need to update the converter
+ if dtype is None:
+ for (converter, item) in zip(converters, values):
+ converter.upgrade(item)
+ # Store the values
+ append_to_rows(tuple(values))
+ if usemask:
+ append_to_masks(tuple([val.strip() in mss
+ for (val, mss) in zip(values,
+ missing_values)]))
+
+ # Convert each value according to the converter:
+ # We want to modify the list in place to avoid creating a new one...
+ if loose:
+ conversionfuncs = [conv._loose_call for conv in converters]
+ else:
+ conversionfuncs = [conv._strict_call for conv in converters]
+ for (i, vals) in enumerate(rows):
+ rows[i] = tuple([convert(val)
+ for (convert, val) in zip(conversionfuncs, vals)])
+
+ # Reset the dtype
+ data = rows
+ if dtype is None:
+ # Get the dtypes from the types of the converters
+ coldtypes = [conv.type for conv in converters]
+ # Find the columns with strings...
+ strcolidx = [i for (i, v) in enumerate(coldtypes)
+ if v in (type('S'), np.string_)]
+ # ... and take the largest number of chars.
+ for i in strcolidx:
+ coldtypes[i] = "|S%i" % max(len(row[i]) for row in data)
+ #
+ if names is None:
+ # If the dtype is uniform, don't define names, else use ''
+ base = set([c.type for c in converters if c._checked])
+
+ if len(base) == 1:
+ (ddtype, mdtype) = (list(base)[0], np.bool)
+ else:
+ ddtype = [('', dt) for dt in coldtypes]
+ mdtype = [('', np.bool) for dt in coldtypes]
+ else:
+ ddtype = zip(names, coldtypes)
+ mdtype = zip(names, [np.bool] * len(coldtypes))
+ output = np.array(data, dtype=ddtype)
+ if usemask:
+ outputmask = np.array(masks, dtype=mdtype)
+ else:
+ # Overwrite the initial dtype names if needed
+ if names and dtype.names:
+ dtype.names = names
+ flatdtypes = flatten_dtype(dtype)
+ # Case 1. We have a structured type
+ if len(flatdtypes) > 1:
+ # Nested dtype, eg [('a', int), ('b', [('b0', int), ('b1', 'f4')])]
+ # First, create the array using a flattened dtype:
+ # [('a', int), ('b1', int), ('b2', float)]
+ # Then, view the array using the specified dtype.
+ if has_nested_fields(dtype):
+ if 'O' in (_.char for _ in flatdtypes):
+ errmsg = "Nested fields involving objects "\
+ "are not supported..."
+ raise NotImplementedError(errmsg)
+ rows = np.array(data, dtype=[('', t) for t in flatdtypes])
+ output = rows.view(dtype)
+ else:
+ output = np.array(data, dtype=dtype)
+ # Now, process the rowmasks the same way
+ if usemask:
+ rowmasks = np.array(masks,
+ dtype=np.dtype([('', np.bool)
+ for t in flatdtypes]))
+ # Construct the new dtype
+ mdtype = make_mask_descr(dtype)
+ outputmask = rowmasks.view(mdtype)
+ # Case #2. We have a basic dtype
+ else:
+ # We used some user-defined converters
+ if user_converters:
+ ishomogeneous = True
+ descr = []
+ for (i, ttype) in enumerate([conv.type for conv in converters]):
+ # Keep the dtype of the current converter
+ if i in user_converters:
+ ishomogeneous &= (ttype == dtype.type)
+ if ttype == np.string_:
+ ttype = "|S%i" % max(len(row[i]) for row in data)
+ descr.append(('', ttype))
+ else:
+ descr.append(('', dtype))
+ # So we changed the dtype ?
+ if not ishomogeneous:
+ # We have more than one field
+ if len(descr) > 1:
+ dtype = np.dtype(descr)
+ # We have only one field: drop the name if not needed.
+ else:
+ dtype = np.dtype(ttype)
+ #
+ output = np.array(data, dtype)
+ if usemask:
+ if dtype.names:
+ mdtype = [(_, np.bool) for _ in dtype.names]
+ else:
+ mdtype = np.bool
+ outputmask = np.array(masks, dtype=mdtype)
+ # Try to take care of the missing data we missed
+ if usemask and output.dtype.names:
+ for (name, conv) in zip(names or (), converters):
+ missing_values = [conv(_) for _ in conv.missing_values if _ != '']
+ for mval in missing_values:
+ outputmask[name] |= (output[name] == mval)
+ # Construct the final array
+ if usemask:
+ output = output.view(MaskedArray)
+ output._mask = outputmask
+ if unpack:
+ return output.squeeze().T
+ return output.squeeze()
+
+
+
+def ndfromtxt(fname, dtype=float, comments='#', delimiter=None, skiprows=0,
+ converters=None, missing='', missing_values=None,
+ usecols=None, unpack=None, names=None,
+ excludelist=None, deletechars=None, case_sensitive=True,):
+ """
+ Load ASCII data stored in fname and returns a ndarray.
+
+ Complete description of all the optional input parameters is available in
+ the docstring of the `genfromtxt` function.
+
+ See Also
+ --------
+ numpy.genfromtxt : generic function.
+
+ """
+ kwargs = dict(dtype=dtype, comments=comments, delimiter=delimiter,
+ skiprows=skiprows, converters=converters,
+ missing=missing, missing_values=missing_values,
+ usecols=usecols, unpack=unpack, names=names,
+ excludelist=excludelist, deletechars=deletechars,
+ case_sensitive=case_sensitive, usemask=False)
+ return genfromtxt(fname, **kwargs)
+
+def mafromtxt(fname, dtype=float, comments='#', delimiter=None, skiprows=0,
+ converters=None, missing='', missing_values=None,
+ usecols=None, unpack=None, names=None,
+ excludelist=None, deletechars=None, case_sensitive=True,):
+ """
+ Load ASCII data stored in fname and returns a MaskedArray.
+
+ Complete description of all the optional input parameters is available in
+ the docstring of the `genfromtxt` function.
+
+ See Also
+ --------
+ numpy.genfromtxt : generic function.
+ """
+ kwargs = dict(dtype=dtype, comments=comments, delimiter=delimiter,
+ skiprows=skiprows, converters=converters,
+ missing=missing, missing_values=missing_values,
+ usecols=usecols, unpack=unpack, names=names,
+ excludelist=excludelist, deletechars=deletechars,
+ case_sensitive=case_sensitive,
+ usemask=True)
+ return genfromtxt(fname, **kwargs)
+
+
+def recfromtxt(fname, dtype=None, comments='#', delimiter=None, skiprows=0,
+ converters=None, missing='', missing_values=None,
+ usecols=None, unpack=None, names=None,
+ excludelist=None, deletechars=None, case_sensitive=True,
+ usemask=False):
+ """
+ Load ASCII data stored in fname and returns a standard recarray (if
+ `usemask=False`) or a MaskedRecords (if `usemask=True`).
+
+ Complete description of all the optional input parameters is available in
+ the docstring of the `genfromtxt` function.
+
+ See Also
+ --------
+ numpy.genfromtxt : generic function
+
+ Warnings
+ --------
+ * by default, `dtype=None`, which means that the dtype of the output array
+ will be determined from the data.
+ """
+ kwargs = dict(dtype=dtype, comments=comments, delimiter=delimiter,
+ skiprows=skiprows, converters=converters,
+ missing=missing, missing_values=missing_values,
+ usecols=usecols, unpack=unpack, names=names,
+ excludelist=excludelist, deletechars=deletechars,
+ case_sensitive=case_sensitive, usemask=usemask)
+ output = genfromtxt(fname, **kwargs)
+ if usemask:
+ from numpy.ma.mrecords import MaskedRecords
+ output = output.view(MaskedRecords)
+ else:
+ output = output.view(np.recarray)
+ return output
+
+
+def recfromcsv(fname, dtype=None, comments='#', skiprows=0,
+ converters=None, missing='', missing_values=None,
+ usecols=None, unpack=None, names=True,
+ excludelist=None, deletechars=None, case_sensitive='lower',
+ usemask=False):
+ """
+ Load ASCII data stored in comma-separated file and returns a recarray (if
+ `usemask=False`) or a MaskedRecords (if `usemask=True`).
+
+ Complete description of all the optional input parameters is available in
+ the docstring of the `genfromtxt` function.
+
+ See Also
+ --------
+ numpy.genfromtxt : generic function
+ """
+ kwargs = dict(dtype=dtype, comments=comments, delimiter=",",
+ skiprows=skiprows, converters=converters,
+ missing=missing, missing_values=missing_values,
+ usecols=usecols, unpack=unpack, names=names,
+ excludelist=excludelist, deletechars=deletechars,
+ case_sensitive=case_sensitive, usemask=usemask)
+ output = genfromtxt(fname, **kwargs)
+ if usemask:
+ from numpy.ma.mrecords import MaskedRecords
+ output = output.view(MaskedRecords)
+ else:
+ output = output.view(np.recarray)
+ return output
+
diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py
new file mode 100644
index 000000000..b3eecdc0e
--- /dev/null
+++ b/numpy/lib/recfunctions.py
@@ -0,0 +1,942 @@
+"""
+Collection of utilities to manipulate structured arrays.
+
+Most of these functions were initially implemented by John Hunter for matplotlib.
+They have been rewritten and extended for convenience.
+
+
+"""
+
+
+import itertools
+from itertools import chain as iterchain, repeat as iterrepeat, izip as iterizip
+import numpy as np
+from numpy import ndarray, recarray
+import numpy.ma as ma
+from numpy.ma import MaskedArray
+from numpy.ma.mrecords import MaskedRecords
+
+from numpy.lib._iotools import _is_string_like
+
+_check_fill_value = np.ma.core._check_fill_value
+
+__all__ = ['append_fields',
+ 'drop_fields',
+ 'find_duplicates',
+ 'get_fieldstructure',
+ 'join_by',
+ 'merge_arrays',
+ 'rec_append_fields', 'rec_drop_fields', 'rec_join',
+ 'recursive_fill_fields', 'rename_fields',
+ 'stack_arrays',
+ ]
+
+
+def recursive_fill_fields(input, output):
+ """
+ Fills fields from output with fields from input,
+ with support for nested structures.
+
+ Parameters
+ ----------
+ input : ndarray
+ Input array.
+ output : ndarray
+ Output array.
+
+ Notes
+ -----
+ * `output` should be at least the same size as `input`
+
+ Examples
+ --------
+ >>> a = np.array([(1, 10.), (2, 20.)], dtype=[('A', int), ('B', float)])
+ >>> b = np.zeros((3,), dtype=a.dtype)
+ >>> recursive_fill_fields(a, b)
+ np.array([(1, 10.), (2, 20.), (0, 0.)], dtype=[('A', int), ('B', float)])
+
+ """
+ newdtype = output.dtype
+ for field in newdtype.names:
+ try:
+ current = input[field]
+ except ValueError:
+ continue
+ if current.dtype.names:
+ recursive_fill_fields(current, output[field])
+ else:
+ output[field][:len(current)] = current
+ return output
+
+
+
+def get_names(adtype):
+ """
+ Returns the field names of the input datatype as a tuple.
+
+ Parameters
+ ----------
+ adtype : dtype
+ Input datatype
+
+ Examples
+ --------
+ >>> get_names(np.empty((1,), dtype=int)) is None
+ True
+ >>> get_names(np.empty((1,), dtype=[('A',int), ('B', float)]))
+ ('A', 'B')
+ >>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
+ >>> get_names(adtype)
+ ('a', ('b', ('ba', 'bb')))
+ """
+ listnames = []
+ names = adtype.names
+ for name in names:
+ current = adtype[name]
+ if current.names:
+ listnames.append((name, tuple(get_names(current))))
+ else:
+ listnames.append(name)
+ return tuple(listnames) or None
+
+
+def get_names_flat(adtype):
+ """
+ Returns the field names of the input datatype as a tuple. Nested structure
+ are flattend beforehand.
+
+ Parameters
+ ----------
+ adtype : dtype
+ Input datatype
+
+ Examples
+ --------
+ >>> get_names_flat(np.empty((1,), dtype=int)) is None
+ True
+ >>> get_names_flat(np.empty((1,), dtype=[('A',int), ('B', float)]))
+ ('A', 'B')
+ >>> adtype = np.dtype([('a', int), ('b', [('ba', int), ('bb', int)])])
+ >>> get_names_flat(adtype)
+ ('a', 'b', 'ba', 'bb')
+ """
+ listnames = []
+ names = adtype.names
+ for name in names:
+ listnames.append(name)
+ current = adtype[name]
+ if current.names:
+ listnames.extend(get_names_flat(current))
+ return tuple(listnames) or None
+
+
+def flatten_descr(ndtype):
+ """
+ Flatten a structured data-type description.
+
+ Examples
+ --------
+ >>> ndtype = np.dtype([('a', '<i4'), ('b', [('ba', '<f8'), ('bb', '<i4')])])
+ >>> flatten_descr(ndtype)
+ (('a', dtype('int32')), ('ba', dtype('float64')), ('bb', dtype('int32')))
+
+ """
+ names = ndtype.names
+ if names is None:
+ return ndtype.descr
+ else:
+ descr = []
+ for field in names:
+ (typ, _) = ndtype.fields[field]
+ if typ.names:
+ descr.extend(flatten_descr(typ))
+ else:
+ descr.append((field, typ))
+ return tuple(descr)
+
+
+def zip_descr(seqarrays, flatten=False):
+ """
+ Combine the dtype description of a series of arrays.
+
+ Parameters
+ ----------
+ seqarrays : sequence of arrays
+ Sequence of arrays
+ flatten : {boolean}, optional
+ Whether to collapse nested descriptions.
+ """
+ newdtype = []
+ if flatten:
+ for a in seqarrays:
+ newdtype.extend(flatten_descr(a.dtype))
+ else:
+ for a in seqarrays:
+ current = a.dtype
+ names = current.names or ()
+ if len(names) > 1:
+ newdtype.append(('', current.descr))
+ else:
+ newdtype.extend(current.descr)
+ return np.dtype(newdtype).descr
+
+
+def get_fieldstructure(adtype, lastname=None, parents=None,):
+ """
+ Returns a dictionary with fields as keys and a list of parent fields as values.
+
+ This function is used to simplify access to fields nested in other fields.
+
+ Parameters
+ ----------
+ adtype : np.dtype
+ Input datatype
+ lastname : optional
+ Last processed field name (used internally during recursion).
+ parents : dictionary
+ Dictionary of parent fields (used interbally during recursion).
+
+ Examples
+ --------
+ >>> ndtype = np.dtype([('A', int),
+ ... ('B', [('BA', int),
+ ... ('BB', [('BBA', int), ('BBB', int)])])])
+ >>> get_fieldstructure(ndtype)
+ {'A': [], 'B': [], 'BA': ['B'], 'BB': ['B'],
+ 'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
+
+ """
+ if parents is None:
+ parents = {}
+ names = adtype.names
+ for name in names:
+ current = adtype[name]
+ if current.names:
+ if lastname:
+ parents[name] = [lastname,]
+ else:
+ parents[name] = []
+ parents.update(get_fieldstructure(current, name, parents))
+ else:
+ lastparent = [_ for _ in (parents.get(lastname, []) or [])]
+ if lastparent:
+# if (lastparent[-1] != lastname):
+ lastparent.append(lastname)
+ elif lastname:
+ lastparent = [lastname,]
+ parents[name] = lastparent or []
+ return parents or None
+
+
+def _izip_fields_flat(iterable):
+ """
+ Returns an iterator of concatenated fields from a sequence of arrays,
+ collapsing any nested structure.
+ """
+ for element in iterable:
+ if isinstance(element, np.void):
+ for f in _izip_fields_flat(tuple(element)):
+ yield f
+ else:
+ yield element
+
+
+def _izip_fields(iterable):
+ """
+ Returns an iterator of concatenated fields from a sequence of arrays.
+ """
+ for element in iterable:
+ if hasattr(element, '__iter__') and not isinstance(element, basestring):
+ for f in _izip_fields(element):
+ yield f
+ elif isinstance(element, np.void) and len(tuple(element)) == 1:
+ for f in _izip_fields(element):
+ yield f
+ else:
+ yield element
+
+
+def izip_records(seqarrays, fill_value=None, flatten=True):
+ """
+ Returns an iterator of concatenated items from a sequence of arrays.
+
+ Parameters
+ ----------
+ seqarray : sequence of arrays
+ Sequence of arrays.
+ fill_value : {None, integer}
+ Value used to pad shorter iterables.
+ flatten : {True, False},
+ Whether to
+ """
+ # OK, that's a complete ripoff from Python2.6 itertools.izip_longest
+ def sentinel(counter = ([fill_value]*(len(seqarrays)-1)).pop):
+ "Yields the fill_value or raises IndexError"
+ yield counter()
+ #
+ fillers = iterrepeat(fill_value)
+ iters = [iterchain(it, sentinel(), fillers) for it in seqarrays]
+ # Should we flatten the items, or just use a nested approach
+ if flatten:
+ zipfunc = _izip_fields_flat
+ else:
+ zipfunc = _izip_fields
+ #
+ try:
+ for tup in iterizip(*iters):
+ yield tuple(zipfunc(tup))
+ except IndexError:
+ pass
+
+
+def _fix_output(output, usemask=True, asrecarray=False):
+ """
+ Private function: return a recarray, a ndarray, a MaskedArray
+ or a MaskedRecords depending on the input parameters
+ """
+ if not isinstance(output, MaskedArray):
+ usemask = False
+ if usemask:
+ if asrecarray:
+ output = output.view(MaskedRecords)
+ else:
+ output = ma.filled(output)
+ if asrecarray:
+ output = output.view(recarray)
+ return output
+
+
+def _fix_defaults(output, defaults=None):
+ """
+ Update the fill_value and masked data of `output`
+ from the default given in a dictionary defaults.
+ """
+ names = output.dtype.names
+ (data, mask, fill_value) = (output.data, output.mask, output.fill_value)
+ for (k, v) in (defaults or {}).iteritems():
+ if k in names:
+ fill_value[k] = v
+ data[k][mask[k]] = v
+ return output
+
+
+def merge_arrays(seqarrays,
+ fill_value=-1, flatten=False, usemask=True, asrecarray=False):
+ """
+ Merge arrays field by field.
+
+ Parameters
+ ----------
+ seqarrays : sequence of ndarrays
+ Sequence of arrays
+ fill_value : {float}, optional
+ Filling value used to pad missing data on the shorter arrays.
+ flatten : {False, True}, optional
+ Whether to collapse nested fields.
+ usemask : {False, True}, optional
+ Whether to return a masked array or not.
+ asrecarray : {False, True}, optional
+ Whether to return a recarray (MaskedRecords) or not.
+
+ Examples
+ --------
+ >>> merge_arrays((np.array([1, 2]), np.array([10., 20., 30.])))
+ masked_array(data = [(1, 10.0) (2, 20.0) (--, 30.0)],
+ mask = [(False, False) (False, False) (True, False)],
+ fill_value=(999999, 1e+20)
+ dtype=[('f0', '<i4'), ('f1', '<f8')])
+ >>> merge_arrays((np.array([1, 2]), np.array([10., 20., 30.])),
+ ... usemask=False)
+ array(data = [(1, 10.0) (2, 20.0) (-1, 30.0)],
+ dtype=[('f0', '<i4'), ('f1', '<f8')])
+ >>> merge_arrays((np.array([1, 2]).view([('a', int)]),
+ np.array([10., 20., 30.])),
+ usemask=False, asrecarray=True)
+ rec.array(data = [(1, 10.0) (2, 20.0) (-1, 30.0)],
+ dtype=[('a', int), ('f1', '<f8')])
+ """
+ if (len(seqarrays) == 1):
+ seqarrays = seqarrays[0]
+ if isinstance(seqarrays, ndarray):
+ seqdtype = seqarrays.dtype
+ if (not flatten) or \
+ (zip_descr((seqarrays,), flatten=True) == seqdtype.descr):
+ seqarrays = seqarrays.ravel()
+ if not seqdtype.names:
+ seqarrays = seqarrays.view([('', seqdtype)])
+ if usemask:
+ if asrecarray:
+ return seqarrays.view(MaskedRecords)
+ return seqarrays.view(MaskedArray)
+ elif asrecarray:
+ return seqarrays.view(recarray)
+ return seqarrays
+ else:
+ seqarrays = (seqarrays,)
+ # Get the dtype
+ newdtype = zip_descr(seqarrays, flatten=flatten)
+ # Get the data and the fill_value from each array
+ seqdata = [ma.getdata(a.ravel()) for a in seqarrays]
+ seqmask = [ma.getmaskarray(a).ravel() for a in seqarrays]
+ fill_value = [_check_fill_value(fill_value, a.dtype) for a in seqdata]
+ # Make an iterator from each array, padding w/ fill_values
+ maxlength = max(len(a) for a in seqarrays)
+ for (i, (a, m, fval)) in enumerate(zip(seqdata, seqmask, fill_value)):
+ # Flatten the fill_values if there's only one field
+ if isinstance(fval, (ndarray, np.void)):
+ fmsk = ma.ones((1,), m.dtype)[0]
+ if len(fval.dtype) == 1:
+ fval = fval.item()[0]
+ fmsk = True
+ else:
+ # fval and fmsk should be np.void objects
+ fval = np.array([fval,], dtype=a.dtype)[0]
+# fmsk = np.array([fmsk,], dtype=m.dtype)[0]
+ else:
+ fmsk = True
+ nbmissing = (maxlength-len(a))
+ seqdata[i] = iterchain(a, [fval]*nbmissing)
+ seqmask[i] = iterchain(m, [fmsk]*nbmissing)
+ #
+ data = izip_records(seqdata, flatten=flatten)
+ data = tuple(data)
+ if usemask:
+ mask = izip_records(seqmask, fill_value=True, flatten=flatten)
+ mask = tuple(mask)
+ output = ma.array(np.fromiter(data, dtype=newdtype))
+ output._mask[:] = list(mask)
+ if asrecarray:
+ output = output.view(MaskedRecords)
+ else:
+ output = np.fromiter(data, dtype=newdtype)
+ if asrecarray:
+ output = output.view(recarray)
+ return output
+
+
+
+def drop_fields(base, drop_names, usemask=True, asrecarray=False):
+ """
+ Return a new array with fields in `drop_names` dropped.
+
+ Nested fields are supported.
+
+ Parameters
+ ----------
+ base : array
+ Input array
+ drop_names : string or sequence
+ String or sequence of strings corresponding to the names of the fields
+ to drop.
+ usemask : {False, True}, optional
+ Whether to return a masked array or not.
+ asrecarray : string or sequence
+ Whether to return a recarray or a mrecarray (`asrecarray=True`) or
+ a plain ndarray or masked array with flexible dtype (`asrecarray=False`)
+
+ Examples
+ --------
+ >>> a = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ >>> drop_fields(a, 'a')
+ array([((2.0, 3),), ((5.0, 6),)],
+ dtype=[('b', [('ba', '<f8'), ('bb', '<i4')])])
+ >>> drop_fields(a, 'ba')
+ array([(1, (3,)), (4, (6,))],
+ dtype=[('a', '<i4'), ('b', [('bb', '<i4')])])
+ >>> drop_fields(a, ['ba', 'bb'])
+ array([(1,), (4,)],
+ dtype=[('a', '<i4')])
+ """
+ if _is_string_like(drop_names):
+ drop_names = [drop_names,]
+ else:
+ drop_names = set(drop_names)
+ #
+ def _drop_descr(ndtype, drop_names):
+ names = ndtype.names
+ newdtype = []
+ for name in names:
+ current = ndtype[name]
+ if name in drop_names:
+ continue
+ if current.names:
+ descr = _drop_descr(current, drop_names)
+ if descr:
+ newdtype.append((name, descr))
+ else:
+ newdtype.append((name, current))
+ return newdtype
+ #
+ newdtype = _drop_descr(base.dtype, drop_names)
+ if not newdtype:
+ return None
+ #
+ output = np.empty(base.shape, dtype=newdtype)
+ output = recursive_fill_fields(base, output)
+ return _fix_output(output, usemask=usemask, asrecarray=asrecarray)
+
+
+def rec_drop_fields(base, drop_names):
+ """
+ Returns a new numpy.recarray with fields in `drop_names` dropped.
+ """
+ return drop_fields(base, drop_names, usemask=False, asrecarray=True)
+
+
+
+def rename_fields(base, namemapper):
+ """
+ Rename the fields from a flexible-datatype ndarray or recarray.
+
+ Nested fields are supported.
+
+ Parameters
+ ----------
+ base : ndarray
+ Input array whose fields must be modified.
+ namemapper : dictionary
+ Dictionary mapping old field names to their new version.
+
+ Examples
+ --------
+ >>> a = np.array([(1, (2, [3.0, 30.])), (4, (5, [6.0, 60.]))],
+ dtype=[('a', int),
+ ('b', [('ba', float), ('bb', (float, 2))])])
+ >>> rename_fields(a, {'a':'A', 'bb':'BB'})
+ array([(1, (2.0, 3)), (4, (5.0, 6))],
+ dtype=[('A', '<i4'), ('b', [('ba', '<f8'), ('BB', '<i4')])])
+
+ """
+ def _recursive_rename_fields(ndtype, namemapper):
+ newdtype = []
+ for name in ndtype.names:
+ newname = namemapper.get(name, name)
+ current = ndtype[name]
+ if current.names:
+ newdtype.append((newname,
+ _recursive_rename_fields(current, namemapper)))
+ else:
+ newdtype.append((newname, current))
+ return newdtype
+ newdtype = _recursive_rename_fields(base.dtype, namemapper)
+ return base.view(newdtype)
+
+
+def append_fields(base, names, data=None, dtypes=None,
+ fill_value=-1, usemask=True, asrecarray=False):
+ """
+ Add new fields to an existing array.
+
+ The names of the fields are given with the `names` arguments,
+ the corresponding values with the `data` arguments.
+ If a single field is appended, `names`, `data` and `dtypes` do not have
+ to be lists but just values.
+
+ Parameters
+ ----------
+ base : array
+ Input array to extend.
+ names : string, sequence
+ String or sequence of strings corresponding to the names
+ of the new fields.
+ data : array or sequence of arrays
+ Array or sequence of arrays storing the fields to add to the base.
+ dtypes : sequence of datatypes
+ Datatype or sequence of datatypes.
+ If None, the datatypes are estimated from the `data`.
+ fill_value : {float}, optional
+ Filling value used to pad missing data on the shorter arrays.
+ usemask : {False, True}, optional
+ Whether to return a masked array or not.
+ asrecarray : {False, True}, optional
+ Whether to return a recarray (MaskedRecords) or not.
+
+ """
+ # Check the names
+ if isinstance(names, (tuple, list)):
+ if len(names) != len(data):
+ err_msg = "The number of arrays does not match the number of names"
+ raise ValueError(err_msg)
+ elif isinstance(names, basestring):
+ names = [names,]
+ data = [data,]
+ #
+ if dtypes is None:
+ data = [np.array(a, copy=False, subok=True) for a in data]
+ data = [a.view([(name, a.dtype)]) for (name, a) in zip(names, data)]
+ elif not hasattr(dtypes, '__iter__'):
+ dtypes = [dtypes,]
+ if len(data) != len(dtypes):
+ if len(dtypes) == 1:
+ dtypes = dtypes * len(data)
+ else:
+ msg = "The dtypes argument must be None, "\
+ "a single dtype or a list."
+ raise ValueError(msg)
+ data = [np.array(a, copy=False, subok=True, dtype=d).view([(n, d)])
+ for (a, n, d) in zip(data, names, dtypes)]
+ #
+ base = merge_arrays(base, usemask=usemask, fill_value=fill_value)
+ if len(data) > 1:
+ data = merge_arrays(data, flatten=True, usemask=usemask,
+ fill_value=fill_value)
+ else:
+ data = data.pop()
+ #
+ output = ma.masked_all(max(len(base), len(data)),
+ dtype=base.dtype.descr + data.dtype.descr)
+ output = recursive_fill_fields(base, output)
+ output = recursive_fill_fields(data, output)
+ #
+ return _fix_output(output, usemask=usemask, asrecarray=asrecarray)
+
+
+
+def rec_append_fields(base, names, data, dtypes=None):
+ """
+ Add new fields to an existing array.
+
+ The names of the fields are given with the `names` arguments,
+ the corresponding values with the `data` arguments.
+ If a single field is appended, `names`, `data` and `dtypes` do not have
+ to be lists but just values.
+
+ Parameters
+ ----------
+ base : array
+ Input array to extend.
+ names : string, sequence
+ String or sequence of strings corresponding to the names
+ of the new fields.
+ data : array or sequence of arrays
+ Array or sequence of arrays storing the fields to add to the base.
+ dtypes : sequence of datatypes, optional
+ Datatype or sequence of datatypes.
+ If None, the datatypes are estimated from the `data`.
+
+ See Also
+ --------
+ append_fields
+
+ Returns
+ -------
+ appended_array : np.recarray
+ """
+ return append_fields(base, names, data=data, dtypes=dtypes,
+ asrecarray=True, usemask=False)
+
+
+
+def stack_arrays(arrays, defaults=None, usemask=True, asrecarray=False,
+ autoconvert=False):
+ """
+ Superposes arrays fields by fields
+
+ Parameters
+ ----------
+ seqarrays : array or sequence
+ Sequence of input arrays.
+ defaults : dictionary, optional
+ Dictionary mapping field names to the corresponding default values.
+ usemask : {True, False}, optional
+ Whether to return a MaskedArray (or MaskedRecords is `asrecarray==True`)
+ or a ndarray.
+ asrecarray : {False, True}, optional
+ Whether to return a recarray (or MaskedRecords if `usemask==True`) or
+ just a flexible-type ndarray.
+ autoconvert : {False, True}, optional
+ Whether automatically cast the type of the field to the maximum.
+
+ Examples
+ --------
+ >>> x = np.array([1, 2,])
+ >>> stack_arrays(x) is x
+ True
+ >>> z = np.array([('A', 1), ('B', 2)], dtype=[('A', '|S3'), ('B', float)])
+ >>> zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
+ dtype=[('A', '|S3'), ('B', float), ('C', float)])
+ >>> test = stack_arrays((z,zz))
+ >>> masked_array(data = [('A', 1.0, --) ('B', 2.0, --) ('a', 10.0, 100.0)
+ ... ('b', 20.0, 200.0) ('c', 30.0, 300.0)],
+ ... mask = [(False, False, True) (False, False, True) (False, False, False)
+ ... (False, False, False) (False, False, False)],
+ ... fill_value=('N/A', 1e+20, 1e+20)
+ ... dtype=[('A', '|S3'), ('B', '<f8'), ('C', '<f8')])
+
+ """
+ if isinstance(arrays, ndarray):
+ return arrays
+ elif len(arrays) == 1:
+ return arrays[0]
+ seqarrays = [np.asanyarray(a).ravel() for a in arrays]
+ nrecords = [len(a) for a in seqarrays]
+ ndtype = [a.dtype for a in seqarrays]
+ fldnames = [d.names for d in ndtype]
+ #
+ dtype_l = ndtype[0]
+ newdescr = dtype_l.descr
+ names = [_[0] for _ in newdescr]
+ for dtype_n in ndtype[1:]:
+ for descr in dtype_n.descr:
+ name = descr[0] or ''
+ if name not in names:
+ newdescr.append(descr)
+ names.append(name)
+ else:
+ nameidx = names.index(name)
+ current_descr = newdescr[nameidx]
+ if autoconvert:
+ if np.dtype(descr[1]) > np.dtype(current_descr[-1]):
+ current_descr = list(current_descr)
+ current_descr[-1] = descr[1]
+ newdescr[nameidx] = tuple(current_descr)
+ elif descr[1] != current_descr[-1]:
+ raise TypeError("Incompatible type '%s' <> '%s'" %\
+ (dict(newdescr)[name], descr[1]))
+ # Only one field: use concatenate
+ if len(newdescr) == 1:
+ output = ma.concatenate(seqarrays)
+ else:
+ #
+ output = ma.masked_all((np.sum(nrecords),), newdescr)
+ offset = np.cumsum(np.r_[0, nrecords])
+ seen = []
+ for (a, n, i, j) in zip(seqarrays, fldnames, offset[:-1], offset[1:]):
+ names = a.dtype.names
+ if names is None:
+ output['f%i' % len(seen)][i:j] = a
+ else:
+ for name in n:
+ output[name][i:j] = a[name]
+ if name not in seen:
+ seen.append(name)
+ #
+ return _fix_output(_fix_defaults(output, defaults),
+ usemask=usemask, asrecarray=asrecarray)
+
+
+
+def find_duplicates(a, key=None, ignoremask=True, return_index=False):
+ """
+ Find the duplicates in a structured array along a given key
+
+ Parameters
+ ----------
+ a : array-like
+ Input array
+ key : {string, None}, optional
+ Name of the fields along which to check the duplicates.
+ If None, the search is performed by records
+ ignoremask : {True, False}, optional
+ Whether masked data should be discarded or considered as duplicates.
+ return_index : {False, True}, optional
+ Whether to return the indices of the duplicated values.
+
+ Examples
+ --------
+ >>> ndtype = [('a', int)]
+ >>> a = ma.array([1, 1, 1, 2, 2, 3, 3],
+ ... mask=[0, 0, 1, 0, 0, 0, 1]).view(ndtype)
+ >>> find_duplicates(a, ignoremask=True, return_index=True)
+ """
+ a = np.asanyarray(a).ravel()
+ # Get a dictionary of fields
+ fields = get_fieldstructure(a.dtype)
+ # Get the sorting data (by selecting the corresponding field)
+ base = a
+ if key:
+ for f in fields[key]:
+ base = base[f]
+ base = base[key]
+ # Get the sorting indices and the sorted data
+ sortidx = base.argsort()
+ sortedbase = base[sortidx]
+ sorteddata = sortedbase.filled()
+ # Compare the sorting data
+ flag = (sorteddata[:-1] == sorteddata[1:])
+ # If masked data must be ignored, set the flag to false where needed
+ if ignoremask:
+ sortedmask = sortedbase.recordmask
+ flag[sortedmask[1:]] = False
+ flag = np.concatenate(([False], flag))
+ # We need to take the point on the left as well (else we're missing it)
+ flag[:-1] = flag[:-1] + flag[1:]
+ duplicates = a[sortidx][flag]
+ if return_index:
+ return (duplicates, sortidx[flag])
+ else:
+ return duplicates
+
+
+
+def join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
+ defaults=None, usemask=True, asrecarray=False):
+ """
+ Join arrays `r1` and `r2` on key `key`.
+
+ The key should be either a string or a sequence of string corresponding
+ to the fields used to join the array.
+ An exception is raised if the `key` field cannot be found in the two input
+ arrays.
+ Neither `r1` nor `r2` should have any duplicates along `key`: the presence
+ of duplicates will make the output quite unreliable. Note that duplicates
+ are not looked for by the algorithm.
+
+ Parameters
+ ----------
+ key : {string, sequence}
+ A string or a sequence of strings corresponding to the fields used
+ for comparison.
+ r1, r2 : arrays
+ Structured arrays.
+ jointype : {'inner', 'outer', 'leftouter'}, optional
+ If 'inner', returns the elements common to both r1 and r2.
+ If 'outer', returns the common elements as well as the elements of r1
+ not in r2 and the elements of not in r2.
+ If 'leftouter', returns the common elements and the elements of r1 not
+ in r2.
+ r1postfix : string, optional
+ String appended to the names of the fields of r1 that are present in r2
+ but absent of the key.
+ r2postfix : string, optional
+ String appended to the names of the fields of r2 that are present in r1
+ but absent of the key.
+ defaults : {dictionary}, optional
+ Dictionary mapping field names to the corresponding default values.
+ usemask : {True, False}, optional
+ Whether to return a MaskedArray (or MaskedRecords is `asrecarray==True`)
+ or a ndarray.
+ asrecarray : {False, True}, optional
+ Whether to return a recarray (or MaskedRecords if `usemask==True`) or
+ just a flexible-type ndarray.
+
+ Notes
+ -----
+ * The output is sorted along the key.
+ * A temporary array is formed by dropping the fields not in the key for the
+ two arrays and concatenating the result. This array is then sorted, and
+ the common entries selected. The output is constructed by filling the fields
+ with the selected entries. Matching is not preserved if there are some
+ duplicates...
+
+ """
+ # Check jointype
+ if jointype not in ('inner', 'outer', 'leftouter'):
+ raise ValueError("The 'jointype' argument should be in 'inner', "\
+ "'outer' or 'leftouter' (got '%s' instead)" % jointype)
+ # If we have a single key, put it in a tuple
+ if isinstance(key, basestring):
+ key = (key, )
+
+ # Check the keys
+ for name in key:
+ if name not in r1.dtype.names:
+ raise ValueError('r1 does not have key field %s'%name)
+ if name not in r2.dtype.names:
+ raise ValueError('r2 does not have key field %s'%name)
+
+ # Make sure we work with ravelled arrays
+ r1 = r1.ravel()
+ r2 = r2.ravel()
+ (nb1, nb2) = (len(r1), len(r2))
+ (r1names, r2names) = (r1.dtype.names, r2.dtype.names)
+
+ # Make temporary arrays of just the keys
+ r1k = drop_fields(r1, [n for n in r1names if n not in key])
+ r2k = drop_fields(r2, [n for n in r2names if n not in key])
+
+ # Concatenate the two arrays for comparison
+ aux = ma.concatenate((r1k, r2k))
+ idx_sort = aux.argsort(order=key)
+ aux = aux[idx_sort]
+ #
+ # Get the common keys
+ flag_in = ma.concatenate(([False], aux[1:] == aux[:-1]))
+ flag_in[:-1] = flag_in[1:] + flag_in[:-1]
+ idx_in = idx_sort[flag_in]
+ idx_1 = idx_in[(idx_in < nb1)]
+ idx_2 = idx_in[(idx_in >= nb1)] - nb1
+ (r1cmn, r2cmn) = (len(idx_1), len(idx_2))
+ if jointype == 'inner':
+ (r1spc, r2spc) = (0, 0)
+ elif jointype == 'outer':
+ idx_out = idx_sort[~flag_in]
+ idx_1 = np.concatenate((idx_1, idx_out[(idx_out < nb1)]))
+ idx_2 = np.concatenate((idx_2, idx_out[(idx_out >= nb1)] - nb1))
+ (r1spc, r2spc) = (len(idx_1) - r1cmn, len(idx_2) - r2cmn)
+ elif jointype == 'leftouter':
+ idx_out = idx_sort[~flag_in]
+ idx_1 = np.concatenate((idx_1, idx_out[(idx_out < nb1)]))
+ (r1spc, r2spc) = (len(idx_1) - r1cmn, 0)
+ # Select the entries from each input
+ (s1, s2) = (r1[idx_1], r2[idx_2])
+ #
+ # Build the new description of the output array .......
+ # Start with the key fields
+ ndtype = [list(_) for _ in r1k.dtype.descr]
+ # Add the other fields
+ ndtype.extend(list(_) for _ in r1.dtype.descr if _[0] not in key)
+ # Find the new list of names (it may be different from r1names)
+ names = list(_[0] for _ in ndtype)
+ for desc in r2.dtype.descr:
+ desc = list(desc)
+ name = desc[0]
+ # Have we seen the current name already ?
+ if name in names:
+ nameidx = names.index(name)
+ current = ndtype[nameidx]
+ # The current field is part of the key: take the largest dtype
+ if name in key:
+ current[-1] = max(desc[1], current[-1])
+ # The current field is not part of the key: add the suffixes
+ else:
+ current[0] += r1postfix
+ desc[0] += r2postfix
+ ndtype.insert(nameidx+1, desc)
+ #... we haven't: just add the description to the current list
+ else:
+ names.extend(desc[0])
+ ndtype.append(desc)
+ # Revert the elements to tuples
+ ndtype = [tuple(_) for _ in ndtype]
+ # Find the largest nb of common fields : r1cmn and r2cmn should be equal, but...
+ cmn = max(r1cmn, r2cmn)
+ # Construct an empty array
+ output = ma.masked_all((cmn + r1spc + r2spc,), dtype=ndtype)
+ names = output.dtype.names
+ for f in r1names:
+ selected = s1[f]
+ if f not in names:
+ f += r1postfix
+ current = output[f]
+ current[:r1cmn] = selected[:r1cmn]
+ if jointype in ('outer', 'leftouter'):
+ current[cmn:cmn+r1spc] = selected[r1cmn:]
+ for f in r2names:
+ selected = s2[f]
+ if f not in names:
+ f += r2postfix
+ current = output[f]
+ current[:r2cmn] = selected[:r2cmn]
+ if (jointype == 'outer') and r2spc:
+ current[-r2spc:] = selected[r2cmn:]
+ # Sort and finalize the output
+ output.sort(order=key)
+ kwargs = dict(usemask=usemask, asrecarray=asrecarray)
+ return _fix_output(_fix_defaults(output, defaults), **kwargs)
+
+
+def rec_join(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
+ defaults=None):
+ """
+ Join arrays `r1` and `r2` on keys.
+ Alternative to join_by, that always returns a np.recarray.
+
+ See Also
+ --------
+ join_by : equivalent function
+ """
+ kwargs = dict(jointype=jointype, r1postfix=r1postfix, r2postfix=r2postfix,
+ defaults=defaults, usemask=False, asrecarray=True)
+ return join_by(key, r1, r2, **kwargs)
diff --git a/numpy/lib/src/_compiled_base.c b/numpy/lib/src/_compiled_base.c
index ddab9f851..54955e60a 100644
--- a/numpy/lib/src/_compiled_base.c
+++ b/numpy/lib/src/_compiled_base.c
@@ -494,34 +494,45 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
#define _TESTDOC1(typebase) (obj->ob_type == &Py##typebase##_Type)
#define _TESTDOC2(typebase) (obj->ob_type == Py##typebase##_TypePtr)
-#define _ADDDOC(typebase, doc, name) { \
+#define _ADDDOC(typebase, doc, name) do { \
Py##typebase##Object *new = (Py##typebase##Object *)obj; \
if (!(doc)) { \
doc = docstr; \
} \
else { \
- PyErr_Format(PyExc_RuntimeError, \
- "%s method %s",name, msg); \
+ PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \
return NULL; \
} \
- }
+ } while (0)
+
+ if (_TESTDOC1(CFunction))
+ _ADDDOC(CFunction, new->m_ml->ml_doc, new->m_ml->ml_name);
+ else if (_TESTDOC1(Type))
+ _ADDDOC(Type, new->tp_doc, new->tp_name);
+ else if (_TESTDOC2(MemberDescr))
+ _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name);
+ else if (_TESTDOC2(GetSetDescr))
+ _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name);
+ else if (_TESTDOC2(MethodDescr))
+ _ADDDOC(MethodDescr, new->d_method->ml_doc, new->d_method->ml_name);
+ else {
+ PyObject *doc_attr;
+
+ doc_attr = PyObject_GetAttrString(obj, "__doc__");
+ if (doc_attr != NULL && doc_attr != Py_None) {
+ PyErr_Format(PyExc_RuntimeError, "object %s", msg);
+ return NULL;
+ }
+ Py_XDECREF(doc_attr);
- if _TESTDOC1(CFunction)
- _ADDDOC(CFunction, new->m_ml->ml_doc, new->m_ml->ml_name)
- else if _TESTDOC1(Type)
- _ADDDOC(Type, new->tp_doc, new->tp_name)
- else if _TESTDOC2(MemberDescr)
- _ADDDOC(MemberDescr, new->d_member->doc, new->d_member->name)
- else if _TESTDOC2(GetSetDescr)
- _ADDDOC(GetSetDescr, new->d_getset->doc, new->d_getset->name)
- else if _TESTDOC2(MethodDescr)
- _ADDDOC(MethodDescr, new->d_method->ml_doc,
- new->d_method->ml_name)
- else {
- PyErr_SetString(PyExc_TypeError,
- "Cannot set a docstring for that object");
- return NULL;
- }
+ if (PyObject_SetAttrString(obj, "__doc__", str) < 0) {
+ PyErr_SetString(PyExc_TypeError,
+ "Cannot set a docstring for that object");
+ return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
#undef _TESTDOC1
#undef _TESTDOC2
@@ -533,35 +544,6 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
}
-static char packbits_doc[] =
- "out = numpy.packbits(myarray, axis=None)\n\n"
- " myarray : an integer type array whose elements should be packed to bits\n\n"
- " This routine packs the elements of a binary-valued dataset into a\n"
- " NumPy array of type uint8 ('B') whose bits correspond to\n"
- " the logical (0 or nonzero) value of the input elements.\n"
- " The dimension over-which bit-packing is done is given by axis.\n"
- " The shape of the output has the same number of dimensions as the input\n"
- " (unless axis is None, in which case the output is 1-d).\n"
- "\n"
- " Example:\n"
- " >>> a = array([[[1,0,1],\n"
- " ... [0,1,0]],\n"
- " ... [[1,1,0],\n"
- " ... [0,0,1]]])\n"
- " >>> b = numpy.packbits(a,axis=-1)\n"
- " >>> b\n"
- " array([[[160],[64]],[[192],[32]]], dtype=uint8)\n\n"
- " Note that 160 = 128 + 32\n"
- " 192 = 128 + 64\n";
-
-static char unpackbits_doc[] =
- "out = numpy.unpackbits(myarray, axis=None)\n\n"
- " myarray - array of uint8 type where each element represents a bit-field\n"
- " that should be unpacked into a boolean output array\n\n"
- " The shape of the output array is either 1-d (if axis is None) or\n"
- " the same shape as the input array with unpacking done along the\n"
- " axis specified.";
-
/* PACKBITS
This function packs binary (0 or 1) 1-bit per pixel arrays
@@ -809,9 +791,9 @@ static struct PyMethodDef methods[] = {
{"add_docstring", (PyCFunction)arr_add_docstring, METH_VARARGS,
NULL},
{"packbits", (PyCFunction)io_pack, METH_VARARGS | METH_KEYWORDS,
- packbits_doc},
+ NULL},
{"unpackbits", (PyCFunction)io_unpack, METH_VARARGS | METH_KEYWORDS,
- unpackbits_doc},
+ NULL},
{NULL, NULL} /* sentinel */
};
diff --git a/numpy/lib/tests/test__iotools.py b/numpy/lib/tests/test__iotools.py
new file mode 100644
index 000000000..2cb8461c3
--- /dev/null
+++ b/numpy/lib/tests/test__iotools.py
@@ -0,0 +1,167 @@
+
+import StringIO
+
+import numpy as np
+from numpy.lib._iotools import LineSplitter, NameValidator, StringConverter,\
+ has_nested_fields
+from numpy.testing import *
+
+class TestLineSplitter(TestCase):
+ "Tests the LineSplitter class."
+ #
+ def test_no_delimiter(self):
+ "Test LineSplitter w/o delimiter"
+ strg = " 1 2 3 4 5 # test"
+ test = LineSplitter()(strg)
+ assert_equal(test, ['1', '2', '3', '4', '5'])
+ test = LineSplitter('')(strg)
+ assert_equal(test, ['1', '2', '3', '4', '5'])
+
+ def test_space_delimiter(self):
+ "Test space delimiter"
+ strg = " 1 2 3 4 5 # test"
+ test = LineSplitter(' ')(strg)
+ assert_equal(test, ['1', '2', '3', '4', '', '5'])
+ test = LineSplitter(' ')(strg)
+ assert_equal(test, ['1 2 3 4', '5'])
+
+ def test_tab_delimiter(self):
+ "Test tab delimiter"
+ strg= " 1\t 2\t 3\t 4\t 5 6"
+ test = LineSplitter('\t')(strg)
+ assert_equal(test, ['1', '2', '3', '4', '5 6'])
+ strg= " 1 2\t 3 4\t 5 6"
+ test = LineSplitter('\t')(strg)
+ assert_equal(test, ['1 2', '3 4', '5 6'])
+
+ def test_other_delimiter(self):
+ "Test LineSplitter on delimiter"
+ strg = "1,2,3,4,,5"
+ test = LineSplitter(',')(strg)
+ assert_equal(test, ['1', '2', '3', '4', '', '5'])
+ #
+ strg = " 1,2,3,4,,5 # test"
+ test = LineSplitter(',')(strg)
+ assert_equal(test, ['1', '2', '3', '4', '', '5'])
+
+ def test_constant_fixed_width(self):
+ "Test LineSplitter w/ fixed-width fields"
+ strg = " 1 2 3 4 5 # test"
+ test = LineSplitter(3)(strg)
+ assert_equal(test, ['1', '2', '3', '4', '', '5', ''])
+ #
+ strg = " 1 3 4 5 6# test"
+ test = LineSplitter(20)(strg)
+ assert_equal(test, ['1 3 4 5 6'])
+ #
+ strg = " 1 3 4 5 6# test"
+ test = LineSplitter(30)(strg)
+ assert_equal(test, ['1 3 4 5 6'])
+
+ def test_variable_fixed_width(self):
+ strg = " 1 3 4 5 6# test"
+ test = LineSplitter((3,6,6,3))(strg)
+ assert_equal(test, ['1', '3', '4 5', '6'])
+ #
+ strg = " 1 3 4 5 6# test"
+ test = LineSplitter((6,6,9))(strg)
+ assert_equal(test, ['1', '3 4', '5 6'])
+
+
+#-------------------------------------------------------------------------------
+
+class TestNameValidator(TestCase):
+ #
+ def test_case_sensitivity(self):
+ "Test case sensitivity"
+ names = ['A', 'a', 'b', 'c']
+ test = NameValidator().validate(names)
+ assert_equal(test, ['A', 'a', 'b', 'c'])
+ test = NameValidator(case_sensitive=False).validate(names)
+ assert_equal(test, ['A', 'A_1', 'B', 'C'])
+ test = NameValidator(case_sensitive='upper').validate(names)
+ assert_equal(test, ['A', 'A_1', 'B', 'C'])
+ test = NameValidator(case_sensitive='lower').validate(names)
+ assert_equal(test, ['a', 'a_1', 'b', 'c'])
+ #
+ def test_excludelist(self):
+ "Test excludelist"
+ names = ['dates', 'data', 'Other Data', 'mask']
+ validator = NameValidator(excludelist = ['dates', 'data', 'mask'])
+ test = validator.validate(names)
+ assert_equal(test, ['dates_', 'data_', 'Other_Data', 'mask_'])
+
+
+#-------------------------------------------------------------------------------
+
+class TestStringConverter(TestCase):
+ "Test StringConverter"
+ #
+ def test_creation(self):
+ "Test creation of a StringConverter"
+ converter = StringConverter(int, -99999)
+ assert_equal(converter._status, 1)
+ assert_equal(converter.default, -99999)
+ #
+ def test_upgrade(self):
+ "Tests the upgrade method."
+ converter = StringConverter()
+ assert_equal(converter._status, 0)
+ converter.upgrade('0')
+ assert_equal(converter._status, 1)
+ converter.upgrade('0.')
+ assert_equal(converter._status, 2)
+ converter.upgrade('0j')
+ assert_equal(converter._status, 3)
+ converter.upgrade('a')
+ assert_equal(converter._status, len(converter._mapper)-1)
+ #
+ def test_missing(self):
+ "Tests the use of missing values."
+ converter = StringConverter(missing_values=('missing','missed'))
+ converter.upgrade('0')
+ assert_equal(converter('0'), 0)
+ assert_equal(converter(''), converter.default)
+ assert_equal(converter('missing'), converter.default)
+ assert_equal(converter('missed'), converter.default)
+ try:
+ converter('miss')
+ except ValueError:
+ pass
+ #
+ def test_upgrademapper(self):
+ "Tests updatemapper"
+ from datetime import date
+ import time
+ dateparser = lambda s : date(*time.strptime(s, "%Y-%m-%d")[:3])
+ StringConverter.upgrade_mapper(dateparser, date(2000,1,1))
+ convert = StringConverter(dateparser, date(2000, 1, 1))
+ test = convert('2001-01-01')
+ assert_equal(test, date(2001, 01, 01))
+ test = convert('2009-01-01')
+ assert_equal(test, date(2009, 01, 01))
+ test = convert('')
+ assert_equal(test, date(2000, 01, 01))
+ #
+ def test_string_to_object(self):
+ "Make sure that string-to-object functions are properly recognized"
+ from datetime import date
+ import time
+ conv = StringConverter(lambda s: date(*(time.strptime(s)[:3])))
+ assert_equal(conv._mapper[-2][0](0), 0j)
+ assert(hasattr(conv, 'default'))
+
+
+#-------------------------------------------------------------------------------
+
+class TestMiscFunctions(TestCase):
+ #
+ def test_has_nested_dtype(self):
+ "Test has_nested_dtype"
+ ndtype = np.dtype(np.float)
+ assert_equal(has_nested_fields(ndtype), False)
+ ndtype = np.dtype([('A', '|S3'), ('B', float)])
+ assert_equal(has_nested_fields(ndtype), False)
+ ndtype = np.dtype([('A', int), ('B', [('BA', float), ('BB', '|S1')])])
+ assert_equal(has_nested_fields(ndtype), True)
+
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index ca8104b53..143e28ae5 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -430,6 +430,44 @@ class TestTrapz(TestCase):
#check integral of normal equals 1
assert_almost_equal(sum(r,axis=0),1,7)
+ def test_ndim(self):
+ x = linspace(0, 1, 3)
+ y = linspace(0, 2, 8)
+ z = linspace(0, 3, 13)
+
+ wx = ones_like(x) * (x[1]-x[0])
+ wx[0] /= 2
+ wx[-1] /= 2
+ wy = ones_like(y) * (y[1]-y[0])
+ wy[0] /= 2
+ wy[-1] /= 2
+ wz = ones_like(z) * (z[1]-z[0])
+ wz[0] /= 2
+ wz[-1] /= 2
+
+ q = x[:,None,None] + y[None,:,None] + z[None,None,:]
+
+ qx = (q*wx[:,None,None]).sum(axis=0)
+ qy = (q*wy[None,:,None]).sum(axis=1)
+ qz = (q*wz[None,None,:]).sum(axis=2)
+
+ # n-d `x`
+ r = trapz(q, x=x[:,None,None], axis=0)
+ assert_almost_equal(r, qx)
+ r = trapz(q, x=y[None,:,None], axis=1)
+ assert_almost_equal(r, qy)
+ r = trapz(q, x=z[None,None,:], axis=2)
+ assert_almost_equal(r, qz)
+
+ # 1-d `x`
+ r = trapz(q, x=x, axis=0)
+ assert_almost_equal(r, qx)
+ r = trapz(q, x=y, axis=1)
+ assert_almost_equal(r, qy)
+ r = trapz(q, x=z, axis=2)
+ assert_almost_equal(r, qz)
+
+
class TestSinc(TestCase):
def test_simple(self):
assert(sinc(0)==1)
diff --git a/numpy/lib/tests/test_getlimits.py b/numpy/lib/tests/test_getlimits.py
index 3fe939b32..325e5a444 100644
--- a/numpy/lib/tests/test_getlimits.py
+++ b/numpy/lib/tests/test_getlimits.py
@@ -51,5 +51,9 @@ class TestIinfo(TestCase):
assert_equal(iinfo(T).max, T(-1))
+def test_instances():
+ iinfo(10)
+ finfo(3.0)
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/lib/tests/test_io.py b/numpy/lib/tests/test_io.py
index 885fd3616..c38d83add 100644
--- a/numpy/lib/tests/test_io.py
+++ b/numpy/lib/tests/test_io.py
@@ -1,10 +1,25 @@
-from numpy.testing import *
+
import numpy as np
+import numpy.ma as ma
+from numpy.ma.testutils import *
+
import StringIO
from tempfile import NamedTemporaryFile
+import sys, time
+from datetime import datetime
+
+
+MAJVER, MINVER = sys.version_info[:2]
-class RoundtripTest:
+def strptime(s, fmt=None):
+ """This function is available in the datetime module only
+ from Python >= 2.5.
+
+ """
+ return datetime(*time.strptime(s, fmt)[:3])
+
+class RoundtripTest(object):
def roundtrip(self, save_func, *args, **kwargs):
"""
save_func : callable
@@ -25,7 +40,14 @@ class RoundtripTest:
file_on_disk = kwargs.get('file_on_disk', False)
if file_on_disk:
- target_file = NamedTemporaryFile()
+ # Do not delete the file on windows, because we can't
+ # reopen an already opened file on that platform, so we
+ # need to close the file and reopen it, implying no
+ # automatic deletion.
+ if sys.platform == 'win32' and MAJVER >= 2 and MINVER >= 6:
+ target_file = NamedTemporaryFile(delete=False)
+ else:
+ target_file = NamedTemporaryFile()
load_file = target_file.name
else:
target_file = StringIO.StringIO()
@@ -37,6 +59,9 @@ class RoundtripTest:
target_file.flush()
target_file.seek(0)
+ if sys.platform == 'win32' and not isinstance(target_file, StringIO.StringIO):
+ target_file.close()
+
arr_reloaded = np.load(load_file, **load_kwds)
self.arr = arr
@@ -59,6 +84,7 @@ class RoundtripTest:
a = np.array([1, 2, 3, 4], int)
self.roundtrip(a)
+ @np.testing.dec.knownfailureif(sys.platform=='win32', "Fail on Win32")
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'})
@@ -95,6 +121,7 @@ class TestSavezLoad(RoundtripTest, TestCase):
class TestSaveTxt(TestCase):
+ @np.testing.dec.knownfailureif(sys.platform=='win32', "Fail on Win32")
def test_array(self):
a =np.array([[1, 2], [3, 4]], float)
c = StringIO.StringIO()
@@ -319,7 +346,6 @@ class Testfromregex(TestCase):
assert_array_equal(x, a)
def test_record_2(self):
- return # pass this test until #736 is resolved
c = StringIO.StringIO()
c.write('1312 foo\n1534 bar\n4444 qux')
c.seek(0)
@@ -341,5 +367,447 @@ class Testfromregex(TestCase):
assert_array_equal(x, a)
+#####--------------------------------------------------------------------------
+
+
+class TestFromTxt(TestCase):
+ #
+ def test_record(self):
+ "Test w/ explicit dtype"
+ data = StringIO.StringIO('1 2\n3 4')
+# data.seek(0)
+ test = np.ndfromtxt(data, dtype=[('x', np.int32), ('y', np.int32)])
+ control = np.array([(1, 2), (3, 4)], dtype=[('x', 'i4'), ('y', 'i4')])
+ assert_equal(test, control)
+ #
+ data = StringIO.StringIO('M 64.0 75.0\nF 25.0 60.0')
+# data.seek(0)
+ descriptor = {'names': ('gender','age','weight'),
+ 'formats': ('S1', 'i4', 'f4')}
+ control = np.array([('M', 64.0, 75.0), ('F', 25.0, 60.0)],
+ dtype=descriptor)
+ test = np.ndfromtxt(data, dtype=descriptor)
+ assert_equal(test, control)
+
+ def test_array(self):
+ "Test outputing a standard ndarray"
+ data = StringIO.StringIO('1 2\n3 4')
+ control = np.array([[1,2],[3,4]], dtype=int)
+ test = np.ndfromtxt(data, dtype=int)
+ assert_array_equal(test, control)
+ #
+ data.seek(0)
+ control = np.array([[1,2],[3,4]], dtype=float)
+ test = np.loadtxt(data, dtype=float)
+ assert_array_equal(test, control)
+
+ def test_1D(self):
+ "Test squeezing to 1D"
+ control = np.array([1, 2, 3, 4], int)
+ #
+ data = StringIO.StringIO('1\n2\n3\n4\n')
+ test = np.ndfromtxt(data, dtype=int)
+ assert_array_equal(test, control)
+ #
+ data = StringIO.StringIO('1,2,3,4\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',')
+ assert_array_equal(test, control)
+
+ def test_comments(self):
+ "Test the stripping of comments"
+ control = np.array([1, 2, 3, 5], int)
+ # Comment on its own line
+ data = StringIO.StringIO('# comment\n1,2,3,5\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',', comments='#')
+ assert_equal(test, control)
+ # Comment at the end of a line
+ data = StringIO.StringIO('1,2,3,5# comment\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',', comments='#')
+ assert_equal(test, control)
+
+ def test_skiprows(self):
+ "Test row skipping"
+ control = np.array([1, 2, 3, 5], int)
+ #
+ data = StringIO.StringIO('comment\n1,2,3,5\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',', skiprows=1)
+ assert_equal(test, control)
+ #
+ data = StringIO.StringIO('# comment\n1,2,3,5\n')
+ test = np.loadtxt(data, dtype=int, delimiter=',', skiprows=1)
+ assert_equal(test, control)
+
+ def test_header(self):
+ "Test retrieving a header"
+ data = StringIO.StringIO('gender age weight\nM 64.0 75.0\nF 25.0 60.0')
+ test = np.ndfromtxt(data, dtype=None, names=True)
+ control = {'gender': np.array(['M', 'F']),
+ 'age': np.array([64.0, 25.0]),
+ 'weight': np.array([75.0, 60.0])}
+ assert_equal(test['gender'], control['gender'])
+ assert_equal(test['age'], control['age'])
+ assert_equal(test['weight'], control['weight'])
+
+ def test_auto_dtype(self):
+ "Test the automatic definition of the output dtype"
+ data = StringIO.StringIO('A 64 75.0 3+4j True\nBCD 25 60.0 5+6j False')
+ test = np.ndfromtxt(data, dtype=None)
+ control = [np.array(['A', 'BCD']),
+ np.array([64, 25]),
+ np.array([75.0, 60.0]),
+ np.array([3+4j, 5+6j]),
+ np.array([True, False]),]
+ assert_equal(test.dtype.names, ['f0','f1','f2','f3','f4'])
+ for (i, ctrl) in enumerate(control):
+ assert_equal(test['f%i' % i], ctrl)
+
+
+ def test_auto_dtype_uniform(self):
+ "Tests whether the output dtype can be uniformized"
+ data = StringIO.StringIO('1 2 3 4\n5 6 7 8\n')
+ test = np.ndfromtxt(data, dtype=None)
+ control = np.array([[1,2,3,4],[5,6,7,8]])
+ assert_equal(test, control)
+
+
+ def test_fancy_dtype(self):
+ "Check that a nested dtype isn't MIA"
+ data = StringIO.StringIO('1,2,3.0\n4,5,6.0\n')
+ fancydtype = np.dtype([('x', int), ('y', [('t', int), ('s', float)])])
+ test = np.ndfromtxt(data, dtype=fancydtype, delimiter=',')
+ control = np.array([(1,(2,3.0)),(4,(5,6.0))], dtype=fancydtype)
+ assert_equal(test, control)
+
+
+ def test_names_overwrite(self):
+ "Test overwriting the names of the dtype"
+ descriptor = {'names': ('g','a','w'),
+ 'formats': ('S1', 'i4', 'f4')}
+ data = StringIO.StringIO('M 64.0 75.0\nF 25.0 60.0')
+ names = ('gender','age','weight')
+ test = np.ndfromtxt(data, dtype=descriptor, names=names)
+ descriptor['names'] = names
+ control = np.array([('M', 64.0, 75.0),
+ ('F', 25.0, 60.0)], dtype=descriptor)
+ assert_equal(test, control)
+
+
+ def test_commented_header(self):
+ "Check that names can be retrieved even if the line is commented out."
+ data = StringIO.StringIO("""
+#gender age weight
+M 21 72.100000
+F 35 58.330000
+M 33 21.99
+ """)
+ # The # is part of the first name and should be deleted automatically.
+ test = np.genfromtxt(data, names=True, dtype=None)
+ ctrl = np.array([('M', 21, 72.1), ('F', 35, 58.33), ('M', 33, 21.99)],
+ dtype=[('gender','|S1'), ('age', int), ('weight', float)])
+ assert_equal(test, ctrl)
+ # Ditto, but we should get rid of the first element
+ data = StringIO.StringIO("""
+# gender age weight
+M 21 72.100000
+F 35 58.330000
+M 33 21.99
+ """)
+ test = np.genfromtxt(data, names=True, dtype=None)
+ assert_equal(test, ctrl)
+
+
+ def test_autonames_and_usecols(self):
+ "Tests names and usecols"
+ data = StringIO.StringIO('A B C D\n aaaa 121 45 9.1')
+ test = np.ndfromtxt(data, usecols=('A', 'C', 'D'),
+ names=True, dtype=None)
+ control = np.array(('aaaa', 45, 9.1),
+ dtype=[('A', '|S4'), ('C', int), ('D', float)])
+ assert_equal(test, control)
+
+
+ def test_converters_with_usecols(self):
+ "Test the combination user-defined converters and usecol"
+ data = StringIO.StringIO('1,2,3,,5\n6,7,8,9,10\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',',
+ converters={3:lambda s: int(s or -999)},
+ usecols=(1, 3, ))
+ control = np.array([[2, -999], [7, 9]], int)
+ assert_equal(test, control)
+
+ def test_converters_with_usecols_and_names(self):
+ "Tests names and usecols"
+ data = StringIO.StringIO('A B C D\n aaaa 121 45 9.1')
+ test = np.ndfromtxt(data, usecols=('A', 'C', 'D'), names=True,
+ dtype=None, converters={'C':lambda s: 2 * int(s)})
+ control = np.array(('aaaa', 90, 9.1),
+ dtype=[('A', '|S4'), ('C', int), ('D', float)])
+ assert_equal(test, control)
+
+ def test_converters_cornercases(self):
+ "Test the conversion to datetime."
+ converter = {'date': lambda s: strptime(s, '%Y-%m-%d %H:%M:%SZ')}
+ data = StringIO.StringIO('2009-02-03 12:00:00Z, 72214.0')
+ test = np.ndfromtxt(data, delimiter=',', dtype=None,
+ names=['date','stid'], converters=converter)
+ control = np.array((datetime(2009,02,03), 72214.),
+ dtype=[('date', np.object_), ('stid', float)])
+ assert_equal(test, control)
+
+
+ def test_unused_converter(self):
+ "Test whether unused converters are forgotten"
+ data = StringIO.StringIO("1 21\n 3 42\n")
+ test = np.ndfromtxt(data, usecols=(1,),
+ converters={0: lambda s: int(s, 16)})
+ assert_equal(test, [21, 42])
+ #
+ data.seek(0)
+ test = np.ndfromtxt(data, usecols=(1,),
+ converters={1: lambda s: int(s, 16)})
+ assert_equal(test, [33, 66])
+
+
+ def test_dtype_with_converters(self):
+ dstr = "2009; 23; 46"
+ test = np.ndfromtxt(StringIO.StringIO(dstr,),
+ delimiter=";", dtype=float, converters={0:str})
+ control = np.array([('2009', 23., 46)],
+ dtype=[('f0','|S4'), ('f1', float), ('f2', float)])
+ assert_equal(test, control)
+ test = np.ndfromtxt(StringIO.StringIO(dstr,),
+ delimiter=";", dtype=float, converters={0:float})
+ control = np.array([2009., 23., 46],)
+ assert_equal(test, control)
+
+
+ def test_dtype_with_object(self):
+ "Test using an explicit dtype with an object"
+ from datetime import date
+ import time
+ data = """
+ 1; 2001-01-01
+ 2; 2002-01-31
+ """
+ ndtype = [('idx', int), ('code', np.object)]
+ func = lambda s: strptime(s.strip(), "%Y-%m-%d")
+ converters = {1: func}
+ test = np.genfromtxt(StringIO.StringIO(data), delimiter=";", dtype=ndtype,
+ converters=converters)
+ control = np.array([(1, datetime(2001,1,1)), (2, datetime(2002,1,31))],
+ dtype=ndtype)
+ assert_equal(test, control)
+ #
+ ndtype = [('nest', [('idx', int), ('code', np.object)])]
+ try:
+ test = np.genfromtxt(StringIO.StringIO(data), delimiter=";",
+ dtype=ndtype, converters=converters)
+ except NotImplementedError:
+ pass
+ else:
+ errmsg = "Nested dtype involving objects should be supported."
+ raise AssertionError(errmsg)
+
+
+ def test_userconverters_with_explicit_dtype(self):
+ "Test user_converters w/ explicit (standard) dtype"
+ data = StringIO.StringIO('skip,skip,2001-01-01,1.0,skip')
+ test = np.genfromtxt(data, delimiter=",", names=None, dtype=float,
+ usecols=(2, 3), converters={2: str})
+ control = np.array([('2001-01-01', 1.)],
+ dtype=[('', '|S10'), ('', float)])
+ assert_equal(test, control)
+
+
+ def test_spacedelimiter(self):
+ "Test space delimiter"
+ data = StringIO.StringIO("1 2 3 4 5\n6 7 8 9 10")
+ test = np.ndfromtxt(data)
+ control = np.array([[ 1., 2., 3., 4., 5.],
+ [ 6., 7., 8., 9.,10.]])
+ assert_equal(test, control)
+
+
+ def test_missing(self):
+ data = StringIO.StringIO('1,2,3,,5\n')
+ test = np.ndfromtxt(data, dtype=int, delimiter=',', \
+ converters={3:lambda s: int(s or -999)})
+ control = np.array([1, 2, 3, -999, 5], int)
+ assert_equal(test, control)
+
+
+ def test_usecols(self):
+ "Test the selection of columns"
+ # Select 1 column
+ control = np.array( [[1, 2], [3, 4]], float)
+ data = StringIO.StringIO()
+ np.savetxt(data, control)
+ data.seek(0)
+ test = np.ndfromtxt(data, dtype=float, usecols=(1,))
+ assert_equal(test, control[:, 1])
+ #
+ control = np.array( [[1, 2, 3], [3, 4, 5]], float)
+ data = StringIO.StringIO()
+ np.savetxt(data, control)
+ data.seek(0)
+ test = np.ndfromtxt(data, dtype=float, usecols=(1, 2))
+ assert_equal(test, control[:, 1:])
+ # Testing with arrays instead of tuples.
+ data.seek(0)
+ test = np.ndfromtxt(data, dtype=float, usecols=np.array([1, 2]))
+ assert_equal(test, control[:, 1:])
+ # Checking with dtypes defined converters.
+ data = StringIO.StringIO("""JOE 70.1 25.3\nBOB 60.5 27.9""")
+ names = ['stid', 'temp']
+ dtypes = ['S4', 'f8']
+ test = np.ndfromtxt(data, usecols=(0, 2), dtype=zip(names, dtypes))
+ assert_equal(test['stid'], ["JOE", "BOB"])
+ assert_equal(test['temp'], [25.3, 27.9])
+
+
+ def test_empty_file(self):
+ "Test that an empty file raises the proper exception"
+ data = StringIO.StringIO()
+ assert_raises(IOError, np.ndfromtxt, data)
+
+
+ def test_fancy_dtype_alt(self):
+ "Check that a nested dtype isn't MIA"
+ data = StringIO.StringIO('1,2,3.0\n4,5,6.0\n')
+ fancydtype = np.dtype([('x', int), ('y', [('t', int), ('s', float)])])
+ test = np.mafromtxt(data, dtype=fancydtype, delimiter=',')
+ control = ma.array([(1,(2,3.0)),(4,(5,6.0))], dtype=fancydtype)
+ assert_equal(test, control)
+
+
+ def test_withmissing(self):
+ data = StringIO.StringIO('A,B\n0,1\n2,N/A')
+ test = np.mafromtxt(data, dtype=None, delimiter=',', missing='N/A',
+ names=True)
+ control = ma.array([(0, 1), (2, -1)],
+ mask=[(False, False), (False, True)],
+ dtype=[('A', np.int), ('B', np.int)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ #
+ data.seek(0)
+ test = np.mafromtxt(data, delimiter=',', missing='N/A', names=True)
+ control = ma.array([(0, 1), (2, -1)],
+ mask=[[False, False], [False, True]],)
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+
+
+ def test_user_missing_values(self):
+ datastr ="A, B, C\n0, 0., 0j\n1, N/A, 1j\n-9, 2.2, N/A\n3, -99, 3j"
+ data = StringIO.StringIO(datastr)
+ basekwargs = dict(dtype=None, delimiter=',', names=True, missing='N/A')
+ mdtype = [('A', int), ('B', float), ('C', complex)]
+ #
+ test = np.mafromtxt(data, **basekwargs)
+ control = ma.array([( 0, 0.0, 0j), (1, -999, 1j),
+ ( -9, 2.2, -999j), (3, -99, 3j)],
+ mask=[(0, 0, 0), (0, 1, 0), (0, 0, 1), (0, 0, 0)],
+ dtype=mdtype)
+ assert_equal(test, control)
+ #
+ data.seek(0)
+ test = np.mafromtxt(data,
+ missing_values={0:-9, 1:-99, 2:-999j}, **basekwargs)
+ control = ma.array([( 0, 0.0, 0j), (1, -999, 1j),
+ ( -9, 2.2, -999j), (3, -99, 3j)],
+ mask=[(0, 0, 0), (0, 1, 0), (1, 0, 1), (0, 1, 0)],
+ dtype=mdtype)
+ assert_equal(test, control)
+ #
+ data.seek(0)
+ test = np.mafromtxt(data,
+ missing_values={0:-9, 'B':-99, 'C':-999j},
+ **basekwargs)
+ control = ma.array([( 0, 0.0, 0j), (1, -999, 1j),
+ ( -9, 2.2, -999j), (3, -99, 3j)],
+ mask=[(0, 0, 0), (0, 1, 0), (1, 0, 1), (0, 1, 0)],
+ dtype=mdtype)
+ assert_equal(test, control)
+
+
+ def test_withmissing_float(self):
+ data = StringIO.StringIO('A,B\n0,1.5\n2,-999.00')
+ test = np.mafromtxt(data, dtype=None, delimiter=',', missing='-999.0',
+ names=True,)
+ control = ma.array([(0, 1.5), (2, -1.)],
+ mask=[(False, False), (False, True)],
+ dtype=[('A', np.int), ('B', np.float)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+
+
+ def test_with_masked_column_uniform(self):
+ "Test masked column"
+ data = StringIO.StringIO('1 2 3\n4 5 6\n')
+ test = np.genfromtxt(data, missing='2,5', dtype=None, usemask=True)
+ control = ma.array([[1, 2, 3], [4, 5, 6]], mask=[[0, 1, 0],[0, 1, 0]])
+ assert_equal(test, control)
+
+ def test_with_masked_column_various(self):
+ "Test masked column"
+ data = StringIO.StringIO('True 2 3\nFalse 5 6\n')
+ test = np.genfromtxt(data, missing='2,5', dtype=None, usemask=True)
+ control = ma.array([(1, 2, 3), (0, 5, 6)],
+ mask=[(0, 1, 0),(0, 1, 0)],
+ dtype=[('f0', bool), ('f1', bool), ('f2', int)])
+ assert_equal(test, control)
+
+
+ def test_recfromtxt(self):
+ #
+ data = StringIO.StringIO('A,B\n0,1\n2,3')
+ test = np.recfromtxt(data, delimiter=',', missing='N/A', names=True)
+ control = np.array([(0, 1), (2, 3)],
+ dtype=[('A', np.int), ('B', np.int)])
+ self.failUnless(isinstance(test, np.recarray))
+ assert_equal(test, control)
+ #
+ data = StringIO.StringIO('A,B\n0,1\n2,N/A')
+ test = np.recfromtxt(data, dtype=None, delimiter=',', missing='N/A',
+ names=True, usemask=True)
+ control = ma.array([(0, 1), (2, -1)],
+ mask=[(False, False), (False, True)],
+ dtype=[('A', np.int), ('B', np.int)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ assert_equal(test.A, [0, 2])
+
+
+ def test_recfromcsv(self):
+ #
+ data = StringIO.StringIO('A,B\n0,1\n2,3')
+ test = np.recfromcsv(data, missing='N/A',
+ names=True, case_sensitive=True)
+ control = np.array([(0, 1), (2, 3)],
+ dtype=[('A', np.int), ('B', np.int)])
+ self.failUnless(isinstance(test, np.recarray))
+ assert_equal(test, control)
+ #
+ data = StringIO.StringIO('A,B\n0,1\n2,N/A')
+ test = np.recfromcsv(data, dtype=None, missing='N/A',
+ names=True, case_sensitive=True, usemask=True)
+ control = ma.array([(0, 1), (2, -1)],
+ mask=[(False, False), (False, True)],
+ dtype=[('A', np.int), ('B', np.int)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ assert_equal(test.A, [0, 2])
+ #
+ data = StringIO.StringIO('A,B\n0,1\n2,3')
+ test = np.recfromcsv(data, missing='N/A',)
+ control = np.array([(0, 1), (2, 3)],
+ dtype=[('a', np.int), ('b', np.int)])
+ self.failUnless(isinstance(test, np.recarray))
+ assert_equal(test, control)
+
+
+
+
if __name__ == "__main__":
run_module_suite()
diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py
new file mode 100644
index 000000000..424d60ae4
--- /dev/null
+++ b/numpy/lib/tests/test_recfunctions.py
@@ -0,0 +1,606 @@
+import sys
+
+import numpy as np
+import numpy.ma as ma
+from numpy.ma.testutils import *
+
+from numpy.ma.mrecords import MaskedRecords
+
+from numpy.lib.recfunctions import *
+get_names = np.lib.recfunctions.get_names
+get_names_flat = np.lib.recfunctions.get_names_flat
+zip_descr = np.lib.recfunctions.zip_descr
+
+class TestRecFunctions(TestCase):
+ """
+ Misc tests
+ """
+ #
+ def setUp(self):
+ x = np.array([1, 2,])
+ y = np.array([10, 20, 30])
+ z = np.array([('A', 1.), ('B', 2.)],
+ dtype=[('A', '|S3'), ('B', float)])
+ w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ self.data = (w, x, y, z)
+
+
+ def test_zip_descr(self):
+ "Test zip_descr"
+ (w, x, y, z) = self.data
+ # Std array
+ test = zip_descr((x, x), flatten=True)
+ assert_equal(test,
+ np.dtype([('', int), ('', int)]))
+ test = zip_descr((x, x), flatten=False)
+ assert_equal(test,
+ np.dtype([('', int), ('', int)]))
+ # Std & flexible-dtype
+ test = zip_descr((x, z), flatten=True)
+ assert_equal(test,
+ np.dtype([('', int), ('A', '|S3'), ('B', float)]))
+ test = zip_descr((x, z), flatten=False)
+ assert_equal(test,
+ np.dtype([('', int),
+ ('', [('A', '|S3'), ('B', float)])]))
+ # Standard & nested dtype
+ test = zip_descr((x, w), flatten=True)
+ assert_equal(test,
+ np.dtype([('', int),
+ ('a', int),
+ ('ba', float), ('bb', int)]))
+ test = zip_descr((x, w), flatten=False)
+ assert_equal(test,
+ np.dtype([('', int),
+ ('', [('a', int),
+ ('b', [('ba', float), ('bb', int)])])]))
+
+
+ def test_drop_fields(self):
+ "Test drop_fields"
+ a = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ # A basic field
+ test = drop_fields(a, 'a')
+ control = np.array([((2, 3.0),), ((5, 6.0),)],
+ dtype=[('b', [('ba', float), ('bb', int)])])
+ assert_equal(test, control)
+ # Another basic field (but nesting two fields)
+ test = drop_fields(a, 'b')
+ control = np.array([(1,), (4,)], dtype=[('a', int)])
+ assert_equal(test, control)
+ # A nested sub-field
+ test = drop_fields(a, ['ba',])
+ control = np.array([(1, (3.0,)), (4, (6.0,))],
+ dtype=[('a', int), ('b', [('bb', int)])])
+ assert_equal(test, control)
+ # All the nested sub-field from a field: zap that field
+ test = drop_fields(a, ['ba', 'bb'])
+ control = np.array([(1,), (4,)], dtype=[('a', int)])
+ assert_equal(test, control)
+ #
+ test = drop_fields(a, ['a', 'b'])
+ assert(test is None)
+
+
+ def test_rename_fields(self):
+ "Tests rename fields"
+ a = np.array([(1, (2, [3.0, 30.])), (4, (5, [6.0, 60.]))],
+ dtype=[('a', int),
+ ('b', [('ba', float), ('bb', (float, 2))])])
+ test = rename_fields(a, {'a':'A', 'bb':'BB'})
+ newdtype = [('A', int), ('b', [('ba', float), ('BB', (float, 2))])]
+ control = a.view(newdtype)
+ assert_equal(test.dtype, newdtype)
+ assert_equal(test, control)
+
+
+ def test_get_names(self):
+ "Tests get_names"
+ ndtype = np.dtype([('A', '|S3'), ('B', float)])
+ test = get_names(ndtype)
+ assert_equal(test, ('A', 'B'))
+ #
+ ndtype = np.dtype([('a', int), ('b', [('ba', float), ('bb', int)])])
+ test = get_names(ndtype)
+ assert_equal(test, ('a', ('b', ('ba', 'bb'))))
+
+
+ def test_get_names_flat(self):
+ "Test get_names_flat"
+ ndtype = np.dtype([('A', '|S3'), ('B', float)])
+ test = get_names_flat(ndtype)
+ assert_equal(test, ('A', 'B'))
+ #
+ ndtype = np.dtype([('a', int), ('b', [('ba', float), ('bb', int)])])
+ test = get_names_flat(ndtype)
+ assert_equal(test, ('a', 'b', 'ba', 'bb'))
+
+
+ def test_get_fieldstructure(self):
+ "Test get_fieldstructure"
+ # No nested fields
+ ndtype = np.dtype([('A', '|S3'), ('B', float)])
+ test = get_fieldstructure(ndtype)
+ assert_equal(test, {'A':[], 'B':[]})
+ # One 1-nested field
+ ndtype = np.dtype([('A', int), ('B', [('BA', float), ('BB', '|S1')])])
+ test = get_fieldstructure(ndtype)
+ assert_equal(test, {'A': [], 'B': [], 'BA':['B',], 'BB':['B']})
+ # One 2-nested fields
+ ndtype = np.dtype([('A', int),
+ ('B', [('BA', int),
+ ('BB', [('BBA', int), ('BBB', int)])])])
+ test = get_fieldstructure(ndtype)
+ control = {'A': [], 'B': [], 'BA': ['B'], 'BB': ['B'],
+ 'BBA': ['B', 'BB'], 'BBB': ['B', 'BB']}
+ assert_equal(test, control)
+
+
+ @np.testing.dec.knownfailureif(sys.platform=='win32', "Fail on Win32")
+ def test_find_duplicates(self):
+ "Test find_duplicates"
+ a = ma.array([(2, (2., 'B')), (1, (2., 'B')), (2, (2., 'B')),
+ (1, (1., 'B')), (2, (2., 'B')), (2, (2., 'C'))],
+ mask=[(0, (0, 0)), (0, (0, 0)), (0, (0, 0)),
+ (0, (0, 0)), (1, (0, 0)), (0, (1, 0))],
+ dtype=[('A', int), ('B', [('BA', float), ('BB', '|S1')])])
+ #
+ test = find_duplicates(a, ignoremask=False, return_index=True)
+ control = [0, 2]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+ #
+ test = find_duplicates(a, key='A', return_index=True)
+ control = [1, 3, 0, 2, 5]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+ #
+ test = find_duplicates(a, key='B', return_index=True)
+ control = [0, 1, 2, 4]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+ #
+ test = find_duplicates(a, key='BA', return_index=True)
+ control = [0, 1, 2, 4]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+ #
+ test = find_duplicates(a, key='BB', return_index=True)
+ control = [0, 1, 2, 3, 4]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+
+
+ @np.testing.dec.knownfailureif(sys.platform=='win32', "Fail on Win32")
+ def test_find_duplicates_ignoremask(self):
+ "Test the ignoremask option of find_duplicates"
+ ndtype = [('a', int)]
+ a = ma.array([1, 1, 1, 2, 2, 3, 3],
+ mask=[0, 0, 1, 0, 0, 0, 1]).view(ndtype)
+ test = find_duplicates(a, ignoremask=True, return_index=True)
+ control = [0, 1, 3, 4]
+ assert_equal(test[-1], control)
+ assert_equal(test[0], a[control])
+ #
+ test = find_duplicates(a, ignoremask=False, return_index=True)
+ control = [0, 1, 3, 4, 6, 2]
+ try:
+ assert_equal(test[-1], control)
+ except AssertionError:
+ assert_equal(test[-1], [0, 1, 3, 4, 2, 6])
+ assert_equal(test[0], a[control])
+
+
+class TestRecursiveFillFields(TestCase):
+ """
+ Test recursive_fill_fields.
+ """
+ def test_simple_flexible(self):
+ "Test recursive_fill_fields on flexible-array"
+ a = np.array([(1, 10.), (2, 20.)], dtype=[('A', int), ('B', float)])
+ b = np.zeros((3,), dtype=a.dtype)
+ test = recursive_fill_fields(a, b)
+ control = np.array([(1, 10.), (2, 20.), (0, 0.)],
+ dtype=[('A', int), ('B', float)])
+ assert_equal(test, control)
+ #
+ def test_masked_flexible(self):
+ "Test recursive_fill_fields on masked flexible-array"
+ a = ma.array([(1, 10.), (2, 20.)], mask=[(0, 1), (1, 0)],
+ dtype=[('A', int), ('B', float)])
+ b = ma.zeros((3,), dtype=a.dtype)
+ test = recursive_fill_fields(a, b)
+ control = ma.array([(1, 10.), (2, 20.), (0, 0.)],
+ mask=[(0, 1), (1, 0), (0, 0)],
+ dtype=[('A', int), ('B', float)])
+ assert_equal(test, control)
+ #
+
+
+
+class TestMergeArrays(TestCase):
+ """
+ Test merge_arrays
+ """
+ def setUp(self):
+ x = np.array([1, 2,])
+ y = np.array([10, 20, 30])
+ z = np.array([('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
+ w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ self.data = (w, x, y, z)
+ #
+ def test_solo(self):
+ "Test merge_arrays on a single array."
+ (_, x, _, z) = self.data
+ #
+ test = merge_arrays(x)
+ control = np.array([(1,), (2,)], dtype=[('f0', int)])
+ assert_equal(test, control)
+ test = merge_arrays((x,))
+ assert_equal(test, control)
+ #
+ test = merge_arrays(z, flatten=False)
+ assert_equal(test, z)
+ test = merge_arrays(z, flatten=True)
+ assert_equal(test, z)
+ #
+ def test_solo_w_flatten(self):
+ "Test merge_arrays on a single array w & w/o flattening"
+ w = self.data[0]
+ test = merge_arrays(w, flatten=False)
+ assert_equal(test, w)
+ #
+ test = merge_arrays(w, flatten=True)
+ control = np.array([(1, 2, 3.0), (4, 5, 6.0)],
+ dtype=[('a', int), ('ba', float), ('bb', int)])
+ assert_equal(test, control)
+ #
+ def test_standard(self):
+ "Test standard & standard"
+ # Test merge arrays
+ (_, x, y, _) = self.data
+ test = merge_arrays((x, y), usemask=False)
+ control = np.array([(1, 10), (2, 20), (-1, 30)],
+ dtype=[('f0', int), ('f1', int)])
+ assert_equal(test, control)
+ #
+ test = merge_arrays((x, y), usemask=True)
+ control = ma.array([(1, 10), (2, 20), (-1, 30)],
+ mask=[(0, 0), (0, 0), (1, 0)],
+ dtype=[('f0', int), ('f1', int)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ #
+ def test_flatten(self):
+ "Test standard & flexible"
+ (_, x, _, z) = self.data
+ test = merge_arrays((x, z), flatten=True)
+ control = np.array([(1, 'A', 1.), (2, 'B', 2.)],
+ dtype=[('f0', int), ('A', '|S3'), ('B', float)])
+ assert_equal(test, control)
+ #
+ test = merge_arrays((x, z), flatten=False)
+ control = np.array([(1, ('A', 1.)), (2, ('B', 2.))],
+ dtype=[('f0', int),
+ ('f1', [('A', '|S3'), ('B', float)])])
+ assert_equal(test, control)
+ #
+ def test_flatten_wflexible(self):
+ "Test flatten standard & nested"
+ (w, x, _, _) = self.data
+ test = merge_arrays((x, w), flatten=True)
+ control = np.array([(1, 1, 2, 3.0), (2, 4, 5, 6.0)],
+ dtype=[('f0', int),
+ ('a', int), ('ba', float), ('bb', int)])
+ assert_equal(test, control)
+ #
+ test = merge_arrays((x, w), flatten=False)
+ controldtype = dtype=[('f0', int),
+ ('f1', [('a', int),
+ ('b', [('ba', float), ('bb', int)])])]
+ control = np.array([(1., (1, (2, 3.0))), (2, (4, (5, 6.0)))],
+ dtype=controldtype)
+ #
+ def test_wmasked_arrays(self):
+ "Test merge_arrays masked arrays"
+ (_, x, _, _) = self.data
+ mx = ma.array([1, 2, 3], mask=[1, 0, 0])
+ test = merge_arrays((x, mx), usemask=True)
+ control = ma.array([(1, 1), (2, 2), (-1, 3)],
+ mask=[(0, 1), (0, 0), (1, 0)],
+ dtype=[('f0', int), ('f1', int)])
+ assert_equal(test, control)
+ test = merge_arrays((x, mx), usemask=True, asrecarray=True)
+ assert_equal(test, control)
+ assert(isinstance(test, MaskedRecords))
+ #
+ def test_w_singlefield(self):
+ "Test single field"
+ test = merge_arrays((np.array([1, 2]).view([('a', int)]),
+ np.array([10., 20., 30.])),)
+ control = ma.array([(1, 10.), (2, 20.), (-1, 30.)],
+ mask=[(0, 0), (0, 0), (1, 0)],
+ dtype=[('a', int), ('f1', float)])
+ assert_equal(test, control)
+ #
+ def test_w_shorter_flex(self):
+ "Test merge_arrays w/ a shorter flexndarray."
+ z = self.data[-1]
+ test = merge_arrays((z, np.array([10, 20, 30]).view([('C', int)])))
+ control = np.array([('A', 1., 10), ('B', 2., 20), ('-1', -1, 20)],
+ dtype=[('A', '|S3'), ('B', float), ('C', int)])
+
+
+
+class TestAppendFields(TestCase):
+ """
+ Test append_fields
+ """
+ def setUp(self):
+ x = np.array([1, 2,])
+ y = np.array([10, 20, 30])
+ z = np.array([('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
+ w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ self.data = (w, x, y, z)
+ #
+ def test_append_single(self):
+ "Test simple case"
+ (_, x, _, _) = self.data
+ test = append_fields(x, 'A', data=[10, 20, 30])
+ control = ma.array([(1, 10), (2, 20), (-1, 30)],
+ mask=[(0, 0), (0, 0), (1, 0)],
+ dtype=[('f0', int), ('A', int)],)
+ assert_equal(test, control)
+ #
+ def test_append_double(self):
+ "Test simple case"
+ (_, x, _, _) = self.data
+ test = append_fields(x, ('A', 'B'), data=[[10, 20, 30], [100, 200]])
+ control = ma.array([(1, 10, 100), (2, 20, 200), (-1, 30, -1)],
+ mask=[(0, 0, 0), (0, 0, 0), (1, 0, 1)],
+ dtype=[('f0', int), ('A', int), ('B', int)],)
+ assert_equal(test, control)
+ #
+ def test_append_on_flex(self):
+ "Test append_fields on flexible type arrays"
+ z = self.data[-1]
+ test = append_fields(z, 'C', data=[10, 20, 30])
+ control = ma.array([('A', 1., 10), ('B', 2., 20), (-1, -1., 30)],
+ mask=[(0, 0, 0), (0, 0, 0), (1, 1, 0)],
+ dtype=[('A', '|S3'), ('B', float), ('C', int)],)
+ assert_equal(test, control)
+ #
+ def test_append_on_nested(self):
+ "Test append_fields on nested fields"
+ w = self.data[0]
+ test = append_fields(w, 'C', data=[10, 20, 30])
+ control = ma.array([(1, (2, 3.0), 10),
+ (4, (5, 6.0), 20),
+ (-1, (-1, -1.), 30)],
+ mask=[(0, (0, 0), 0), (0, (0, 0), 0), (1, (1, 1), 0)],
+ dtype=[('a', int),
+ ('b', [('ba', float), ('bb', int)]),
+ ('C', int)],)
+ assert_equal(test, control)
+
+
+
+class TestStackArrays(TestCase):
+ """
+ Test stack_arrays
+ """
+ def setUp(self):
+ x = np.array([1, 2,])
+ y = np.array([10, 20, 30])
+ z = np.array([('A', 1.), ('B', 2.)], dtype=[('A', '|S3'), ('B', float)])
+ w = np.array([(1, (2, 3.0)), (4, (5, 6.0))],
+ dtype=[('a', int), ('b', [('ba', float), ('bb', int)])])
+ self.data = (w, x, y, z)
+ #
+ def test_solo(self):
+ "Test stack_arrays on single arrays"
+ (_, x, _, _) = self.data
+ test = stack_arrays((x,))
+ assert_equal(test, x)
+ self.failUnless(test is x)
+ #
+ test = stack_arrays(x)
+ assert_equal(test, x)
+ self.failUnless(test is x)
+ #
+ def test_unnamed_fields(self):
+ "Tests combinations of arrays w/o named fields"
+ (_, x, y, _) = self.data
+ #
+ test = stack_arrays((x, x), usemask=False)
+ control = np.array([1, 2, 1, 2])
+ assert_equal(test, control)
+ #
+ test = stack_arrays((x, y), usemask=False)
+ control = np.array([1, 2, 10, 20, 30])
+ assert_equal(test, control)
+ #
+ test = stack_arrays((y, x), usemask=False)
+ control = np.array([10, 20, 30, 1, 2])
+ assert_equal(test, control)
+ #
+ def test_unnamed_and_named_fields(self):
+ "Test combination of arrays w/ & w/o named fields"
+ (_, x, _, z) = self.data
+ #
+ test = stack_arrays((x, z))
+ control = ma.array([(1, -1, -1), (2, -1, -1),
+ (-1, 'A', 1), (-1, 'B', 2)],
+ mask=[(0, 1, 1), (0, 1, 1),
+ (1, 0, 0), (1, 0, 0)],
+ dtype=[('f0', int), ('A', '|S3'), ('B', float)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ #
+ test = stack_arrays((z, x))
+ control = ma.array([('A', 1, -1), ('B', 2, -1),
+ (-1, -1, 1), (-1, -1, 2),],
+ mask=[(0, 0, 1), (0, 0, 1),
+ (1, 1, 0), (1, 1, 0)],
+ dtype=[('A', '|S3'), ('B', float), ('f2', int)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ #
+ test = stack_arrays((z, z, x))
+ control = ma.array([('A', 1, -1), ('B', 2, -1),
+ ('A', 1, -1), ('B', 2, -1),
+ (-1, -1, 1), (-1, -1, 2),],
+ mask=[(0, 0, 1), (0, 0, 1),
+ (0, 0, 1), (0, 0, 1),
+ (1, 1, 0), (1, 1, 0)],
+ dtype=[('A', '|S3'), ('B', float), ('f2', int)])
+ assert_equal(test, control)
+ #
+ def test_matching_named_fields(self):
+ "Test combination of arrays w/ matching field names"
+ (_, x, _, z) = self.data
+ zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
+ dtype=[('A', '|S3'), ('B', float), ('C', float)])
+ test = stack_arrays((z, zz))
+ control = ma.array([('A', 1, -1), ('B', 2, -1),
+ ('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
+ dtype=[('A', '|S3'), ('B', float), ('C', float)],
+ mask=[(0, 0, 1), (0, 0, 1),
+ (0, 0, 0), (0, 0, 0), (0, 0, 0)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ #
+ test = stack_arrays((z, zz, x))
+ ndtype = [('A', '|S3'), ('B', float), ('C', float), ('f3', int)]
+ control = ma.array([('A', 1, -1, -1), ('B', 2, -1, -1),
+ ('a', 10., 100., -1), ('b', 20., 200., -1),
+ ('c', 30., 300., -1),
+ (-1, -1, -1, 1), (-1, -1, -1, 2)],
+ dtype=ndtype,
+ mask=[(0, 0, 1, 1), (0, 0, 1, 1),
+ (0, 0, 0, 1), (0, 0, 0, 1), (0, 0, 0, 1),
+ (1, 1, 1, 0), (1, 1, 1, 0)])
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+
+
+ def test_defaults(self):
+ "Test defaults: no exception raised if keys of defaults are not fields."
+ (_, _, _, z) = self.data
+ zz = np.array([('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
+ dtype=[('A', '|S3'), ('B', float), ('C', float)])
+ defaults = {'A':'???', 'B':-999., 'C':-9999., 'D':-99999.}
+ test = stack_arrays((z, zz), defaults=defaults)
+ control = ma.array([('A', 1, -9999.), ('B', 2, -9999.),
+ ('a', 10., 100.), ('b', 20., 200.), ('c', 30., 300.)],
+ dtype=[('A', '|S3'), ('B', float), ('C', float)],
+ mask=[(0, 0, 1), (0, 0, 1),
+ (0, 0, 0), (0, 0, 0), (0, 0, 0)])
+ assert_equal(test, control)
+ assert_equal(test.data, control.data)
+ assert_equal(test.mask, control.mask)
+
+
+ def test_autoconversion(self):
+ "Tests autoconversion"
+ adtype = [('A', int), ('B', bool), ('C', float)]
+ a = ma.array([(1, 2, 3)], mask=[(0, 1, 0)], dtype=adtype)
+ bdtype = [('A', int), ('B', float), ('C', float)]
+ b = ma.array([(4, 5, 6)], dtype=bdtype)
+ control = ma.array([(1, 2, 3), (4, 5, 6)], mask=[(0, 1, 0), (0, 0, 0)],
+ dtype=bdtype)
+ test = stack_arrays((a, b), autoconvert=True)
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+ try:
+ test = stack_arrays((a, b), autoconvert=False)
+ except TypeError:
+ pass
+ else:
+ raise AssertionError
+
+
+ def test_checktitles(self):
+ "Test using titles in the field names"
+ adtype = [(('a', 'A'), int), (('b', 'B'), bool), (('c', 'C'), float)]
+ a = ma.array([(1, 2, 3)], mask=[(0, 1, 0)], dtype=adtype)
+ bdtype = [(('a', 'A'), int), (('b', 'B'), bool), (('c', 'C'), float)]
+ b = ma.array([(4, 5, 6)], dtype=bdtype)
+ test = stack_arrays((a, b))
+ control = ma.array([(1, 2, 3), (4, 5, 6)], mask=[(0, 1, 0), (0, 0, 0)],
+ dtype=bdtype)
+ assert_equal(test, control)
+ assert_equal(test.mask, control.mask)
+
+
+class TestJoinBy(TestCase):
+ #
+ def test_base(self):
+ "Basic test of join_by"
+ a = np.array(zip(np.arange(10), np.arange(50, 60), np.arange(100, 110)),
+ dtype=[('a', int), ('b', int), ('c', int)])
+ b = np.array(zip(np.arange(5, 15), np.arange(65, 75), np.arange(100, 110)),
+ dtype=[('a', int), ('b', int), ('d', int)])
+ #
+ test = join_by('a', a, b, jointype='inner')
+ control = np.array([(5, 55, 65, 105, 100), (6, 56, 66, 106, 101),
+ (7, 57, 67, 107, 102), (8, 58, 68, 108, 103),
+ (9, 59, 69, 109, 104)],
+ dtype=[('a', int), ('b1', int), ('b2', int),
+ ('c', int), ('d', int)])
+ assert_equal(test, control)
+ #
+ test = join_by(('a', 'b'), a, b)
+ control = np.array([(5, 55, 105, 100), (6, 56, 106, 101),
+ (7, 57, 107, 102), (8, 58, 108, 103),
+ (9, 59, 109, 104)],
+ dtype=[('a', int), ('b', int),
+ ('c', int), ('d', int)])
+ #
+ test = join_by(('a', 'b'), a, b, 'outer')
+ control = ma.array([( 0, 50, 100, -1), ( 1, 51, 101, -1),
+ ( 2, 52, 102, -1), ( 3, 53, 103, -1),
+ ( 4, 54, 104, -1), ( 5, 55, 105, -1),
+ ( 5, 65, -1, 100), ( 6, 56, 106, -1),
+ ( 6, 66, -1, 101), ( 7, 57, 107, -1),
+ ( 7, 67, -1, 102), ( 8, 58, 108, -1),
+ ( 8, 68, -1, 103), ( 9, 59, 109, -1),
+ ( 9, 69, -1, 104), (10, 70, -1, 105),
+ (11, 71, -1, 106), (12, 72, -1, 107),
+ (13, 73, -1, 108), (14, 74, -1, 109)],
+ mask=[( 0, 0, 0, 1), ( 0, 0, 0, 1),
+ ( 0, 0, 0, 1), ( 0, 0, 0, 1),
+ ( 0, 0, 0, 1), ( 0, 0, 0, 1),
+ ( 0, 0, 1, 0), ( 0, 0, 0, 1),
+ ( 0, 0, 1, 0), ( 0, 0, 0, 1),
+ ( 0, 0, 1, 0), ( 0, 0, 0, 1),
+ ( 0, 0, 1, 0), ( 0, 0, 0, 1),
+ ( 0, 0, 1, 0), ( 0, 0, 1, 0),
+ ( 0, 0, 1, 0), ( 0, 0, 1, 0),
+ ( 0, 0, 1, 0), ( 0, 0, 1, 0)],
+ dtype=[('a', int), ('b', int),
+ ('c', int), ('d', int)])
+ assert_equal(test, control)
+ #
+ test = join_by(('a', 'b'), a, b, 'leftouter')
+ control = ma.array([(0, 50, 100, -1), (1, 51, 101, -1),
+ (2, 52, 102, -1), (3, 53, 103, -1),
+ (4, 54, 104, -1), (5, 55, 105, -1),
+ (6, 56, 106, -1), (7, 57, 107, -1),
+ (8, 58, 108, -1), (9, 59, 109, -1)],
+ mask=[(0, 0, 0, 1), (0, 0, 0, 1),
+ (0, 0, 0, 1), (0, 0, 0, 1),
+ (0, 0, 0, 1), (0, 0, 0, 1),
+ (0, 0, 0, 1), (0, 0, 0, 1),
+ (0, 0, 0, 1), (0, 0, 0, 1)],
+ dtype=[('a', int), ('b', int), ('c', int), ('d', int)])
+
+
+
+
+if __name__ == '__main__':
+ run_module_suite()
diff --git a/numpy/lib/utils.py b/numpy/lib/utils.py
index d749f00b6..9717a7a8f 100644
--- a/numpy/lib/utils.py
+++ b/numpy/lib/utils.py
@@ -699,11 +699,11 @@ def _lookfor_generate_cache(module, import_modules, regenerate):
# import sub-packages
if import_modules and hasattr(item, '__path__'):
- for pth in item.__path__:
- for mod_path in os.listdir(pth):
- init_py = os.path.join(pth, mod_path, '__init__.py')
+ for pth in item.__path__:
+ for mod_path in os.listdir(pth):
+ init_py = os.path.join(pth, mod_path, '__init__.py')
if not os.path.isfile(init_py):
- continue
+ continue
if _all is not None and mod_path not in _all:
continue
try: