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
ENH: Add np.full to dispatchable functions #16138
base: main
Are you sure you want to change the base?
Conversation
Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.
|
@@ -241,6 +241,10 @@ def like_helper(a, *args, **kwargs): | |||
unit = a.unit if subok else None | |||
return (a.view(np.ndarray),) + args, kwargs, unit, None | |||
|
|||
@dispatched_function | |||
def full(shape, fill_value, dtype=None, order='C'): | |||
return np.full(shape, fill_value, dtype, order), fill_value.unit, None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also be something like:
return np.full(shape, fill_value, dtype, order), fill_value.unit, None | |
return np.full(shape, fill_value.view(np.ndarray), dtype, order), fill_value.unit, None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not know here that fill_value
is a Quantity
- because you will have gotten here by the like
argument. So, you'd need to pass it through _as_quantity()
. I also think this works fine as a function_helper
, i.e.,
@function_helper
def full(shape, fill_value, dtype=None, order='C'):
fill_value = _as_quantity(fill_value)
return (shape, fill_value.value, dtype, order), {}, fill_value.unit, None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, so something like np.full(10, fill_value=1, like=my_quantity)
is expected behavior too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the idea is you pass in a class, as in like=Quantity
, and for Quantity
, fill_value
does not have to have units. But you make a good point that for Angle
there should be units, so my solution is not correct for that. Unfortunately, in this piece of code we do not actually know what (sub)class of Quantity we're in! We only know inside __array_function__
... I think this will need some looking into how it actually is called...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that has long been on my wish list! Note that I mention other creation routines, but I'm frankly not sure any of them is very useful - np.full
is really the one exception. So, I'm fine with just doing this one and hard-coding it in the list of functions we test and support.
p.s. Of course, if you really want to go for this, one can also do the same for Masked
...
@@ -241,6 +241,10 @@ def like_helper(a, *args, **kwargs): | |||
unit = a.unit if subok else None | |||
return (a.view(np.ndarray),) + args, kwargs, unit, None | |||
|
|||
@dispatched_function | |||
def full(shape, fill_value, dtype=None, order='C'): | |||
return np.full(shape, fill_value, dtype, order), fill_value.unit, None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not know here that fill_value
is a Quantity
- because you will have gotten here by the like
argument. So, you'd need to pass it through _as_quantity()
. I also think this works fine as a function_helper
, i.e.,
@function_helper
def full(shape, fill_value, dtype=None, order='C'):
fill_value = _as_quantity(fill_value)
return (shape, fill_value.value, dtype, order), {}, fill_value.unit, None
a = u.Quantity(1, u.m) | ||
b = np.full(3, a, like=a) | ||
assert b.unit == a.unit | ||
assert len(b) == 3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is really for is_close
, etc., i.e., helper routines to deal with quantities rather than helper routines to deal with numpy functions (naming is hard!!). It should go in test_quantity_non_ufuncs.py
(did I mention naming is hard?).
Note that that file attempts to keep track of whether our coverage is complete, and the set that it things needs to be covered is calculated in get_wrapped_functions
- you'd need to extend that to include the generation-like routines like np.full
(also np.zeros
, np.arange
, etc.). It would make sense to create a new TestCreatingFunctionsUsingLike
or so.
Description
This almost fixes #10836, with NEP 35 it is possible to dispatch functions like
np.full
.With this change the following code should work:
This does require passing in the
like
argument as numpy can't auto infer fromfill_value
, and I guess it gets close enough to the behavior requested in #10836 (comment)