Skip to content

Conversation

@mhvk
Copy link
Contributor

@mhvk mhvk commented Jun 7, 2019

In numpy 1.17, a new __array_function__ protocol is being introduced that allows one to overwrite every function in numpy. This PR applies it to Quantity, so that things like np.contatenate(q1, q2) "just work"!

I think it is mostly complete, though (EDIT) I need to be a bit smarter about how to not support things like polynomials, financial functions, etc. functions in linalg, etc., are not yet included - those I'd like to do separately.

Have a look especially at test_quantity_non_ufuncs to see what now works.

One thing I've noticed so far is that this breaks straight plotting with quantities with different units for x and y (at least plt.scatter) since that internally tries to stick the 2 axes together. We may need to turn on quantity_support by default...

(EDIT, solved) There are also a number of failures in models - I'm hoping those are just smoking out minor bugs in the implementation, but haven't looked in detail yet.

fixes #1273, fixes #5842

@codecov
Copy link

codecov bot commented Jun 8, 2019

Codecov Report

Merging #8808 into master will decrease coverage by 0.32%.
The diff coverage is 28.69%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #8808      +/-   ##
==========================================
- Coverage   86.99%   86.66%   -0.33%     
==========================================
  Files         400      401       +1     
  Lines       59469    59803     +334     
  Branches     1100     1100              
==========================================
+ Hits        51736    51830      +94     
- Misses       7092     7332     +240     
  Partials      641      641
