Skip to content

Conversation

@astrofrog
Copy link
Member

The current behavior of multiplying arrays with quantities is inconsistent:

In [4]: (3. * u.m) * np.array([1,2,3])
Out[4]: <Quantity [ 3.  6.  9.] m>

In [5]: np.array([1,2,3]) * (3. * u.m)
WARNING: Converting Quantity object in units 'm' to a Numpy array [astropy.units.quantity]
Out[5]: array([ 3.,  6.,  9.])

the first behavior is correct. The problem is that the Quantity class needs __array_priority__ to be set like Unit has, and this PR does this.

However, note that this doesn't yet work, because it seems that the __array__ method takes precedence over even checking __array_priority__. I'll look into it a bit more, but if anyone has any ideas, please let me know!

… when the array is the left hand side operand (this does not work yet, because Quantity also has an __array__ method which appears to take precedence).
@astrofrog
Copy link
Member Author

I've reported this as a possible issue on Numpy: numpy/numpy#3164

@astrofrog
Copy link
Member Author

The only solution I can think of for now is to actually remove the __array__ method from Quantity - so users would have to explicitly do:

np.array(q.value)

but at least that won't raise a warning, so maybe it's not such a bad thing?

@astrofrog
Copy link
Member Author

Removing __array__ does work, but this produces an array with a single quantity object inside. Arguably, that's less bad than having array * q give something different from q * array. What do others think?

@embray
Copy link
Member

embray commented Mar 22, 2013

I don't understand--what's the point of __array_priority__ if it isn't even checked before __array__?

@astrofrog
Copy link
Member Author

@iguananaut - __array_priority__ is useful if __array__ is not defined because if you do something like array * object, if you set __array_priority__ high enough, it's object.__rmul__ that will be called, not array.__mul__, which means you can control the result (that's how np.array([1,2,3]) * u.m works). But I think it's a bug that __array_priority__ is not respected if __array__ is present...

@embray
Copy link
Member

embray commented Mar 22, 2013

Ah, I understand now. Hm. That's annoying. Will have to think on this a bit.

@taldcroft
Copy link
Member

Apologies for ignorance of the design history of Quantity, but was there ever serious consideration given to subclassing ndarray instead of using a container class? The Column class (which subclasses ndarray) doesn't have the commutativity problem. Anyway, just throwing this out there. 😼

In [15]: c = Column(data=[1,2,3], name='c')

In [16]: c
Out[16]: 
<Column name='c' units=None format=None description=None>
array([1, 2, 3])

In [17]: c * np.array([1, 2, 3])
Out[17]: 
<Column name='c' units=None format=None description=None>
array([1, 4, 9])

In [18]: np.array([1, 2, 3]) * c
Out[18]: 
<Column name='c' units=None format=None description=None>
array([1, 4, 9])

@astrofrog
Copy link
Member Author

@taldcroft - Quantity was first designed as a scalar class, so array support was added later. Could we still support scalar values if we sub-classed from arrays?

@embray
Copy link
Member

embray commented Mar 27, 2013

I think we could do that so long as Quantity can be an array-scalar (curse Numpy for even coming up with such a concept ;)

@taldcroft
Copy link
Member

Even though the array scalar has caused me many pains, now that I'm used to it I have a grudging respect. I think there would be just be some different problems if there were no array scalar.

For the purposes of Quantity and the possibility of subclassing ndarray, here is what Column does now:

In [56]: c = Column(data=[1,2])

In [57]: c
Out[57]: 
<Column name=None units=None format=None description=None>
array([1, 2])

In [58]: c[1]
Out[58]: 2

In [59]: type(c[1])
Out[59]: numpy.int64

So there is an array scalar that comes out, but it lost its Column-ness. If I recall that was on purpose, but for Quantity obviously the array scalar still needs to be a Quantity.

Something I have lurking in the back of my mind always is integrating Quantity and Table Columns. You should be able to have a Table column act like a quantity. But honestly I don't quite know how to make this work nicely.

@embray
Copy link
Member

embray commented Mar 29, 2013

@taldcroft I agree--eventually these concepts need to start coming together more cohesively, with nddata in the mix too.

@astrofrog
Copy link
Member Author

See #929 for the start of an implementation in which Quantity is an ndarray sub-class.

@astrofrog
Copy link
Member Author

Fixed in #929!

In [4]: (3. * u.m) * np.array([1,2,3])
Out[4]: <Quantity [ 3.  6.  9.] m>

In [5]: np.array([1,2,3]) * (3. * u.m)
Out[5]: <Quantity [ 3.  6.  9.] m>
``

@astrofrog astrofrog closed this Jul 25, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants