Repository navigation
Improve speed of coordinate transformations for arrays of obstime - #10647
Conversation
The erfa.astrom struct needs a substantial amount of computing power to update Earth parameters. However, all but the Earth rotation angle are relatively slowly changing numbers. If some accuracy can be sacrificed, calculating the slowly changing astrom parameters only on certain time-steps, can lead to large speed-ups. For example, a time resolution of 10 minutes will still have an accuracy of <~50 mas if ICRS is transformed to AltAz. add astrom_manager helpers and transform_precision context coordinates.astrom_manager: do interpolation of earth_pv and CIS just for curiosity, we removed the pure MJD-binning in get_astrom helper and implemented a linear interpolation of the Earth-PV, Heliocentric, and CIS (Cartesian) vectors based on a binned MJD support. Comparing to the MJD binning, the accuracy of the coordinate transforms is boosted by a factor of a thousand, or so, while the computing times are almost as fast as before.
8aaa42e to
fd817ba
Compare
fd817ba to
ebf101e
Compare
This comment has been minimized.
This comment has been minimized.
|
Tests for the actual interpolation are missing and it does currently not work due to a shape issue, looking into it. |
from astropy.coordinates.astrom_manager import astrom_interpolation_resolution
from astropy.coordinates import SkyCoord, EarthLocation, AltAz
from astropy.time import Time
import astropy.units as u
import numpy as np
import matplotlib.pyplot as plt
from time import perf_counter
t = Time('2020-01-01T20:00:00') + np.random.uniform(0, 24, 100000) * u.hour
location = EarthLocation.of_site('Roque de los Muchachos')
crab = SkyCoord.from_name("Crab Nebula")
altaz = AltAz(obstime=t, location=location)
t0 = perf_counter()
no_interp = crab.transform_to(altaz)
print(f'No Interpolation took {perf_counter() - t0:.4f} s')
seps = {}
for resolution in [10 * u.s, 5 * u.min, 30 * u.min]:
t0 = perf_counter()
astrom_interpolation_resolution.set(resolution)
interp = crab.transform_to(altaz)
print(f'Interpolation with {resolution.value: 5} {str(resolution.unit):3s} resolution took {perf_counter() - t0:.4f} s')
seps[resolution.to_value(u.s)] = no_interp.separation(interp)
fig, axs = plt.subplots(len(seps), 1, constrained_layout=True)
for ax, (key, sep) in zip(axs, seps.items()):
ax.hist(sep.to_value(u.microarcsecond), bins=100)
ax.set_title(f'{key} s resolution')
ax.text(
0.5, 0.95,
(
f'mean: {sep.to_value(u.microarcsecond).mean():.4f} µas'
f'\np95: {np.percentile(sep.to_value(u.microarcsecond), 95):.4f} µas'
f'\nmax: {sep.to_value(u.microarcsecond).max():.4f} µas'
),
va='top',
ha='center',
transform=ax.transAxes
)
ax.set_xlabel('Angular Separation / µas')
fig.savefig('interpolation_error.png', dpi=300)Timings: |
Including the minimum and maximum timestamp of the obstimes dramatically improves interpolation results when the resolition is larger than the time range without hurting performance or when transforming a single value.
|
@maxnoe - as you will probably have seen from the original issue, I was quite wary of these speed-related work-arounds. That said, clearly you and others need it and looking at it again I think the approach taken, with a generic Before going there, it may be good to just make sure that what we implement is the right level of generality, so that users perhaps can change also in other ways how the transformations operate. I have not read back the whole original thread, but is it obviously why one would not override parts of the transformation graph with interpolating routines (and have a I think it may well be that the The implementation might look something like So, internally, whenever needed, code would do something like Or perhaps with string equivalents, like for the ephemerides, |
|
@mhvk I think your proposal makes a lot of sense! It seems a bit more work than the current solution, but it would indeed be a much more generic solution and leave the default behavior intact. It's been a while, since I looked into this part of the Astropy code, but I'll try to find some time next week to work on this. Perhaps you or @maxnoe would be available for some pair programming session? |
One of the plots was posted in the original PR, with the spatial dependency. The other plots are inferior to your histograms, I think, but I could dig that out if necessary. |
I agree, right now the code is very much entangled and this should be cleanly separated.
I started crude approximate transformations (implemented after formulas in the "Explanatory Supplement to the Astronomical Almanac") with a context manager to switch out transformations completely here: https://github.com/MaxNoe/approximate_coords But I think the interpolation approach of the astrom is a nice way of not having to replace a full transformation.
I like this proposal a lot better then the imperative structure of the current function, I'll give it a shot.
Sure! |
|
First I am going to write some basic unit tests and then refactor into the class based approach. |
|
Is codecov failing because the |
|
@mhvk Do you have an idea why the coverage is failing? |
|
@maxnoe - I think the coverage is done on a run without |
|
@mhvk Ok thanks, seems indeed it is unnecessary. I switched to hard coded coordinates in between without relying on |
|
@StuartLittlefair Could you re-review? Are all your comments addressed? |
|
@maxnoe sorry for the holiday induced delay! Looks good to me... |
|
@mhvk I adressed most of your comments by simply taking you suggestions but left a few out for now. I have no real problems with following your suggestions everywhere but nitpicked back a bit 🤣 |
|
@mhvk Ok, I think that's all comments adressed. |
mhvk
left a comment
There was a problem hiding this comment.
@maxnoe - OK, looks all fine now, so I'll go ahead and merge. Thanks so much for making this happen - it went from a feature I wasn't all that sure about to a really nice implementation that both solves the original purpose and sets us up a nice framework for possible future extensions.
On the imports, I do think that if we cannot import things from astropy, I think one would want test collection to fail immediately, as something is quite broken! But there are obviously more corner cases where an import depends on something else that is not available, and I'm not sure the tangle of pytest.skipif(...) decorators we have now is the best system.
Anyway, always good to discuss whether things can be improved, so definitely do open an issue with suggestions!
|
@maxnoe thank you so much for making this happen. Made my day! |

This is a followup to #6068, which was outdated.
Here, I squashed the commits in that branch to make rebasing easier and then rebased versus the current master.
Please see the discussion there.
I will start doing benchmarks with this code again and doing some cleaning up, e.g. using units for the precision and removing python 2 support in the new files.
EDIT: Close #6068