Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/testing/utils.py @ 87:2a2c65a20a8b
Add Python libs and headers
author | Chris Cannam |
---|---|
date | Wed, 25 Feb 2015 14:05:22 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
86:413a9d26189e | 87:2a2c65a20a8b |
---|---|
1 """ | |
2 Utility function to facilitate testing. | |
3 | |
4 """ | |
5 from __future__ import division, absolute_import, print_function | |
6 | |
7 import os | |
8 import sys | |
9 import re | |
10 import operator | |
11 import warnings | |
12 from functools import partial | |
13 import shutil | |
14 import contextlib | |
15 from tempfile import mkdtemp | |
16 from .nosetester import import_nose | |
17 from numpy.core import float32, empty, arange, array_repr, ndarray | |
18 | |
19 if sys.version_info[0] >= 3: | |
20 from io import StringIO | |
21 else: | |
22 from StringIO import StringIO | |
23 | |
24 __all__ = ['assert_equal', 'assert_almost_equal', 'assert_approx_equal', | |
25 'assert_array_equal', 'assert_array_less', 'assert_string_equal', | |
26 'assert_array_almost_equal', 'assert_raises', 'build_err_msg', | |
27 'decorate_methods', 'jiffies', 'memusage', 'print_assert_equal', | |
28 'raises', 'rand', 'rundocs', 'runstring', 'verbose', 'measure', | |
29 'assert_', 'assert_array_almost_equal_nulp', 'assert_raises_regex', | |
30 'assert_array_max_ulp', 'assert_warns', 'assert_no_warnings', | |
31 'assert_allclose', 'IgnoreException'] | |
32 | |
33 | |
34 verbose = 0 | |
35 | |
36 | |
37 def assert_(val, msg='') : | |
38 """ | |
39 Assert that works in release mode. | |
40 Accepts callable msg to allow deferring evaluation until failure. | |
41 | |
42 The Python built-in ``assert`` does not work when executing code in | |
43 optimized mode (the ``-O`` flag) - no byte-code is generated for it. | |
44 | |
45 For documentation on usage, refer to the Python documentation. | |
46 | |
47 """ | |
48 if not val : | |
49 try: | |
50 smsg = msg() | |
51 except TypeError: | |
52 smsg = msg | |
53 raise AssertionError(smsg) | |
54 | |
55 def gisnan(x): | |
56 """like isnan, but always raise an error if type not supported instead of | |
57 returning a TypeError object. | |
58 | |
59 Notes | |
60 ----- | |
61 isnan and other ufunc sometimes return a NotImplementedType object instead | |
62 of raising any exception. This function is a wrapper to make sure an | |
63 exception is always raised. | |
64 | |
65 This should be removed once this problem is solved at the Ufunc level.""" | |
66 from numpy.core import isnan | |
67 st = isnan(x) | |
68 if isinstance(st, type(NotImplemented)): | |
69 raise TypeError("isnan not supported for this type") | |
70 return st | |
71 | |
72 def gisfinite(x): | |
73 """like isfinite, but always raise an error if type not supported instead of | |
74 returning a TypeError object. | |
75 | |
76 Notes | |
77 ----- | |
78 isfinite and other ufunc sometimes return a NotImplementedType object instead | |
79 of raising any exception. This function is a wrapper to make sure an | |
80 exception is always raised. | |
81 | |
82 This should be removed once this problem is solved at the Ufunc level.""" | |
83 from numpy.core import isfinite, errstate | |
84 with errstate(invalid='ignore'): | |
85 st = isfinite(x) | |
86 if isinstance(st, type(NotImplemented)): | |
87 raise TypeError("isfinite not supported for this type") | |
88 return st | |
89 | |
90 def gisinf(x): | |
91 """like isinf, but always raise an error if type not supported instead of | |
92 returning a TypeError object. | |
93 | |
94 Notes | |
95 ----- | |
96 isinf and other ufunc sometimes return a NotImplementedType object instead | |
97 of raising any exception. This function is a wrapper to make sure an | |
98 exception is always raised. | |
99 | |
100 This should be removed once this problem is solved at the Ufunc level.""" | |
101 from numpy.core import isinf, errstate | |
102 with errstate(invalid='ignore'): | |
103 st = isinf(x) | |
104 if isinstance(st, type(NotImplemented)): | |
105 raise TypeError("isinf not supported for this type") | |
106 return st | |
107 | |
108 def rand(*args): | |
109 """Returns an array of random numbers with the given shape. | |
110 | |
111 This only uses the standard library, so it is useful for testing purposes. | |
112 """ | |
113 import random | |
114 from numpy.core import zeros, float64 | |
115 results = zeros(args, float64) | |
116 f = results.flat | |
117 for i in range(len(f)): | |
118 f[i] = random.random() | |
119 return results | |
120 | |
121 if sys.platform[:5]=='linux': | |
122 def jiffies(_proc_pid_stat = '/proc/%s/stat'%(os.getpid()), | |
123 _load_time=[]): | |
124 """ Return number of jiffies (1/100ths of a second) that this | |
125 process has been scheduled in user mode. See man 5 proc. """ | |
126 import time | |
127 if not _load_time: | |
128 _load_time.append(time.time()) | |
129 try: | |
130 f=open(_proc_pid_stat, 'r') | |
131 l = f.readline().split(' ') | |
132 f.close() | |
133 return int(l[13]) | |
134 except: | |
135 return int(100*(time.time()-_load_time[0])) | |
136 | |
137 def memusage(_proc_pid_stat = '/proc/%s/stat'%(os.getpid())): | |
138 """ Return virtual memory size in bytes of the running python. | |
139 """ | |
140 try: | |
141 f=open(_proc_pid_stat, 'r') | |
142 l = f.readline().split(' ') | |
143 f.close() | |
144 return int(l[22]) | |
145 except: | |
146 return | |
147 else: | |
148 # os.getpid is not in all platforms available. | |
149 # Using time is safe but inaccurate, especially when process | |
150 # was suspended or sleeping. | |
151 def jiffies(_load_time=[]): | |
152 """ Return number of jiffies (1/100ths of a second) that this | |
153 process has been scheduled in user mode. [Emulation with time.time]. """ | |
154 import time | |
155 if not _load_time: | |
156 _load_time.append(time.time()) | |
157 return int(100*(time.time()-_load_time[0])) | |
158 def memusage(): | |
159 """ Return memory usage of running python. [Not implemented]""" | |
160 raise NotImplementedError | |
161 | |
162 if os.name=='nt' and sys.version[:3] > '2.3': | |
163 # Code "stolen" from enthought/debug/memusage.py | |
164 def GetPerformanceAttributes(object, counter, instance = None, | |
165 inum=-1, format = None, machine=None): | |
166 # NOTE: Many counters require 2 samples to give accurate results, | |
167 # including "% Processor Time" (as by definition, at any instant, a | |
168 # thread's CPU usage is either 0 or 100). To read counters like this, | |
169 # you should copy this function, but keep the counter open, and call | |
170 # CollectQueryData() each time you need to know. | |
171 # See http://msdn.microsoft.com/library/en-us/dnperfmo/html/perfmonpt2.asp | |
172 # My older explanation for this was that the "AddCounter" process forced | |
173 # the CPU to 100%, but the above makes more sense :) | |
174 import win32pdh | |
175 if format is None: format = win32pdh.PDH_FMT_LONG | |
176 path = win32pdh.MakeCounterPath( (machine, object, instance, None, inum, counter) ) | |
177 hq = win32pdh.OpenQuery() | |
178 try: | |
179 hc = win32pdh.AddCounter(hq, path) | |
180 try: | |
181 win32pdh.CollectQueryData(hq) | |
182 type, val = win32pdh.GetFormattedCounterValue(hc, format) | |
183 return val | |
184 finally: | |
185 win32pdh.RemoveCounter(hc) | |
186 finally: | |
187 win32pdh.CloseQuery(hq) | |
188 | |
189 def memusage(processName="python", instance=0): | |
190 # from win32pdhutil, part of the win32all package | |
191 import win32pdh | |
192 return GetPerformanceAttributes("Process", "Virtual Bytes", | |
193 processName, instance, | |
194 win32pdh.PDH_FMT_LONG, None) | |
195 | |
196 def build_err_msg(arrays, err_msg, header='Items are not equal:', | |
197 verbose=True, names=('ACTUAL', 'DESIRED'), precision=8): | |
198 msg = ['\n' + header] | |
199 if err_msg: | |
200 if err_msg.find('\n') == -1 and len(err_msg) < 79-len(header): | |
201 msg = [msg[0] + ' ' + err_msg] | |
202 else: | |
203 msg.append(err_msg) | |
204 if verbose: | |
205 for i, a in enumerate(arrays): | |
206 | |
207 if isinstance(a, ndarray): | |
208 # precision argument is only needed if the objects are ndarrays | |
209 r_func = partial(array_repr, precision=precision) | |
210 else: | |
211 r_func = repr | |
212 | |
213 try: | |
214 r = r_func(a) | |
215 except: | |
216 r = '[repr failed]' | |
217 if r.count('\n') > 3: | |
218 r = '\n'.join(r.splitlines()[:3]) | |
219 r += '...' | |
220 msg.append(' %s: %s' % (names[i], r)) | |
221 return '\n'.join(msg) | |
222 | |
223 def assert_equal(actual,desired,err_msg='',verbose=True): | |
224 """ | |
225 Raises an AssertionError if two objects are not equal. | |
226 | |
227 Given two objects (scalars, lists, tuples, dictionaries or numpy arrays), | |
228 check that all elements of these objects are equal. An exception is raised | |
229 at the first conflicting values. | |
230 | |
231 Parameters | |
232 ---------- | |
233 actual : array_like | |
234 The object to check. | |
235 desired : array_like | |
236 The expected object. | |
237 err_msg : str, optional | |
238 The error message to be printed in case of failure. | |
239 verbose : bool, optional | |
240 If True, the conflicting values are appended to the error message. | |
241 | |
242 Raises | |
243 ------ | |
244 AssertionError | |
245 If actual and desired are not equal. | |
246 | |
247 Examples | |
248 -------- | |
249 >>> np.testing.assert_equal([4,5], [4,6]) | |
250 ... | |
251 <type 'exceptions.AssertionError'>: | |
252 Items are not equal: | |
253 item=1 | |
254 ACTUAL: 5 | |
255 DESIRED: 6 | |
256 | |
257 """ | |
258 if isinstance(desired, dict): | |
259 if not isinstance(actual, dict) : | |
260 raise AssertionError(repr(type(actual))) | |
261 assert_equal(len(actual), len(desired), err_msg, verbose) | |
262 for k, i in desired.items(): | |
263 if k not in actual : | |
264 raise AssertionError(repr(k)) | |
265 assert_equal(actual[k], desired[k], 'key=%r\n%s' % (k, err_msg), verbose) | |
266 return | |
267 if isinstance(desired, (list, tuple)) and isinstance(actual, (list, tuple)): | |
268 assert_equal(len(actual), len(desired), err_msg, verbose) | |
269 for k in range(len(desired)): | |
270 assert_equal(actual[k], desired[k], 'item=%r\n%s' % (k, err_msg), verbose) | |
271 return | |
272 from numpy.core import ndarray, isscalar, signbit | |
273 from numpy.lib import iscomplexobj, real, imag | |
274 if isinstance(actual, ndarray) or isinstance(desired, ndarray): | |
275 return assert_array_equal(actual, desired, err_msg, verbose) | |
276 msg = build_err_msg([actual, desired], err_msg, verbose=verbose) | |
277 | |
278 # Handle complex numbers: separate into real/imag to handle | |
279 # nan/inf/negative zero correctly | |
280 # XXX: catch ValueError for subclasses of ndarray where iscomplex fail | |
281 try: | |
282 usecomplex = iscomplexobj(actual) or iscomplexobj(desired) | |
283 except ValueError: | |
284 usecomplex = False | |
285 | |
286 if usecomplex: | |
287 if iscomplexobj(actual): | |
288 actualr = real(actual) | |
289 actuali = imag(actual) | |
290 else: | |
291 actualr = actual | |
292 actuali = 0 | |
293 if iscomplexobj(desired): | |
294 desiredr = real(desired) | |
295 desiredi = imag(desired) | |
296 else: | |
297 desiredr = desired | |
298 desiredi = 0 | |
299 try: | |
300 assert_equal(actualr, desiredr) | |
301 assert_equal(actuali, desiredi) | |
302 except AssertionError: | |
303 raise AssertionError(msg) | |
304 | |
305 # Inf/nan/negative zero handling | |
306 try: | |
307 # isscalar test to check cases such as [np.nan] != np.nan | |
308 if isscalar(desired) != isscalar(actual): | |
309 raise AssertionError(msg) | |
310 | |
311 # If one of desired/actual is not finite, handle it specially here: | |
312 # check that both are nan if any is a nan, and test for equality | |
313 # otherwise | |
314 if not (gisfinite(desired) and gisfinite(actual)): | |
315 isdesnan = gisnan(desired) | |
316 isactnan = gisnan(actual) | |
317 if isdesnan or isactnan: | |
318 if not (isdesnan and isactnan): | |
319 raise AssertionError(msg) | |
320 else: | |
321 if not desired == actual: | |
322 raise AssertionError(msg) | |
323 return | |
324 elif desired == 0 and actual == 0: | |
325 if not signbit(desired) == signbit(actual): | |
326 raise AssertionError(msg) | |
327 # If TypeError or ValueError raised while using isnan and co, just handle | |
328 # as before | |
329 except (TypeError, ValueError, NotImplementedError): | |
330 pass | |
331 | |
332 # Explicitly use __eq__ for comparison, ticket #2552 | |
333 if not (desired == actual): | |
334 raise AssertionError(msg) | |
335 | |
336 def print_assert_equal(test_string, actual, desired): | |
337 """ | |
338 Test if two objects are equal, and print an error message if test fails. | |
339 | |
340 The test is performed with ``actual == desired``. | |
341 | |
342 Parameters | |
343 ---------- | |
344 test_string : str | |
345 The message supplied to AssertionError. | |
346 actual : object | |
347 The object to test for equality against `desired`. | |
348 desired : object | |
349 The expected result. | |
350 | |
351 Examples | |
352 -------- | |
353 >>> np.testing.print_assert_equal('Test XYZ of func xyz', [0, 1], [0, 1]) | |
354 >>> np.testing.print_assert_equal('Test XYZ of func xyz', [0, 1], [0, 2]) | |
355 Traceback (most recent call last): | |
356 ... | |
357 AssertionError: Test XYZ of func xyz failed | |
358 ACTUAL: | |
359 [0, 1] | |
360 DESIRED: | |
361 [0, 2] | |
362 | |
363 """ | |
364 import pprint | |
365 | |
366 if not (actual == desired): | |
367 msg = StringIO() | |
368 msg.write(test_string) | |
369 msg.write(' failed\nACTUAL: \n') | |
370 pprint.pprint(actual, msg) | |
371 msg.write('DESIRED: \n') | |
372 pprint.pprint(desired, msg) | |
373 raise AssertionError(msg.getvalue()) | |
374 | |
375 def assert_almost_equal(actual,desired,decimal=7,err_msg='',verbose=True): | |
376 """ | |
377 Raises an AssertionError if two items are not equal up to desired | |
378 precision. | |
379 | |
380 .. note:: It is recommended to use one of `assert_allclose`, | |
381 `assert_array_almost_equal_nulp` or `assert_array_max_ulp` | |
382 instead of this function for more consistent floating point | |
383 comparisons. | |
384 | |
385 The test is equivalent to ``abs(desired-actual) < 0.5 * 10**(-decimal)``. | |
386 | |
387 Given two objects (numbers or ndarrays), check that all elements of these | |
388 objects are almost equal. An exception is raised at conflicting values. | |
389 For ndarrays this delegates to assert_array_almost_equal | |
390 | |
391 Parameters | |
392 ---------- | |
393 actual : array_like | |
394 The object to check. | |
395 desired : array_like | |
396 The expected object. | |
397 decimal : int, optional | |
398 Desired precision, default is 7. | |
399 err_msg : str, optional | |
400 The error message to be printed in case of failure. | |
401 verbose : bool, optional | |
402 If True, the conflicting values are appended to the error message. | |
403 | |
404 Raises | |
405 ------ | |
406 AssertionError | |
407 If actual and desired are not equal up to specified precision. | |
408 | |
409 See Also | |
410 -------- | |
411 assert_allclose: Compare two array_like objects for equality with desired | |
412 relative and/or absolute precision. | |
413 assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal | |
414 | |
415 Examples | |
416 -------- | |
417 >>> import numpy.testing as npt | |
418 >>> npt.assert_almost_equal(2.3333333333333, 2.33333334) | |
419 >>> npt.assert_almost_equal(2.3333333333333, 2.33333334, decimal=10) | |
420 ... | |
421 <type 'exceptions.AssertionError'>: | |
422 Items are not equal: | |
423 ACTUAL: 2.3333333333333002 | |
424 DESIRED: 2.3333333399999998 | |
425 | |
426 >>> npt.assert_almost_equal(np.array([1.0,2.3333333333333]), | |
427 ... np.array([1.0,2.33333334]), decimal=9) | |
428 ... | |
429 <type 'exceptions.AssertionError'>: | |
430 Arrays are not almost equal | |
431 <BLANKLINE> | |
432 (mismatch 50.0%) | |
433 x: array([ 1. , 2.33333333]) | |
434 y: array([ 1. , 2.33333334]) | |
435 | |
436 """ | |
437 from numpy.core import ndarray | |
438 from numpy.lib import iscomplexobj, real, imag | |
439 | |
440 # Handle complex numbers: separate into real/imag to handle | |
441 # nan/inf/negative zero correctly | |
442 # XXX: catch ValueError for subclasses of ndarray where iscomplex fail | |
443 try: | |
444 usecomplex = iscomplexobj(actual) or iscomplexobj(desired) | |
445 except ValueError: | |
446 usecomplex = False | |
447 | |
448 def _build_err_msg(): | |
449 header = ('Arrays are not almost equal to %d decimals' % decimal) | |
450 return build_err_msg([actual, desired], err_msg, verbose=verbose, | |
451 header=header) | |
452 | |
453 if usecomplex: | |
454 if iscomplexobj(actual): | |
455 actualr = real(actual) | |
456 actuali = imag(actual) | |
457 else: | |
458 actualr = actual | |
459 actuali = 0 | |
460 if iscomplexobj(desired): | |
461 desiredr = real(desired) | |
462 desiredi = imag(desired) | |
463 else: | |
464 desiredr = desired | |
465 desiredi = 0 | |
466 try: | |
467 assert_almost_equal(actualr, desiredr, decimal=decimal) | |
468 assert_almost_equal(actuali, desiredi, decimal=decimal) | |
469 except AssertionError: | |
470 raise AssertionError(_build_err_msg()) | |
471 | |
472 if isinstance(actual, (ndarray, tuple, list)) \ | |
473 or isinstance(desired, (ndarray, tuple, list)): | |
474 return assert_array_almost_equal(actual, desired, decimal, err_msg) | |
475 try: | |
476 # If one of desired/actual is not finite, handle it specially here: | |
477 # check that both are nan if any is a nan, and test for equality | |
478 # otherwise | |
479 if not (gisfinite(desired) and gisfinite(actual)): | |
480 if gisnan(desired) or gisnan(actual): | |
481 if not (gisnan(desired) and gisnan(actual)): | |
482 raise AssertionError(_build_err_msg()) | |
483 else: | |
484 if not desired == actual: | |
485 raise AssertionError(_build_err_msg()) | |
486 return | |
487 except (NotImplementedError, TypeError): | |
488 pass | |
489 if round(abs(desired - actual), decimal) != 0 : | |
490 raise AssertionError(_build_err_msg()) | |
491 | |
492 | |
493 def assert_approx_equal(actual,desired,significant=7,err_msg='',verbose=True): | |
494 """ | |
495 Raises an AssertionError if two items are not equal up to significant | |
496 digits. | |
497 | |
498 .. note:: It is recommended to use one of `assert_allclose`, | |
499 `assert_array_almost_equal_nulp` or `assert_array_max_ulp` | |
500 instead of this function for more consistent floating point | |
501 comparisons. | |
502 | |
503 Given two numbers, check that they are approximately equal. | |
504 Approximately equal is defined as the number of significant digits | |
505 that agree. | |
506 | |
507 Parameters | |
508 ---------- | |
509 actual : scalar | |
510 The object to check. | |
511 desired : scalar | |
512 The expected object. | |
513 significant : int, optional | |
514 Desired precision, default is 7. | |
515 err_msg : str, optional | |
516 The error message to be printed in case of failure. | |
517 verbose : bool, optional | |
518 If True, the conflicting values are appended to the error message. | |
519 | |
520 Raises | |
521 ------ | |
522 AssertionError | |
523 If actual and desired are not equal up to specified precision. | |
524 | |
525 See Also | |
526 -------- | |
527 assert_allclose: Compare two array_like objects for equality with desired | |
528 relative and/or absolute precision. | |
529 assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal | |
530 | |
531 Examples | |
532 -------- | |
533 >>> np.testing.assert_approx_equal(0.12345677777777e-20, 0.1234567e-20) | |
534 >>> np.testing.assert_approx_equal(0.12345670e-20, 0.12345671e-20, | |
535 significant=8) | |
536 >>> np.testing.assert_approx_equal(0.12345670e-20, 0.12345672e-20, | |
537 significant=8) | |
538 ... | |
539 <type 'exceptions.AssertionError'>: | |
540 Items are not equal to 8 significant digits: | |
541 ACTUAL: 1.234567e-021 | |
542 DESIRED: 1.2345672000000001e-021 | |
543 | |
544 the evaluated condition that raises the exception is | |
545 | |
546 >>> abs(0.12345670e-20/1e-21 - 0.12345672e-20/1e-21) >= 10**-(8-1) | |
547 True | |
548 | |
549 """ | |
550 import numpy as np | |
551 | |
552 (actual, desired) = map(float, (actual, desired)) | |
553 if desired==actual: | |
554 return | |
555 # Normalized the numbers to be in range (-10.0,10.0) | |
556 # scale = float(pow(10,math.floor(math.log10(0.5*(abs(desired)+abs(actual)))))) | |
557 with np.errstate(invalid='ignore'): | |
558 scale = 0.5*(np.abs(desired) + np.abs(actual)) | |
559 scale = np.power(10, np.floor(np.log10(scale))) | |
560 try: | |
561 sc_desired = desired/scale | |
562 except ZeroDivisionError: | |
563 sc_desired = 0.0 | |
564 try: | |
565 sc_actual = actual/scale | |
566 except ZeroDivisionError: | |
567 sc_actual = 0.0 | |
568 msg = build_err_msg([actual, desired], err_msg, | |
569 header='Items are not equal to %d significant digits:' % | |
570 significant, | |
571 verbose=verbose) | |
572 try: | |
573 # If one of desired/actual is not finite, handle it specially here: | |
574 # check that both are nan if any is a nan, and test for equality | |
575 # otherwise | |
576 if not (gisfinite(desired) and gisfinite(actual)): | |
577 if gisnan(desired) or gisnan(actual): | |
578 if not (gisnan(desired) and gisnan(actual)): | |
579 raise AssertionError(msg) | |
580 else: | |
581 if not desired == actual: | |
582 raise AssertionError(msg) | |
583 return | |
584 except (TypeError, NotImplementedError): | |
585 pass | |
586 if np.abs(sc_desired - sc_actual) >= np.power(10., -(significant-1)) : | |
587 raise AssertionError(msg) | |
588 | |
589 def assert_array_compare(comparison, x, y, err_msg='', verbose=True, | |
590 header='', precision=6): | |
591 from numpy.core import array, isnan, isinf, any, all, inf | |
592 x = array(x, copy=False, subok=True) | |
593 y = array(y, copy=False, subok=True) | |
594 | |
595 def isnumber(x): | |
596 return x.dtype.char in '?bhilqpBHILQPefdgFDG' | |
597 | |
598 def chk_same_position(x_id, y_id, hasval='nan'): | |
599 """Handling nan/inf: check that x and y have the nan/inf at the same | |
600 locations.""" | |
601 try: | |
602 assert_array_equal(x_id, y_id) | |
603 except AssertionError: | |
604 msg = build_err_msg([x, y], | |
605 err_msg + '\nx and y %s location mismatch:' \ | |
606 % (hasval), verbose=verbose, header=header, | |
607 names=('x', 'y'), precision=precision) | |
608 raise AssertionError(msg) | |
609 | |
610 try: | |
611 cond = (x.shape==() or y.shape==()) or x.shape == y.shape | |
612 if not cond: | |
613 msg = build_err_msg([x, y], | |
614 err_msg | |
615 + '\n(shapes %s, %s mismatch)' % (x.shape, | |
616 y.shape), | |
617 verbose=verbose, header=header, | |
618 names=('x', 'y'), precision=precision) | |
619 if not cond : | |
620 raise AssertionError(msg) | |
621 | |
622 if isnumber(x) and isnumber(y): | |
623 x_isnan, y_isnan = isnan(x), isnan(y) | |
624 x_isinf, y_isinf = isinf(x), isinf(y) | |
625 | |
626 # Validate that the special values are in the same place | |
627 if any(x_isnan) or any(y_isnan): | |
628 chk_same_position(x_isnan, y_isnan, hasval='nan') | |
629 if any(x_isinf) or any(y_isinf): | |
630 # Check +inf and -inf separately, since they are different | |
631 chk_same_position(x == +inf, y == +inf, hasval='+inf') | |
632 chk_same_position(x == -inf, y == -inf, hasval='-inf') | |
633 | |
634 # Combine all the special values | |
635 x_id, y_id = x_isnan, y_isnan | |
636 x_id |= x_isinf | |
637 y_id |= y_isinf | |
638 | |
639 # Only do the comparison if actual values are left | |
640 if all(x_id): | |
641 return | |
642 | |
643 if any(x_id): | |
644 val = comparison(x[~x_id], y[~y_id]) | |
645 else: | |
646 val = comparison(x, y) | |
647 else: | |
648 val = comparison(x, y) | |
649 | |
650 if isinstance(val, bool): | |
651 cond = val | |
652 reduced = [0] | |
653 else: | |
654 reduced = val.ravel() | |
655 cond = reduced.all() | |
656 reduced = reduced.tolist() | |
657 if not cond: | |
658 match = 100-100.0*reduced.count(1)/len(reduced) | |
659 msg = build_err_msg([x, y], | |
660 err_msg | |
661 + '\n(mismatch %s%%)' % (match,), | |
662 verbose=verbose, header=header, | |
663 names=('x', 'y'), precision=precision) | |
664 if not cond : | |
665 raise AssertionError(msg) | |
666 except ValueError as e: | |
667 import traceback | |
668 efmt = traceback.format_exc() | |
669 header = 'error during assertion:\n\n%s\n\n%s' % (efmt, header) | |
670 | |
671 msg = build_err_msg([x, y], err_msg, verbose=verbose, header=header, | |
672 names=('x', 'y'), precision=precision) | |
673 raise ValueError(msg) | |
674 | |
675 def assert_array_equal(x, y, err_msg='', verbose=True): | |
676 """ | |
677 Raises an AssertionError if two array_like objects are not equal. | |
678 | |
679 Given two array_like objects, check that the shape is equal and all | |
680 elements of these objects are equal. An exception is raised at | |
681 shape mismatch or conflicting values. In contrast to the standard usage | |
682 in numpy, NaNs are compared like numbers, no assertion is raised if | |
683 both objects have NaNs in the same positions. | |
684 | |
685 The usual caution for verifying equality with floating point numbers is | |
686 advised. | |
687 | |
688 Parameters | |
689 ---------- | |
690 x : array_like | |
691 The actual object to check. | |
692 y : array_like | |
693 The desired, expected object. | |
694 err_msg : str, optional | |
695 The error message to be printed in case of failure. | |
696 verbose : bool, optional | |
697 If True, the conflicting values are appended to the error message. | |
698 | |
699 Raises | |
700 ------ | |
701 AssertionError | |
702 If actual and desired objects are not equal. | |
703 | |
704 See Also | |
705 -------- | |
706 assert_allclose: Compare two array_like objects for equality with desired | |
707 relative and/or absolute precision. | |
708 assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal | |
709 | |
710 Examples | |
711 -------- | |
712 The first assert does not raise an exception: | |
713 | |
714 >>> np.testing.assert_array_equal([1.0,2.33333,np.nan], | |
715 ... [np.exp(0),2.33333, np.nan]) | |
716 | |
717 Assert fails with numerical inprecision with floats: | |
718 | |
719 >>> np.testing.assert_array_equal([1.0,np.pi,np.nan], | |
720 ... [1, np.sqrt(np.pi)**2, np.nan]) | |
721 ... | |
722 <type 'exceptions.ValueError'>: | |
723 AssertionError: | |
724 Arrays are not equal | |
725 <BLANKLINE> | |
726 (mismatch 50.0%) | |
727 x: array([ 1. , 3.14159265, NaN]) | |
728 y: array([ 1. , 3.14159265, NaN]) | |
729 | |
730 Use `assert_allclose` or one of the nulp (number of floating point values) | |
731 functions for these cases instead: | |
732 | |
733 >>> np.testing.assert_allclose([1.0,np.pi,np.nan], | |
734 ... [1, np.sqrt(np.pi)**2, np.nan], | |
735 ... rtol=1e-10, atol=0) | |
736 | |
737 """ | |
738 assert_array_compare(operator.__eq__, x, y, err_msg=err_msg, | |
739 verbose=verbose, header='Arrays are not equal') | |
740 | |
741 def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True): | |
742 """ | |
743 Raises an AssertionError if two objects are not equal up to desired | |
744 precision. | |
745 | |
746 .. note:: It is recommended to use one of `assert_allclose`, | |
747 `assert_array_almost_equal_nulp` or `assert_array_max_ulp` | |
748 instead of this function for more consistent floating point | |
749 comparisons. | |
750 | |
751 The test verifies identical shapes and verifies values with | |
752 ``abs(desired-actual) < 0.5 * 10**(-decimal)``. | |
753 | |
754 Given two array_like objects, check that the shape is equal and all | |
755 elements of these objects are almost equal. An exception is raised at | |
756 shape mismatch or conflicting values. In contrast to the standard usage | |
757 in numpy, NaNs are compared like numbers, no assertion is raised if | |
758 both objects have NaNs in the same positions. | |
759 | |
760 Parameters | |
761 ---------- | |
762 x : array_like | |
763 The actual object to check. | |
764 y : array_like | |
765 The desired, expected object. | |
766 decimal : int, optional | |
767 Desired precision, default is 6. | |
768 err_msg : str, optional | |
769 The error message to be printed in case of failure. | |
770 verbose : bool, optional | |
771 If True, the conflicting values are appended to the error message. | |
772 | |
773 Raises | |
774 ------ | |
775 AssertionError | |
776 If actual and desired are not equal up to specified precision. | |
777 | |
778 See Also | |
779 -------- | |
780 assert_allclose: Compare two array_like objects for equality with desired | |
781 relative and/or absolute precision. | |
782 assert_array_almost_equal_nulp, assert_array_max_ulp, assert_equal | |
783 | |
784 Examples | |
785 -------- | |
786 the first assert does not raise an exception | |
787 | |
788 >>> np.testing.assert_array_almost_equal([1.0,2.333,np.nan], | |
789 [1.0,2.333,np.nan]) | |
790 | |
791 >>> np.testing.assert_array_almost_equal([1.0,2.33333,np.nan], | |
792 ... [1.0,2.33339,np.nan], decimal=5) | |
793 ... | |
794 <type 'exceptions.AssertionError'>: | |
795 AssertionError: | |
796 Arrays are not almost equal | |
797 <BLANKLINE> | |
798 (mismatch 50.0%) | |
799 x: array([ 1. , 2.33333, NaN]) | |
800 y: array([ 1. , 2.33339, NaN]) | |
801 | |
802 >>> np.testing.assert_array_almost_equal([1.0,2.33333,np.nan], | |
803 ... [1.0,2.33333, 5], decimal=5) | |
804 <type 'exceptions.ValueError'>: | |
805 ValueError: | |
806 Arrays are not almost equal | |
807 x: array([ 1. , 2.33333, NaN]) | |
808 y: array([ 1. , 2.33333, 5. ]) | |
809 | |
810 """ | |
811 from numpy.core import around, number, float_, result_type, array | |
812 from numpy.core.numerictypes import issubdtype | |
813 from numpy.core.fromnumeric import any as npany | |
814 def compare(x, y): | |
815 try: | |
816 if npany(gisinf(x)) or npany( gisinf(y)): | |
817 xinfid = gisinf(x) | |
818 yinfid = gisinf(y) | |
819 if not xinfid == yinfid: | |
820 return False | |
821 # if one item, x and y is +- inf | |
822 if x.size == y.size == 1: | |
823 return x == y | |
824 x = x[~xinfid] | |
825 y = y[~yinfid] | |
826 except (TypeError, NotImplementedError): | |
827 pass | |
828 | |
829 # make sure y is an inexact type to avoid abs(MIN_INT); will cause | |
830 # casting of x later. | |
831 dtype = result_type(y, 1.) | |
832 y = array(y, dtype=dtype, copy=False, subok=True) | |
833 z = abs(x-y) | |
834 | |
835 if not issubdtype(z.dtype, number): | |
836 z = z.astype(float_) # handle object arrays | |
837 | |
838 return around(z, decimal) <= 10.0**(-decimal) | |
839 | |
840 assert_array_compare(compare, x, y, err_msg=err_msg, verbose=verbose, | |
841 header=('Arrays are not almost equal to %d decimals' % decimal), | |
842 precision=decimal) | |
843 | |
844 | |
845 def assert_array_less(x, y, err_msg='', verbose=True): | |
846 """ | |
847 Raises an AssertionError if two array_like objects are not ordered by less | |
848 than. | |
849 | |
850 Given two array_like objects, check that the shape is equal and all | |
851 elements of the first object are strictly smaller than those of the | |
852 second object. An exception is raised at shape mismatch or incorrectly | |
853 ordered values. Shape mismatch does not raise if an object has zero | |
854 dimension. In contrast to the standard usage in numpy, NaNs are | |
855 compared, no assertion is raised if both objects have NaNs in the same | |
856 positions. | |
857 | |
858 | |
859 | |
860 Parameters | |
861 ---------- | |
862 x : array_like | |
863 The smaller object to check. | |
864 y : array_like | |
865 The larger object to compare. | |
866 err_msg : string | |
867 The error message to be printed in case of failure. | |
868 verbose : bool | |
869 If True, the conflicting values are appended to the error message. | |
870 | |
871 Raises | |
872 ------ | |
873 AssertionError | |
874 If actual and desired objects are not equal. | |
875 | |
876 See Also | |
877 -------- | |
878 assert_array_equal: tests objects for equality | |
879 assert_array_almost_equal: test objects for equality up to precision | |
880 | |
881 | |
882 | |
883 Examples | |
884 -------- | |
885 >>> np.testing.assert_array_less([1.0, 1.0, np.nan], [1.1, 2.0, np.nan]) | |
886 >>> np.testing.assert_array_less([1.0, 1.0, np.nan], [1, 2.0, np.nan]) | |
887 ... | |
888 <type 'exceptions.ValueError'>: | |
889 Arrays are not less-ordered | |
890 (mismatch 50.0%) | |
891 x: array([ 1., 1., NaN]) | |
892 y: array([ 1., 2., NaN]) | |
893 | |
894 >>> np.testing.assert_array_less([1.0, 4.0], 3) | |
895 ... | |
896 <type 'exceptions.ValueError'>: | |
897 Arrays are not less-ordered | |
898 (mismatch 50.0%) | |
899 x: array([ 1., 4.]) | |
900 y: array(3) | |
901 | |
902 >>> np.testing.assert_array_less([1.0, 2.0, 3.0], [4]) | |
903 ... | |
904 <type 'exceptions.ValueError'>: | |
905 Arrays are not less-ordered | |
906 (shapes (3,), (1,) mismatch) | |
907 x: array([ 1., 2., 3.]) | |
908 y: array([4]) | |
909 | |
910 """ | |
911 assert_array_compare(operator.__lt__, x, y, err_msg=err_msg, | |
912 verbose=verbose, | |
913 header='Arrays are not less-ordered') | |
914 | |
915 def runstring(astr, dict): | |
916 exec(astr, dict) | |
917 | |
918 def assert_string_equal(actual, desired): | |
919 """ | |
920 Test if two strings are equal. | |
921 | |
922 If the given strings are equal, `assert_string_equal` does nothing. | |
923 If they are not equal, an AssertionError is raised, and the diff | |
924 between the strings is shown. | |
925 | |
926 Parameters | |
927 ---------- | |
928 actual : str | |
929 The string to test for equality against the expected string. | |
930 desired : str | |
931 The expected string. | |
932 | |
933 Examples | |
934 -------- | |
935 >>> np.testing.assert_string_equal('abc', 'abc') | |
936 >>> np.testing.assert_string_equal('abc', 'abcd') | |
937 Traceback (most recent call last): | |
938 File "<stdin>", line 1, in <module> | |
939 ... | |
940 AssertionError: Differences in strings: | |
941 - abc+ abcd? + | |
942 | |
943 """ | |
944 # delay import of difflib to reduce startup time | |
945 import difflib | |
946 | |
947 if not isinstance(actual, str) : | |
948 raise AssertionError(repr(type(actual))) | |
949 if not isinstance(desired, str): | |
950 raise AssertionError(repr(type(desired))) | |
951 if re.match(r'\A'+desired+r'\Z', actual, re.M): | |
952 return | |
953 | |
954 diff = list(difflib.Differ().compare(actual.splitlines(1), desired.splitlines(1))) | |
955 diff_list = [] | |
956 while diff: | |
957 d1 = diff.pop(0) | |
958 if d1.startswith(' '): | |
959 continue | |
960 if d1.startswith('- '): | |
961 l = [d1] | |
962 d2 = diff.pop(0) | |
963 if d2.startswith('? '): | |
964 l.append(d2) | |
965 d2 = diff.pop(0) | |
966 if not d2.startswith('+ ') : | |
967 raise AssertionError(repr(d2)) | |
968 l.append(d2) | |
969 d3 = diff.pop(0) | |
970 if d3.startswith('? '): | |
971 l.append(d3) | |
972 else: | |
973 diff.insert(0, d3) | |
974 if re.match(r'\A'+d2[2:]+r'\Z', d1[2:]): | |
975 continue | |
976 diff_list.extend(l) | |
977 continue | |
978 raise AssertionError(repr(d1)) | |
979 if not diff_list: | |
980 return | |
981 msg = 'Differences in strings:\n%s' % (''.join(diff_list)).rstrip() | |
982 if actual != desired : | |
983 raise AssertionError(msg) | |
984 | |
985 | |
986 def rundocs(filename=None, raise_on_error=True): | |
987 """ | |
988 Run doctests found in the given file. | |
989 | |
990 By default `rundocs` raises an AssertionError on failure. | |
991 | |
992 Parameters | |
993 ---------- | |
994 filename : str | |
995 The path to the file for which the doctests are run. | |
996 raise_on_error : bool | |
997 Whether to raise an AssertionError when a doctest fails. Default is | |
998 True. | |
999 | |
1000 Notes | |
1001 ----- | |
1002 The doctests can be run by the user/developer by adding the ``doctests`` | |
1003 argument to the ``test()`` call. For example, to run all tests (including | |
1004 doctests) for `numpy.lib`: | |
1005 | |
1006 >>> np.lib.test(doctests=True) #doctest: +SKIP | |
1007 """ | |
1008 import doctest, imp | |
1009 if filename is None: | |
1010 f = sys._getframe(1) | |
1011 filename = f.f_globals['__file__'] | |
1012 name = os.path.splitext(os.path.basename(filename))[0] | |
1013 path = [os.path.dirname(filename)] | |
1014 file, pathname, description = imp.find_module(name, path) | |
1015 try: | |
1016 m = imp.load_module(name, file, pathname, description) | |
1017 finally: | |
1018 file.close() | |
1019 | |
1020 tests = doctest.DocTestFinder().find(m) | |
1021 runner = doctest.DocTestRunner(verbose=False) | |
1022 | |
1023 msg = [] | |
1024 if raise_on_error: | |
1025 out = lambda s: msg.append(s) | |
1026 else: | |
1027 out = None | |
1028 | |
1029 for test in tests: | |
1030 runner.run(test, out=out) | |
1031 | |
1032 if runner.failures > 0 and raise_on_error: | |
1033 raise AssertionError("Some doctests failed:\n%s" % "\n".join(msg)) | |
1034 | |
1035 | |
1036 def raises(*args,**kwargs): | |
1037 nose = import_nose() | |
1038 return nose.tools.raises(*args,**kwargs) | |
1039 | |
1040 | |
1041 def assert_raises(*args,**kwargs): | |
1042 """ | |
1043 assert_raises(exception_class, callable, *args, **kwargs) | |
1044 | |
1045 Fail unless an exception of class exception_class is thrown | |
1046 by callable when invoked with arguments args and keyword | |
1047 arguments kwargs. If a different type of exception is | |
1048 thrown, it will not be caught, and the test case will be | |
1049 deemed to have suffered an error, exactly as for an | |
1050 unexpected exception. | |
1051 | |
1052 """ | |
1053 nose = import_nose() | |
1054 return nose.tools.assert_raises(*args,**kwargs) | |
1055 | |
1056 | |
1057 assert_raises_regex_impl = None | |
1058 | |
1059 | |
1060 def assert_raises_regex(exception_class, expected_regexp, | |
1061 callable_obj=None, *args, **kwargs): | |
1062 """ | |
1063 Fail unless an exception of class exception_class and with message that | |
1064 matches expected_regexp is thrown by callable when invoked with arguments | |
1065 args and keyword arguments kwargs. | |
1066 | |
1067 Name of this function adheres to Python 3.2+ reference, but should work in | |
1068 all versions down to 2.6. | |
1069 | |
1070 """ | |
1071 nose = import_nose() | |
1072 | |
1073 global assert_raises_regex_impl | |
1074 if assert_raises_regex_impl is None: | |
1075 try: | |
1076 # Python 3.2+ | |
1077 assert_raises_regex_impl = nose.tools.assert_raises_regex | |
1078 except AttributeError: | |
1079 try: | |
1080 # 2.7+ | |
1081 assert_raises_regex_impl = nose.tools.assert_raises_regexp | |
1082 except AttributeError: | |
1083 # 2.6 | |
1084 | |
1085 # This class is copied from Python2.7 stdlib almost verbatim | |
1086 class _AssertRaisesContext(object): | |
1087 """A context manager used to implement TestCase.assertRaises* methods.""" | |
1088 | |
1089 def __init__(self, expected, expected_regexp=None): | |
1090 self.expected = expected | |
1091 self.expected_regexp = expected_regexp | |
1092 | |
1093 def failureException(self, msg): | |
1094 return AssertionError(msg) | |
1095 | |
1096 def __enter__(self): | |
1097 return self | |
1098 | |
1099 def __exit__(self, exc_type, exc_value, tb): | |
1100 if exc_type is None: | |
1101 try: | |
1102 exc_name = self.expected.__name__ | |
1103 except AttributeError: | |
1104 exc_name = str(self.expected) | |
1105 raise self.failureException( | |
1106 "{0} not raised".format(exc_name)) | |
1107 if not issubclass(exc_type, self.expected): | |
1108 # let unexpected exceptions pass through | |
1109 return False | |
1110 self.exception = exc_value # store for later retrieval | |
1111 if self.expected_regexp is None: | |
1112 return True | |
1113 | |
1114 expected_regexp = self.expected_regexp | |
1115 if isinstance(expected_regexp, basestring): | |
1116 expected_regexp = re.compile(expected_regexp) | |
1117 if not expected_regexp.search(str(exc_value)): | |
1118 raise self.failureException( | |
1119 '"%s" does not match "%s"' % | |
1120 (expected_regexp.pattern, str(exc_value))) | |
1121 return True | |
1122 | |
1123 def impl(cls, regex, callable_obj, *a, **kw): | |
1124 mgr = _AssertRaisesContext(cls, regex) | |
1125 if callable_obj is None: | |
1126 return mgr | |
1127 with mgr: | |
1128 callable_obj(*a, **kw) | |
1129 assert_raises_regex_impl = impl | |
1130 | |
1131 return assert_raises_regex_impl(exception_class, expected_regexp, | |
1132 callable_obj, *args, **kwargs) | |
1133 | |
1134 | |
1135 def decorate_methods(cls, decorator, testmatch=None): | |
1136 """ | |
1137 Apply a decorator to all methods in a class matching a regular expression. | |
1138 | |
1139 The given decorator is applied to all public methods of `cls` that are | |
1140 matched by the regular expression `testmatch` | |
1141 (``testmatch.search(methodname)``). Methods that are private, i.e. start | |
1142 with an underscore, are ignored. | |
1143 | |
1144 Parameters | |
1145 ---------- | |
1146 cls : class | |
1147 Class whose methods to decorate. | |
1148 decorator : function | |
1149 Decorator to apply to methods | |
1150 testmatch : compiled regexp or str, optional | |
1151 The regular expression. Default value is None, in which case the | |
1152 nose default (``re.compile(r'(?:^|[\\b_\\.%s-])[Tt]est' % os.sep)``) | |
1153 is used. | |
1154 If `testmatch` is a string, it is compiled to a regular expression | |
1155 first. | |
1156 | |
1157 """ | |
1158 if testmatch is None: | |
1159 testmatch = re.compile(r'(?:^|[\\b_\\.%s-])[Tt]est' % os.sep) | |
1160 else: | |
1161 testmatch = re.compile(testmatch) | |
1162 cls_attr = cls.__dict__ | |
1163 | |
1164 # delayed import to reduce startup time | |
1165 from inspect import isfunction | |
1166 | |
1167 methods = [_m for _m in cls_attr.values() if isfunction(_m)] | |
1168 for function in methods: | |
1169 try: | |
1170 if hasattr(function, 'compat_func_name'): | |
1171 funcname = function.compat_func_name | |
1172 else: | |
1173 funcname = function.__name__ | |
1174 except AttributeError: | |
1175 # not a function | |
1176 continue | |
1177 if testmatch.search(funcname) and not funcname.startswith('_'): | |
1178 setattr(cls, funcname, decorator(function)) | |
1179 return | |
1180 | |
1181 | |
1182 def measure(code_str,times=1,label=None): | |
1183 """ | |
1184 Return elapsed time for executing code in the namespace of the caller. | |
1185 | |
1186 The supplied code string is compiled with the Python builtin ``compile``. | |
1187 The precision of the timing is 10 milli-seconds. If the code will execute | |
1188 fast on this timescale, it can be executed many times to get reasonable | |
1189 timing accuracy. | |
1190 | |
1191 Parameters | |
1192 ---------- | |
1193 code_str : str | |
1194 The code to be timed. | |
1195 times : int, optional | |
1196 The number of times the code is executed. Default is 1. The code is | |
1197 only compiled once. | |
1198 label : str, optional | |
1199 A label to identify `code_str` with. This is passed into ``compile`` | |
1200 as the second argument (for run-time error messages). | |
1201 | |
1202 Returns | |
1203 ------- | |
1204 elapsed : float | |
1205 Total elapsed time in seconds for executing `code_str` `times` times. | |
1206 | |
1207 Examples | |
1208 -------- | |
1209 >>> etime = np.testing.measure('for i in range(1000): np.sqrt(i**2)', | |
1210 ... times=times) | |
1211 >>> print "Time for a single execution : ", etime / times, "s" | |
1212 Time for a single execution : 0.005 s | |
1213 | |
1214 """ | |
1215 frame = sys._getframe(1) | |
1216 locs, globs = frame.f_locals, frame.f_globals | |
1217 | |
1218 code = compile(code_str, | |
1219 'Test name: %s ' % label, | |
1220 'exec') | |
1221 i = 0 | |
1222 elapsed = jiffies() | |
1223 while i < times: | |
1224 i += 1 | |
1225 exec(code, globs, locs) | |
1226 elapsed = jiffies() - elapsed | |
1227 return 0.01*elapsed | |
1228 | |
1229 def _assert_valid_refcount(op): | |
1230 """ | |
1231 Check that ufuncs don't mishandle refcount of object `1`. | |
1232 Used in a few regression tests. | |
1233 """ | |
1234 import numpy as np | |
1235 a = np.arange(100 * 100) | |
1236 b = np.arange(100*100).reshape(100, 100) | |
1237 c = b | |
1238 | |
1239 i = 1 | |
1240 | |
1241 rc = sys.getrefcount(i) | |
1242 for j in range(15): | |
1243 d = op(b, c) | |
1244 | |
1245 assert_(sys.getrefcount(i) >= rc) | |
1246 | |
1247 def assert_allclose(actual, desired, rtol=1e-7, atol=0, | |
1248 err_msg='', verbose=True): | |
1249 """ | |
1250 Raises an AssertionError if two objects are not equal up to desired | |
1251 tolerance. | |
1252 | |
1253 The test is equivalent to ``allclose(actual, desired, rtol, atol)``. | |
1254 It compares the difference between `actual` and `desired` to | |
1255 ``atol + rtol * abs(desired)``. | |
1256 | |
1257 .. versionadded:: 1.5.0 | |
1258 | |
1259 Parameters | |
1260 ---------- | |
1261 actual : array_like | |
1262 Array obtained. | |
1263 desired : array_like | |
1264 Array desired. | |
1265 rtol : float, optional | |
1266 Relative tolerance. | |
1267 atol : float, optional | |
1268 Absolute tolerance. | |
1269 err_msg : str, optional | |
1270 The error message to be printed in case of failure. | |
1271 verbose : bool, optional | |
1272 If True, the conflicting values are appended to the error message. | |
1273 | |
1274 Raises | |
1275 ------ | |
1276 AssertionError | |
1277 If actual and desired are not equal up to specified precision. | |
1278 | |
1279 See Also | |
1280 -------- | |
1281 assert_array_almost_equal_nulp, assert_array_max_ulp | |
1282 | |
1283 Examples | |
1284 -------- | |
1285 >>> x = [1e-5, 1e-3, 1e-1] | |
1286 >>> y = np.arccos(np.cos(x)) | |
1287 >>> assert_allclose(x, y, rtol=1e-5, atol=0) | |
1288 | |
1289 """ | |
1290 import numpy as np | |
1291 def compare(x, y): | |
1292 return np.allclose(x, y, rtol=rtol, atol=atol) | |
1293 | |
1294 actual, desired = np.asanyarray(actual), np.asanyarray(desired) | |
1295 header = 'Not equal to tolerance rtol=%g, atol=%g' % (rtol, atol) | |
1296 assert_array_compare(compare, actual, desired, err_msg=str(err_msg), | |
1297 verbose=verbose, header=header) | |
1298 | |
1299 def assert_array_almost_equal_nulp(x, y, nulp=1): | |
1300 """ | |
1301 Compare two arrays relatively to their spacing. | |
1302 | |
1303 This is a relatively robust method to compare two arrays whose amplitude | |
1304 is variable. | |
1305 | |
1306 Parameters | |
1307 ---------- | |
1308 x, y : array_like | |
1309 Input arrays. | |
1310 nulp : int, optional | |
1311 The maximum number of unit in the last place for tolerance (see Notes). | |
1312 Default is 1. | |
1313 | |
1314 Returns | |
1315 ------- | |
1316 None | |
1317 | |
1318 Raises | |
1319 ------ | |
1320 AssertionError | |
1321 If the spacing between `x` and `y` for one or more elements is larger | |
1322 than `nulp`. | |
1323 | |
1324 See Also | |
1325 -------- | |
1326 assert_array_max_ulp : Check that all items of arrays differ in at most | |
1327 N Units in the Last Place. | |
1328 spacing : Return the distance between x and the nearest adjacent number. | |
1329 | |
1330 Notes | |
1331 ----- | |
1332 An assertion is raised if the following condition is not met:: | |
1333 | |
1334 abs(x - y) <= nulps * spacing(max(abs(x), abs(y))) | |
1335 | |
1336 Examples | |
1337 -------- | |
1338 >>> x = np.array([1., 1e-10, 1e-20]) | |
1339 >>> eps = np.finfo(x.dtype).eps | |
1340 >>> np.testing.assert_array_almost_equal_nulp(x, x*eps/2 + x) | |
1341 | |
1342 >>> np.testing.assert_array_almost_equal_nulp(x, x*eps + x) | |
1343 Traceback (most recent call last): | |
1344 ... | |
1345 AssertionError: X and Y are not equal to 1 ULP (max is 2) | |
1346 | |
1347 """ | |
1348 import numpy as np | |
1349 ax = np.abs(x) | |
1350 ay = np.abs(y) | |
1351 ref = nulp * np.spacing(np.where(ax > ay, ax, ay)) | |
1352 if not np.all(np.abs(x-y) <= ref): | |
1353 if np.iscomplexobj(x) or np.iscomplexobj(y): | |
1354 msg = "X and Y are not equal to %d ULP" % nulp | |
1355 else: | |
1356 max_nulp = np.max(nulp_diff(x, y)) | |
1357 msg = "X and Y are not equal to %d ULP (max is %g)" % (nulp, max_nulp) | |
1358 raise AssertionError(msg) | |
1359 | |
1360 def assert_array_max_ulp(a, b, maxulp=1, dtype=None): | |
1361 """ | |
1362 Check that all items of arrays differ in at most N Units in the Last Place. | |
1363 | |
1364 Parameters | |
1365 ---------- | |
1366 a, b : array_like | |
1367 Input arrays to be compared. | |
1368 maxulp : int, optional | |
1369 The maximum number of units in the last place that elements of `a` and | |
1370 `b` can differ. Default is 1. | |
1371 dtype : dtype, optional | |
1372 Data-type to convert `a` and `b` to if given. Default is None. | |
1373 | |
1374 Returns | |
1375 ------- | |
1376 ret : ndarray | |
1377 Array containing number of representable floating point numbers between | |
1378 items in `a` and `b`. | |
1379 | |
1380 Raises | |
1381 ------ | |
1382 AssertionError | |
1383 If one or more elements differ by more than `maxulp`. | |
1384 | |
1385 See Also | |
1386 -------- | |
1387 assert_array_almost_equal_nulp : Compare two arrays relatively to their | |
1388 spacing. | |
1389 | |
1390 Examples | |
1391 -------- | |
1392 >>> a = np.linspace(0., 1., 100) | |
1393 >>> res = np.testing.assert_array_max_ulp(a, np.arcsin(np.sin(a))) | |
1394 | |
1395 """ | |
1396 import numpy as np | |
1397 ret = nulp_diff(a, b, dtype) | |
1398 if not np.all(ret <= maxulp): | |
1399 raise AssertionError("Arrays are not almost equal up to %g ULP" % \ | |
1400 maxulp) | |
1401 return ret | |
1402 | |
1403 def nulp_diff(x, y, dtype=None): | |
1404 """For each item in x and y, return the number of representable floating | |
1405 points between them. | |
1406 | |
1407 Parameters | |
1408 ---------- | |
1409 x : array_like | |
1410 first input array | |
1411 y : array_like | |
1412 second input array | |
1413 | |
1414 Returns | |
1415 ------- | |
1416 nulp : array_like | |
1417 number of representable floating point numbers between each item in x | |
1418 and y. | |
1419 | |
1420 Examples | |
1421 -------- | |
1422 # By definition, epsilon is the smallest number such as 1 + eps != 1, so | |
1423 # there should be exactly one ULP between 1 and 1 + eps | |
1424 >>> nulp_diff(1, 1 + np.finfo(x.dtype).eps) | |
1425 1.0 | |
1426 """ | |
1427 import numpy as np | |
1428 if dtype: | |
1429 x = np.array(x, dtype=dtype) | |
1430 y = np.array(y, dtype=dtype) | |
1431 else: | |
1432 x = np.array(x) | |
1433 y = np.array(y) | |
1434 | |
1435 t = np.common_type(x, y) | |
1436 if np.iscomplexobj(x) or np.iscomplexobj(y): | |
1437 raise NotImplementedError("_nulp not implemented for complex array") | |
1438 | |
1439 x = np.array(x, dtype=t) | |
1440 y = np.array(y, dtype=t) | |
1441 | |
1442 if not x.shape == y.shape: | |
1443 raise ValueError("x and y do not have the same shape: %s - %s" % \ | |
1444 (x.shape, y.shape)) | |
1445 | |
1446 def _diff(rx, ry, vdt): | |
1447 diff = np.array(rx-ry, dtype=vdt) | |
1448 return np.abs(diff) | |
1449 | |
1450 rx = integer_repr(x) | |
1451 ry = integer_repr(y) | |
1452 return _diff(rx, ry, t) | |
1453 | |
1454 def _integer_repr(x, vdt, comp): | |
1455 # Reinterpret binary representation of the float as sign-magnitude: | |
1456 # take into account two-complement representation | |
1457 # See also | |
1458 # http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm | |
1459 rx = x.view(vdt) | |
1460 if not (rx.size == 1): | |
1461 rx[rx < 0] = comp - rx[rx<0] | |
1462 else: | |
1463 if rx < 0: | |
1464 rx = comp - rx | |
1465 | |
1466 return rx | |
1467 | |
1468 def integer_repr(x): | |
1469 """Return the signed-magnitude interpretation of the binary representation of | |
1470 x.""" | |
1471 import numpy as np | |
1472 if x.dtype == np.float32: | |
1473 return _integer_repr(x, np.int32, np.int32(-2**31)) | |
1474 elif x.dtype == np.float64: | |
1475 return _integer_repr(x, np.int64, np.int64(-2**63)) | |
1476 else: | |
1477 raise ValueError("Unsupported dtype %s" % x.dtype) | |
1478 | |
1479 # The following two classes are copied from python 2.6 warnings module (context | |
1480 # manager) | |
1481 class WarningMessage(object): | |
1482 | |
1483 """ | |
1484 Holds the result of a single showwarning() call. | |
1485 | |
1486 Deprecated in 1.8.0 | |
1487 | |
1488 Notes | |
1489 ----- | |
1490 `WarningMessage` is copied from the Python 2.6 warnings module, | |
1491 so it can be used in NumPy with older Python versions. | |
1492 | |
1493 """ | |
1494 | |
1495 _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file", | |
1496 "line") | |
1497 | |
1498 def __init__(self, message, category, filename, lineno, file=None, | |
1499 line=None): | |
1500 local_values = locals() | |
1501 for attr in self._WARNING_DETAILS: | |
1502 setattr(self, attr, local_values[attr]) | |
1503 if category: | |
1504 self._category_name = category.__name__ | |
1505 else: | |
1506 self._category_name = None | |
1507 | |
1508 def __str__(self): | |
1509 return ("{message : %r, category : %r, filename : %r, lineno : %s, " | |
1510 "line : %r}" % (self.message, self._category_name, | |
1511 self.filename, self.lineno, self.line)) | |
1512 | |
1513 class WarningManager(object): | |
1514 """ | |
1515 A context manager that copies and restores the warnings filter upon | |
1516 exiting the context. | |
1517 | |
1518 The 'record' argument specifies whether warnings should be captured by a | |
1519 custom implementation of ``warnings.showwarning()`` and be appended to a | |
1520 list returned by the context manager. Otherwise None is returned by the | |
1521 context manager. The objects appended to the list are arguments whose | |
1522 attributes mirror the arguments to ``showwarning()``. | |
1523 | |
1524 The 'module' argument is to specify an alternative module to the module | |
1525 named 'warnings' and imported under that name. This argument is only useful | |
1526 when testing the warnings module itself. | |
1527 | |
1528 Deprecated in 1.8.0 | |
1529 | |
1530 Notes | |
1531 ----- | |
1532 `WarningManager` is a copy of the ``catch_warnings`` context manager | |
1533 from the Python 2.6 warnings module, with slight modifications. | |
1534 It is copied so it can be used in NumPy with older Python versions. | |
1535 | |
1536 """ | |
1537 def __init__(self, record=False, module=None): | |
1538 self._record = record | |
1539 if module is None: | |
1540 self._module = sys.modules['warnings'] | |
1541 else: | |
1542 self._module = module | |
1543 self._entered = False | |
1544 | |
1545 def __enter__(self): | |
1546 if self._entered: | |
1547 raise RuntimeError("Cannot enter %r twice" % self) | |
1548 self._entered = True | |
1549 self._filters = self._module.filters | |
1550 self._module.filters = self._filters[:] | |
1551 self._showwarning = self._module.showwarning | |
1552 if self._record: | |
1553 log = [] | |
1554 def showwarning(*args, **kwargs): | |
1555 log.append(WarningMessage(*args, **kwargs)) | |
1556 self._module.showwarning = showwarning | |
1557 return log | |
1558 else: | |
1559 return None | |
1560 | |
1561 def __exit__(self): | |
1562 if not self._entered: | |
1563 raise RuntimeError("Cannot exit %r without entering first" % self) | |
1564 self._module.filters = self._filters | |
1565 self._module.showwarning = self._showwarning | |
1566 | |
1567 | |
1568 def assert_warns(warning_class, func, *args, **kw): | |
1569 """ | |
1570 Fail unless the given callable throws the specified warning. | |
1571 | |
1572 A warning of class warning_class should be thrown by the callable when | |
1573 invoked with arguments args and keyword arguments kwargs. | |
1574 If a different type of warning is thrown, it will not be caught, and the | |
1575 test case will be deemed to have suffered an error. | |
1576 | |
1577 .. versionadded:: 1.4.0 | |
1578 | |
1579 Parameters | |
1580 ---------- | |
1581 warning_class : class | |
1582 The class defining the warning that `func` is expected to throw. | |
1583 func : callable | |
1584 The callable to test. | |
1585 \\*args : Arguments | |
1586 Arguments passed to `func`. | |
1587 \\*\\*kwargs : Kwargs | |
1588 Keyword arguments passed to `func`. | |
1589 | |
1590 Returns | |
1591 ------- | |
1592 The value returned by `func`. | |
1593 | |
1594 """ | |
1595 with warnings.catch_warnings(record=True) as l: | |
1596 warnings.simplefilter('always') | |
1597 result = func(*args, **kw) | |
1598 if not len(l) > 0: | |
1599 raise AssertionError("No warning raised when calling %s" | |
1600 % func.__name__) | |
1601 if not l[0].category is warning_class: | |
1602 raise AssertionError("First warning for %s is not a " \ | |
1603 "%s( is %s)" % (func.__name__, warning_class, l[0])) | |
1604 return result | |
1605 | |
1606 def assert_no_warnings(func, *args, **kw): | |
1607 """ | |
1608 Fail if the given callable produces any warnings. | |
1609 | |
1610 .. versionadded:: 1.7.0 | |
1611 | |
1612 Parameters | |
1613 ---------- | |
1614 func : callable | |
1615 The callable to test. | |
1616 \\*args : Arguments | |
1617 Arguments passed to `func`. | |
1618 \\*\\*kwargs : Kwargs | |
1619 Keyword arguments passed to `func`. | |
1620 | |
1621 Returns | |
1622 ------- | |
1623 The value returned by `func`. | |
1624 | |
1625 """ | |
1626 with warnings.catch_warnings(record=True) as l: | |
1627 warnings.simplefilter('always') | |
1628 result = func(*args, **kw) | |
1629 if len(l) > 0: | |
1630 raise AssertionError("Got warnings when calling %s: %s" | |
1631 % (func.__name__, l)) | |
1632 return result | |
1633 | |
1634 | |
1635 def _gen_alignment_data(dtype=float32, type='binary', max_size=24): | |
1636 """ | |
1637 generator producing data with different alignment and offsets | |
1638 to test simd vectorization | |
1639 | |
1640 Parameters | |
1641 ---------- | |
1642 dtype : dtype | |
1643 data type to produce | |
1644 type : string | |
1645 'unary': create data for unary operations, creates one input | |
1646 and output array | |
1647 'binary': create data for unary operations, creates two input | |
1648 and output array | |
1649 max_size : integer | |
1650 maximum size of data to produce | |
1651 | |
1652 Returns | |
1653 ------- | |
1654 if type is 'unary' yields one output, one input array and a message | |
1655 containing information on the data | |
1656 if type is 'binary' yields one output array, two input array and a message | |
1657 containing information on the data | |
1658 | |
1659 """ | |
1660 ufmt = 'unary offset=(%d, %d), size=%d, dtype=%r, %s' | |
1661 bfmt = 'binary offset=(%d, %d, %d), size=%d, dtype=%r, %s' | |
1662 for o in range(3): | |
1663 for s in range(o + 2, max(o + 3, max_size)): | |
1664 if type == 'unary': | |
1665 inp = lambda : arange(s, dtype=dtype)[o:] | |
1666 out = empty((s,), dtype=dtype)[o:] | |
1667 yield out, inp(), ufmt % (o, o, s, dtype, 'out of place') | |
1668 yield inp(), inp(), ufmt % (o, o, s, dtype, 'in place') | |
1669 yield out[1:], inp()[:-1], ufmt % \ | |
1670 (o + 1, o, s - 1, dtype, 'out of place') | |
1671 yield out[:-1], inp()[1:], ufmt % \ | |
1672 (o, o + 1, s - 1, dtype, 'out of place') | |
1673 yield inp()[:-1], inp()[1:], ufmt % \ | |
1674 (o, o + 1, s - 1, dtype, 'aliased') | |
1675 yield inp()[1:], inp()[:-1], ufmt % \ | |
1676 (o + 1, o, s - 1, dtype, 'aliased') | |
1677 if type == 'binary': | |
1678 inp1 = lambda :arange(s, dtype=dtype)[o:] | |
1679 inp2 = lambda :arange(s, dtype=dtype)[o:] | |
1680 out = empty((s,), dtype=dtype)[o:] | |
1681 yield out, inp1(), inp2(), bfmt % \ | |
1682 (o, o, o, s, dtype, 'out of place') | |
1683 yield inp1(), inp1(), inp2(), bfmt % \ | |
1684 (o, o, o, s, dtype, 'in place1') | |
1685 yield inp2(), inp1(), inp2(), bfmt % \ | |
1686 (o, o, o, s, dtype, 'in place2') | |
1687 yield out[1:], inp1()[:-1], inp2()[:-1], bfmt % \ | |
1688 (o + 1, o, o, s - 1, dtype, 'out of place') | |
1689 yield out[:-1], inp1()[1:], inp2()[:-1], bfmt % \ | |
1690 (o, o + 1, o, s - 1, dtype, 'out of place') | |
1691 yield out[:-1], inp1()[:-1], inp2()[1:], bfmt % \ | |
1692 (o, o, o + 1, s - 1, dtype, 'out of place') | |
1693 yield inp1()[1:], inp1()[:-1], inp2()[:-1], bfmt % \ | |
1694 (o + 1, o, o, s - 1, dtype, 'aliased') | |
1695 yield inp1()[:-1], inp1()[1:], inp2()[:-1], bfmt % \ | |
1696 (o, o + 1, o, s - 1, dtype, 'aliased') | |
1697 yield inp1()[:-1], inp1()[:-1], inp2()[1:], bfmt % \ | |
1698 (o, o, o + 1, s - 1, dtype, 'aliased') | |
1699 | |
1700 | |
1701 class IgnoreException(Exception): | |
1702 "Ignoring this exception due to disabled feature" | |
1703 | |
1704 | |
1705 @contextlib.contextmanager | |
1706 def tempdir(*args, **kwargs): | |
1707 """Context manager to provide a temporary test folder. | |
1708 | |
1709 All arguments are passed as this to the underlying tempfile.mkdtemp | |
1710 function. | |
1711 | |
1712 """ | |
1713 tmpdir = mkdtemp(*args, **kwargs) | |
1714 yield tmpdir | |
1715 shutil.rmtree(tmpdir) |