Impacted Files Coverage Δ
astropy/units/quantity_helper/__init__.py 100% <100%> (ø) ⬆️
astropy/modeling/projections.py 86.73% <100%> (ø) ⬆️
astropy/units/quantity.py 91.2% <18.18%> (-2.36%) ⬇️
astropy/units/quantity_helper/function_helpers.py 28.98% <28.98%> (ø)
astropy/samp/hub.py 77.38% <0%> (-0.14%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 41930f7...a2ba397. Read the comment docs.

@mhvk mhvk force-pushed the use-array-function branch 4 times, most recently from f083b61 to 80bd52e Compare June 9, 2019 13:32
Copy link
Member

@adrn adrn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 In general, this looks great - thanks @mhvk for the hard work! I did a preliminary review and didn't catch anything major, but will give this a more detailed look later today.

np.save, np.savez, np.savetxt, np.savez_compressed,
# Polynomials
np.poly, np.polyadd, np.polyder, np.polydiv, np.polyfit, np.polyint,
np.polymul, np.polysub, np.polyval, np.roots, np.vander,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bummer! Conceptually, it would be nice to have support for these -- e.g., polyfit(x, y) could return the coefficients with units (y.unit, y.unit/x.unit, y.unit/x.unit**2, ...etc) -- but many of these functions would require support for multiple / broadcasted units within the same array object first...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and similarly for cov below.

@mhvk
Copy link
Contributor Author

mhvk commented Jun 10, 2019

@adrn - thanks for the initial look!

I now also updated the docs, and think this is getting there.

The main issue that I see with this is that it breaks plotting, which means people either have to be very careful with using .value or .to_value(...) everywhere, or use quantity_support(). Unfortunately, it turns out the latter does not work quite correctly with plt.scatter - likely a matplotlib bug.

Note that in numpy 1.17 at least, it is still possible to turn off the whole overrides by setting an environment variable. Possibly, I should document that...

@mhvk mhvk force-pushed the use-array-function branch 2 times, most recently from 42374f5 to 35aabe6 Compare June 11, 2019 01:48
@mhvk
Copy link
Contributor Author

mhvk commented Jun 11, 2019

OK, plotting is solved (see #8818), though it is still the case that with this PR, it will become necessary to always use .value or turn on quantity_support().

@mhvk
Copy link
Contributor Author

mhvk commented Jun 11, 2019

p.s. One note: I am not yet including functions inside other modules (such as np.linalg) - prefer to leave that for a separate PR.

@bsipocz
Copy link
Member

bsipocz commented Jun 11, 2019

Very much off topic question, but shall we also drop numpy versions for v4.0? E.g. will it be 1.14+ based on the "last 4 releases" rule?

@mhvk
Copy link
Contributor Author

mhvk commented Jun 11, 2019

For a LTS release, it arguably makes sense to insist on a relatively recent numpy version. It might make some sense to exclude 1.14 as well, given that we have work-arounds even for different versions of 1.14; for reference, 1.15 will be a year old by then.

But overall, the work-arounds are all rather small - the only thing that might make a big difference is if we were to require >=1.16, which simplifies erfa and makes __array_function__ possible for all versions.

Anyway, probably best discussed elsewhere!

@bsipocz
Copy link
Member

bsipocz commented Jun 11, 2019

1.15 will be a year old by then.

1.5 year old. I'll open a new issue, but also put on the tentative agenda of the next dev telecon.

Copy link
Member

@adrn adrn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just had a much closer look at this PR, and it still looks to be in great shape! I had a few minor inline comments, but I think they will be very easy to address or discuss. I want to note to others that I did a fairly close read through the tests and didn't see any obvious holes, but this is big enough that it could use another set of eyes if anyone has time.

@mhvk
Copy link
Contributor Author

mhvk commented Jun 12, 2019

On the larger question of how to review this monster PR: I think we'll almost certainly need to get some experience with this. This is partially why I think it is good to have it in just after a release, so that our affiliated packages can play around with it well ahead of 4.0 (of course, numpy 1.17 still has to be released as well).

@bsipocz
Copy link
Member

bsipocz commented Jun 12, 2019

@mhvk - there are a few packages that are testing against astropy-dev. Afaik less against numpy-dev, but we also send out an e-mail to astropy-dev that they might want to consider adding that combination to their CI, preferable as a job that also runs from cron.

mhvk added 3 commits June 14, 2019 10:34
Creates a list of all functions that can be overridden with
__array_function__ and breaks them up into groups.

Add a few tests for coverage, many of which are currently failing.
Be more specific about numpy 1.17
@bsipocz
Copy link
Member

bsipocz commented Jun 18, 2019

I suppose this will also close #1273

@mhvk
Copy link
Contributor Author

mhvk commented Jun 19, 2019

I suppose this will also close #1273

Yes! 🎆 (and added to top so it auto-closes)

@bsipocz
Copy link
Member

bsipocz commented Jun 19, 2019

Would this also mean addressing #6897, or just laying ground works for it?

@bsipocz
Copy link
Member

bsipocz commented Jun 19, 2019

Would this also address #8610?

@bsipocz
Copy link
Member

bsipocz commented Jun 19, 2019

This will also fix #5842

@taldcroft
Copy link
Member

@mhvk - I don't have the time or courage to give this full review, but I skimmed the crux of the new functionality and it looks great. Just want to congratulate you and numpy for bringing the whole numpy duck array concept to fruition. That's huge! And I do hope that "duck array" sticks, it's much better than any of the alternatives in the NEP.

@astrofrog
Copy link
Member

I agree that this will be great to have! One big-picture question I have - is it conceivable that in future we could migrate to no longer subclassing ndarray as a result of this?

@astrofrog
Copy link
Member

One thing I've noticed so far is that this breaks straight plotting with quantities with different units for x and y (at least plt.scatter) since that internally tries to stick the 2 axes together. We may need to turn on quantity_support by default...

I don't really see any downside to this? For time_support it would be trickier since it has arguments, but I can't think of any reason to not enable quantity_support by default.

@astrofrog
Copy link
Member

Overall this looks great, and I like the way it's implemented. I reviewed the main __array_function__ method and it looks good. I didn't comb through all the tests and specific functions one by one, but I think that if people are generally on board, and this is otherwise ready to go, we should consider merging this soon so that it gets a good amount of testing over the next few months.

@mhvk
Copy link
Contributor Author

mhvk commented Jun 19, 2019

@bsipocz - yes, fixes #5842; #8610 is really follow-up. I'll merge it with the other follow-up issue.

@astrofrog, @taldcroft - I agree with the sentiment of merging this soon so we can test it out for a couple of months; the review of __array_function__ itself is the most important; the rest of the code is lots of wrapping boilerplate. I'm covering most with tests, and the only worry there is that I've missed what the units should be for some functions.

@mhvk
Copy link
Contributor Author

mhvk commented Jun 19, 2019

@astrofrog - yes, in principle with the combination of __array_ufunc__ and __array_function__, Quantity no longer has to subclass ndarray. But the drawbacks of subclassing have also become less over time - e.g., a lot of method overrides have now disappeared (which we would all have to bring back).

Also, within numpy, the discussion about introducing a new dtype, which could handle units internally, is getting more and more serious. I think that solution makes a lot of sense.

@mhvk
Copy link
Contributor Author

mhvk commented Jun 19, 2019

@taldcroft - my personal preference is "array mimic" as it doesn't require knowing the "if it quacks like a duck, ..." etc. But I've gotten little traction. 😄

Copy link
Member

@adrn adrn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with this! It sounds like a few of us have taken a close look at the __array_function__ implementation, and at least a first look at the tests. I agree that merging this soon would be great, as subtle issues will hopefully get shaken our during field testing...Given that, I'd be happy to see this merged now!

@pllim pllim merged commit 1d52e7e into astropy:master Jun 19, 2019
@pllim
Copy link
Member

pllim commented Jun 19, 2019

I'd be happy to see this merged now!

As you wish.

@bsipocz
Copy link
Member

bsipocz commented Jun 19, 2019

Thank you @mhvk, this is such a great improvement! 🎉 🎆

@mhvk mhvk deleted the use-array-function branch June 20, 2019 00:07
eerovaher added a commit to eerovaher/astropy that referenced this pull request Aug 16, 2023
With `numpy` < 1.17 or `astropy` < 4.0 calling `np.concatenate()` on
`Quantity` instances produced an output without a unit. Two workarounds
have persisted in the code until now, despite having been obsolete for
quite some time.

See also pull request astropy#8808 and 82ffaad
that updated the relevant documentation.
eerovaher added a commit to eerovaher/astropy that referenced this pull request Aug 17, 2023
It used to be the case that the output of `np.concatenate()` called with
`Quantity` instances lost the unit, but the workarounds have not been
needed since support for `numpy` version 1.16 was dropped. See also pull
request astropy#8808 and 82ffaad that updated
the relevant documentation.
eerovaher added a commit to eerovaher/astropy that referenced this pull request Aug 17, 2023
It used to be the case that the output of `np.concatenate()` called with
`Quantity` instances lost the unit, but the workarounds have not been
needed since support for `numpy` version 1.16 was dropped. See also pull
request astropy#8808 and 82ffaad that updated
the relevant documentation.
Shaheer-Ahmd pushed a commit to Shaheer-Ahmd/astropy that referenced this pull request Aug 22, 2023
It used to be the case that the output of `np.concatenate()` called with
`Quantity` instances lost the unit, but the workarounds have not been
needed since support for `numpy` version 1.16 was dropped. See also pull
request astropy#8808 and 82ffaad that updated
the relevant documentation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

np.where does not work with Quantity Fix known test failures for astropy.units.quantity

6 participants