Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling np.sqrt on a pint quantity has a side effect on the pint quantity #622

Closed
abrahamneben opened this issue Mar 15, 2018 · 4 comments
Closed
Labels
numpy Numpy related bug/enhancement

Comments

@abrahamneben
Copy link

abrahamneben commented Mar 15, 2018

Strange numpy/pint interaction. When I call np.sqrt on a pint quantity, it has the side effect of changing the type of the object in the pint quantity. When I use **(1/2) instead of np.sqrt, this doesn't happen.

>>> import numpy as np
>>> import pint
>>> units = pint.UnitRegistry()

>>> a = 1*units.m
>>> print(type(a.m))
<class 'int'>

>>> np.sqrt(a) # has the side effect of changing the type of a.m

print(type(a.m))
<class 'numpy.ndarray'>
>>> import numpy as np
>>> import pint
>>> units = pint.UnitRegistry()

>>> a = 1*units.m
>>> print(type(a.m))
<class 'int'>

>>> a**(1/2) # no side effects

print(type(a.m))
<class 'int'>
@abrahamneben abrahamneben changed the title Strange numpy sqrt side effects on pint quantity Calling np.sqrt on a pint quantity has a side effect on the pint quantity Mar 15, 2018
@hgrecco
Copy link
Owner

hgrecco commented Mar 23, 2018

Yes. This is true not only for Pint but for everything:

>>> import numpy as np
>>> type(np.sqrt(4))
<class 'numpy.float64'>

While it looks unexpected, it is actually what numpy does

@dopplershift
Copy link
Contributor

The issue isn't changing data type between source and result. The issue is that a**(1/2) returns a new result, but for some reason the original a is modified in-place. I've found that weird as well.

@raphaeltimbo
Copy link
Contributor

raphaeltimbo commented May 5, 2018

This is also described in issue #509.

I believe it could be something related to this part of the code:

pint/pint/quantity.py

Lines 1341 to 1345 in 0c4a950

else:
# If an `__array_` attributes is requested but the magnitude is not an ndarray,
# we convert the magnitude to a numpy ndarray.
self._magnitude = _to_magnitude(self._magnitude, force_ndarray=True)
return getattr(self._magnitude, item)

Maybe this conversion could be done only when the magnitude is iterable?
Or maybe the magnitude could be an np.array right from the beggining (when the quantity is instantiated)?

@hgrecco
Copy link
Owner

hgrecco commented Dec 24, 2019

I am closing this as it is taken care by #925

@hgrecco hgrecco closed this as completed Dec 24, 2019
bors bot added a commit that referenced this issue Dec 27, 2019
957: Add parameterized test for type immutability r=hgrecco a=jthielen

As discussed in #925, this adds a parameterized test to verify that the internal type is not mutated under common operations (as encountered in #399, #481, #509, #622, #678).

- [x] Closes #925, Closes #481
- [x] Executed ``black -t py36 . && isort -rc . && flake8`` with no errors
- [x] The change is fully covered by automated unit tests
- ~~Documented in docs/ as appropriate~~
- [x] Added an entry to the CHANGES file


Co-authored-by: Jon Thielen <github@jont.cc>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
numpy Numpy related bug/enhancement
Projects
None yet
Development

No branches or pull requests

4 participants