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

numpy arange unsupported #484

Open
willprice opened this issue Mar 2, 2017 · 8 comments
Open

numpy arange unsupported #484

willprice opened this issue Mar 2, 2017 · 8 comments
Labels
enhancement numpy Numpy related bug/enhancement

Comments

@willprice
Copy link

Versions:

  • python: v3.6.0
  • numpy: v1.12.0
  • pint: 0.8.dev0 (commit de8fdff)
import numpy as np
import pint
ureg = pint.UnitRegistry()
x = 1 * ureg.meter

y = np.arange(0, x, 0.1)

Results in:

Traceback (most recent call last):
  File "pint_test.py", line 7, in <module>
    y = np.arange(0, x, 0.1)
  File "/home/will/src/pint/pint/quantity.py", line 431, in __float__
    raise DimensionalityError(self._units, 'dimensionless')
pint.errors.DimensionalityError: Cannot convert from 'meter' to 'dimensionless'

Since one can do np.linspace(0, x, 10) without problems I think this is a bug, although I may be misunderstanding and this may be an implication of the stated numpy support

@hgrecco
Copy link
Owner

hgrecco commented Mar 31, 2017

The correct way would be:

y = np.arange(0, 1 * ureg.meter, 0.1 * ureg.meter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: setting an array element with a sequence.

However, this fails (with a different error). The reason is that linspace is implemented internally by numpy as a python function with additions and multiplications. arange is implemented in C and it does not "properly" dispatch to Pint Quantity methods.

@masasin
Copy link

masasin commented Jun 13, 2017

Something like np.array([1 * ureg.meter, 0.1 * ureg.meter]) also fails with that error. Is there any way to mitigate that?

@hgrecco
Copy link
Owner

hgrecco commented Jun 15, 2017

The problem is that there is no way to tell numpy that we will handle it. The suggested way is

[1, 0.1] * ureg.meter

@onealj
Copy link
Contributor

onealj commented Jun 15, 2017 via email

@impact27
Copy link
Contributor

I had the same problem and I had an idea:

The problem is that if the Quantity objects are ndarrays or similar (which numpy determines by calling __array_interface__), numpy will want to transform them to ndarray to do the computation. if they are just some other class, numpy will still work if the class implements arithmetics.

Therefore, by not responding to __array_*, numpy will create a range. This also allows to have a numpy array of Quantity. (with dtype object)

class myQ_(Q_):
    pass
    def __getattr__(self, item):
        if item == '__array_interface__' or item == '__array_struct__' or item == '__array__':
            raise AttributeError('Nope')

        # if item in self.__handled:
        if item in self._Quantity__handled:
            def fun(*args, **kwargs):
                uf = getattr(np, item)
                return uf(self.m, *args, **kwargs)
            fun.__name__ = item
            return functools.partial(self._Quantity__numpy_method_wrap, fun)
        return super().__getattr__(item)
    

A = myQ_(0, 's')
B = myQ_(1, 's')
C = myQ_(0.1, 's')
#%%
y = np.arange(A, B, C)

This code is not working for numpy functions taking more than 1 argument but I thought I would share it.

@thomaslima
Copy link

Just came across this issue while trying to convert a list of Quantities to a numpy array:

>>> from myproject import Q_
>>> a = Q_(1,'nm')
>>> import numpy as np
>>> np.array([a, a])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: setting an array element with a sequence.

@hgrecco
Copy link
Owner

hgrecco commented Dec 3, 2019

Revisit after #905

@jthielen
Copy link
Contributor

Currently, np.arange does not support overrides via __array_function__ (see numpy/numpy#12379), so this is still unresolved by #905.

However, in numpy/numpy#12379, there are comments to the effect that, in principal, np.arange should only be used with scalar integers. So, based on that, I would guess that usage with Quantities as arguments may need to be avoided, and instead something like the following used to achieve the desired behavior:

np.arange(0, 1, 0.1) * ureg.meter

@hgrecco hgrecco added the numpy Numpy related bug/enhancement label Dec 11, 2019
mocquin added a commit to mocquin/physipy that referenced this issue Oct 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement numpy Numpy related bug/enhancement
Projects
None yet
Development

No branches or pull requests

7 participants