Astropy: `quantity_allclose` difference to numpy `allclose`

Created on 18 Oct 2020  路  3Comments  路  Source: astropy/astropy

Description

For certain values, astropy.units.allclose does not match numpy.allclose

Expected behavior

The I/O to be the same, excepting unit considerations.

Actual behavior

When comparing two numbers where the first array has elements very close to 0 and the second array is all zeros, numpy allclose works as expected, but units.allclose returns False, regardless of "rtol"

Steps to Reproduce

>>> import numpy as np
>>> np.allclose([1e-17, 0, 0], [0, 0, 0], rtol=1e-5)
True
>>> import astropy.units as u
>>> u.allclose([1e-17, 0, 0] * u.m, [0, 0, 0] * u.m, rtol=1e-5)
False

System Details

macOS-10.15.7-x86_64-i386-64bit
Python 3.8.2 | packaged by conda-forge | (default, Apr 24 2020, 07:56:27)
[Clang 9.0.1 ]
Numpy 1.18.4
astropy 4.2.dev877+g4eef52a1c
Scipy 1.4.1
Matplotlib 3.2.1

Close? question units

Most helpful comment

This isn't actually a bug, but a conceptual difference between how allclose can operate on unit-less and unit-ful input. As the docstring of numpy.allclose notes:

If the following equation is element-wise True, then allclose returns True.
absolute(a - b) <= (atol + rtol * absolute(b))

In numpy.allclose, atol=1e-8 (by default) because there can be a truly absolute comparison without having to scale the inputs. In the case of astropy.units.allclose, there is no natural way to set atol because it will depend on units. If you look at the call signatures of the two functions, you'll see that atol=None in astropy.units.allclose. If you set atol in the units case, you get the same results:

>>> u.allclose([1e-17, 0, 0] * u.m, [0, 0, 0] * u.m, rtol=1e-5, atol=1e-8*u.m)
True

All 3 comments

This isn't actually a bug, but a conceptual difference between how allclose can operate on unit-less and unit-ful input. As the docstring of numpy.allclose notes:

If the following equation is element-wise True, then allclose returns True.
absolute(a - b) <= (atol + rtol * absolute(b))

In numpy.allclose, atol=1e-8 (by default) because there can be a truly absolute comparison without having to scale the inputs. In the case of astropy.units.allclose, there is no natural way to set atol because it will depend on units. If you look at the call signatures of the two functions, you'll see that atol=None in astropy.units.allclose. If you set atol in the units case, you get the same results:

>>> u.allclose([1e-17, 0, 0] * u.m, [0, 0, 0] * u.m, rtol=1e-5, atol=1e-8*u.m)
True

@nstarman Would it have helped you if there was an explicit note about this in the docstring of astropy.units.allclose?

That would be very useful. The explanation you wrote above would've been perfect.

Was this page helpful?
0 / 5 - 0 ratings