Repository navigation
Extend astropy.cosmology.z_at_value to accept array of values - #11361
MilesCranmer wants to merge 27 commits into
Conversation
There was a problem hiding this comment.
Welcome to Astropy 👋 and congratulations on your first pull request! 🎉
A project member will respond to you as soon as possible; in the meantime, please have a look over the Checklist for Contributed Code and make sure you've addressed as many of the questions there as possible.
If you feel that this pull request has not been responded to in a timely manner, please leave a comment mentioning our software support engineer @embray, or send a message directly to the development mailing list. If the issue is urgent or sensitive in nature (e.g., a security vulnerability) please send an e-mail directly to the private e-mail [email protected].
| The redshift ``z`` satisfying ``zmin < z < zmax`` and ``func(z) = | ||
| fval`` within ``ztol``. | ||
|
|
||
| Notes |
There was a problem hiding this comment.
Looks like this whole section was removed without any replacement text.
There was a problem hiding this comment.
The Notes section here was advice for how to operate on arrays using interpolation. Since the function does this automatically now, I think this part of the docstring is not needed?
There was a problem hiding this comment.
I do wonder why, given that the docs already had an explanation on how to do this, that the functionality wasn't incorporated into the method to begin with.
There was a problem hiding this comment.
I vaguely recall that the issue was that in normal usage you basically iterate to a pretty exact solution, while with interpolation it depends on your number of bins, etc. I.e., a case perhaps where the wish for perfection stopped the "good enough".
But this does bring up a more general issue, whether the result of the call should depend on whether something is passed in as an array or as a scalar. There is an argument to be made to create a more general interpolation method and just refer to that in the docstring. But, then again, I may be aiming for too much perfection...
p.s. Sorry, right now time just to chime in, not for a proper review.
p.s. @MilesCranmer: thanks for the PR!
There was a problem hiding this comment.
Thanks!
Regarding different answers between scalar/array, I could add a warning for this? I also agree: there's probably no perfect solution here. And perfect is the enemy of good :)
There was a problem hiding this comment.
Actually, instead I think your idea to put it in the docstring is a better idea than a warning - I can add that!
There was a problem hiding this comment.
Done - added a note to the docstring.
There was a problem hiding this comment.
I agree that "a more general interpolation method" would be nice, but out of scope, and I think this is a very good intermediate step. 👍
|
Thanks! I left some general comments but would need someone who has expertise in |
Co-authored-by: P. L. Lim <[email protected]>
Co-authored-by: P. L. Lim <[email protected]>
|
Nicely done PR, thank you. |
I agree these points should be explained to the user. Even just dropping this list into the docs would be good.
I defer this to maintainers, but it seems a reasonable suggestion, especially given that this PR adds kwargs to (Need to create a decorator in order to apply these funcs with pie-syntax``) |
| except ImportError: | ||
| HAS_SCIPY = False | ||
| else: | ||
| HAS_SCIPY = True |
| func : callable | ||
| A function that takes a redshift as input. | ||
| fval : astropy.Quantity instance | ||
| fval : astropy.Quantity instance or array_like |
There was a problem hiding this comment.
| fval : astropy.Quantity instance or array_like | |
| fval : `~astropy.units.Quantity` or array_like |
|
@pllim, I think that there is a worthwhile discussion happening here on whether to implement the improvements as a separate function, or not. Given that, I don't see this being done by the feature freeze tomorrow (or Monday?). |
|
Thanks for the update! I tentatively moved the milestone. |
| " scheme for array z_at_value, instead of the normal cubic" | ||
| " spline.")) |
There was a problem hiding this comment.
| " scheme for array z_at_value, instead of the normal cubic" | |
| " spline.")) | |
| " scheme for array z_at_value, instead of the normal cubic spline.")) |
Technicality, but Astropy has a line length limit of 99/100, and as long as the output lines are within 72 chars this can go onto a single line just fine.
| is_array = ( | ||
| (isinstance(fval, Quantity) and not fval.isscalar) or | ||
| (not isinstance(fval, Quantity) and isinstance(fval, np.ndarray)) | ||
| ) |
There was a problem hiding this comment.
| is_array = ( | |
| (isinstance(fval, Quantity) and not fval.isscalar) or | |
| (not isinstance(fval, Quantity) and isinstance(fval, np.ndarray)) | |
| ) | |
| is_array = (isinstance(fval, Quantity) and not fval.isscalar) or np.array(fval).ndim > 0 |
Should be mostly equivalent, in fact this would identify any iterable (array_like) fval.
| zmin=zmin, zmax=zmax, | ||
| nbins=nbins, logspace=logspace, | ||
| interpolation=interpolation) | ||
|
|
There was a problem hiding this comment.
Again, line length limits are not that strict anymore.
Note that the is_array condition from above would include length-1 arrays!
This raises some more general issues on efficiency, but if they cannot be addressed (all) now, as already noted in the discussion, being good but not perfect should not keep this PR from being accepted as a first implementation:
- Default
nbinscould be adapted to the providedzmin-zmaxrange. Some general tests on the required grid resolution would probably be helpful, considering the original example was only using 50. I think I had made some; don't recall the results, but 10000 is certainly very generous. zmin,zmaxthemselves might be adapted to the range required for the inputfval. For monotonic functions this would be straightforward, usingfvals.min(),fvals.max()as already demonstrated in the old example. For the non-monotonic ones this would of course become a bit trickier, like always including the function maximum and then finding the minimum values on both sides. For arbitrary functions and cosmology realisations not that easy...- The typical direct minimisation takes O(20) function calls with the new solvers; for small arrays direct calls to the solver for each
fvalwill therefore be much more efficient. As a guide, onez_at_value(func, fval[i])call is something like 40-100 time faster than thefunc(fval)call on an array[10000].
There was a problem hiding this comment.
Quick comment re: 3 (I agree with other points): evaluating on a grid of 1e4 values is not necessarily (1e4/20)x slower than direct minimisation with 20 steps, since evaluating on a grid is trivially vectorizable, whereas optimization is serial. If the underlying operations are vectorized well, the grid evaluation + interpolation might even be faster than direct minimisation for a single point! But worth testing.
|
Hi humans 👋 - this pull request hasn't had any new commits for approximately 4 months. I plan to close this in 30 days if the pull request doesn't have any new commits by then. In lieu of a stalled pull request, please consider closing this and open an issue instead if a reminder is needed to revisit in the future. Maintainers may also choose to add keep-open label to keep this PR open but it is discouraged unless absolutely necessary. If this PR still needs to be reviewed, as an author, you can rebase it to reset the clock. If you believe I commented on this pull request incorrectly, please report this here. |
I made the stale time approx 5 months but assumed 30 days each month, so I guess some will be destined to stale in 4+ months instead of 5. The old bot was like that too. |
|
Hi all, |
|
Hi @MilesCranmer, thanks for the update.
No worries!
So There are a number of smaller changes: we no longer use
Always happy to help. Just let us know. |
|
Thanks! |
These are currently only on the horizon. |
Description
This PR extends
astropy.cosmology.z_at_valueto accept an array of function values, rather than a single value. The implementation follows the suggested advice in the docstring of using interpolation over a grid of z values and inverting. However, I use a cubic spline instead ofnp.interp(which uses linear interpolation), though the fallback method isnp.interpif scipy is not found.Two new arguments are added:
nbinswhich sets the number of gridpoints to evaluate the function at to build up a dataset of(z, func(z))tuples, andlogspace, a bool which determines whether to generate the grid with logarithmic spacing.zminandzmaxare used for the boundaries.Example
^(The array-based scheme in
In [5]is much faster)