Skip to content

Use new erfa routine to calculate the position of the Moon - #11753

Merged
StuartLittlefair merged 4 commits into
astropy:mainfrom
mhvk:coordinates-moon-use-erfa
May 21, 2021
Merged

StuartLittlefair merged 4 commits into
astropy:mainfrom
mhvk:coordinates-moon-use-erfa

Conversation

@mhvk

@mhvk mhvk commented May 17, 2021 •

Copy link
Copy Markdown
Contributor

This replaces our own implementation of the Meeus algorithm for calculating the position of the Moon with the new routine in erfa (so the PR also bumps the minimum version of erfa).

I added a comparison between the JPL ephemeris and this new one, and oddly the differences in position and velocity are quite a bit larger than they should be according to the moon98 documentation (see https://pyerfa.readthedocs.io/en/latest/api/erfa.moon98.html#erfa.moon98). with the correct implementation pointed out by @mkbrewer the code is now consistent in precision with what was expected.

EDIT: old text for reference only
In the PR, I write we should also be sure to correct for light-travel time effect (which is included in the Meeus algorithm, but should not be for barycentric position), but from the trials I did I'm not sure that is enough. Am I missing something? (I tried applying in GCRS, which has almost no effect; I also tried applying the Moon-Earth light travel time one finds from the GCRS to the ICRS pos and vel, which does give an improvement but not to the level expected).

Fixes #11739, #11755

@mhvk

mhvk commented May 17, 2021

Copy link
Copy Markdown
Contributor Author

cc also @mkbrewer who can perhaps shine some light on why the positions match relatively poorly.

@mhvk mhvk changed the title Coordinates moon use erfa Use new erfa routine to calculate the position of the Moon May 17, 2021
@mkbrewer

Copy link
Copy Markdown
Contributor

@mhvk Can you please post the error in RA/Dec that you see compared to JPL Horizons. Error in both ICRS and TETE would be helpful.

@mkbrewer

Copy link
Copy Markdown
Contributor

Actually, just the date, JPL ICRS and TETE positions along with the corresponding Astropy positions would be good.

@mkbrewer

Copy link
Copy Markdown
Contributor

Of course, you could also just use the Astropy output for DE430 in place of JPL Horizons.

@pllim pllim added this to the v5.0 milestone May 18, 2021
@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

@mkbrewer - I think I part of the problem may be that I misunderstood the statement about the accuracy; the documentation lists:

RMS errors of 2.9 arcsec in geocentric direction, 6.1 km in position and 36 mm/s in velocity.

I interpreted these as RMS errors in the norm of the position differences, but now that I check more carefully (in GRCS), I see that I get 3" rms for the difference in RA and 1.5" in dec, so those are OK. The position I'm still confused about. The rms in distance difference I get is 27 km, and in X, Y, and Z, it is 21, 18, and 6 km. I now wonder if it is just the documentation not being quite right...

I did some checks with the code below. But since the numbers are essentially the same with the old code we had, I think for the purposes of this PR it is probably OK.

import numpy as np
from astropy.time import Time
from astropy import units as u
from astropy.coordinates import get_body
from astropy.table import QTable


t = Time('2016-03-20T12:30:00') + np.arange(8.) * 91 * u.day
body = 'moon'
builtin = get_body(body, t, ephemeris='builtin')
de432 = get_body(body, t, ephemeris='de432s')

pos_diff = (builtin.cartesian - de432.cartesian).norm()
print(f'{pos_diff=}, rms={np.sqrt((pos_diff**2).mean())}')

qt = QTable()
qt['builtin_gcrs'] = builtin.cartesian
qt['de432s_gcrs'] = de432.cartesian
qt['diff'] = builtin.cartesian - de432.cartesian

qt.write('moon.ecsv', overwrite=True)

which produces

# %ECSV 1.0
# ---
# datatype:
# - {name: time, datatype: string}
# - {name: builtin_gcrs.x, unit: km, datatype: float64}
# - {name: builtin_gcrs.y, unit: km, datatype: float64}
# - {name: builtin_gcrs.z, unit: km, datatype: float64}
# - {name: de432s_gcrs.x, unit: km, datatype: float64}
# - {name: de432s_gcrs.y, unit: km, datatype: float64}
# - {name: de432s_gcrs.z, unit: km, datatype: float64}
# - {name: diff.x, unit: km, datatype: float64}
# - {name: diff.y, unit: km, datatype: float64}
# - {name: diff.z, unit: km, datatype: float64}
# meta: !!omap
# - __serialized_columns__:
#     builtin_gcrs:
#       __class__: astropy.coordinates.representation.CartesianRepresentation
#       x: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: &id001 !astropy.units.Unit {unit: km}
#         value: !astropy.table.SerializedColumn {name: builtin_gcrs.x}
#       y: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: builtin_gcrs.y}
#       z: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: builtin_gcrs.z}
#     de432s_gcrs:
#       __class__: astropy.coordinates.representation.CartesianRepresentation
#       x: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: de432s_gcrs.x}
#       y: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: de432s_gcrs.y}
#       z: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: de432s_gcrs.z}
#     diff:
#       __class__: astropy.coordinates.representation.CartesianRepresentation
#       x: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: diff.x}
#       y: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: diff.y}
#       z: !astropy.table.SerializedColumn
#         __class__: astropy.units.quantity.Quantity
#         unit: *id001
#         value: !astropy.table.SerializedColumn {name: diff.z}
#     time:
#       __class__: astropy.time.core.Time
#       format: isot
#       in_subfmt: '*'
#       out_subfmt: '*'
#       precision: 3
#       scale: utc
#       value: !astropy.table.SerializedColumn {name: time}
# schema: astropy-2.0
time builtin_gcrs.x builtin_gcrs.y builtin_gcrs.z de432s_gcrs.x de432s_gcrs.y de432s_gcrs.z diff.x diff.y diff.z
2016-03-20T12:30:00.000 -334191.2676770922 204079.17354726762 71842.61759822942 -334199.88487008435 204094.39125450165 71842.81544772576 8.617192992125638 -15.21770723402733 -0.19784949634049553
2016-06-19T12:30:00.000 -85150.31735980787 -369062.1047164577 -122111.53916730372 -85155.29326370585 -369072.3266442727 -122116.74448117506 4.975903897982789 10.221927815000527 5.205313871338149
2016-09-18T12:30:00.000 340484.52239177853 119057.54974140457 29710.709290328712 340475.180849512 119056.65805202068 29710.780103911882 9.341542266542092 0.8916893838904798 -0.0708135831700929
2016-12-18T12:30:00.000 -319319.9168982803 193699.90246315737 78276.46793327596 -319292.5373954533 193677.71545675964 78268.0909070149 -27.379502827010583 22.18700639772578 8.37702626104874
2017-03-19T12:29:59.000 -95064.4203989457 -373255.3734931006 -122739.92887635271 -95046.37871086932 -373218.88611260924 -122729.46095318746 -18.041688076380524 -36.48738049133681 -10.467923165255343
2017-06-18T12:29:59.000 368998.4378629052 70531.88761875624 5019.187399216661 368962.82381513156 70531.47993079304 5019.811780509273 35.61404777364805 0.4076879632048076 -0.62438129261227
2017-09-17T12:29:59.000 -287943.8061537544 219897.21786271696 93089.51373128328 -287920.1906603668 219886.91986105315 93086.59930385805 -23.615493387624156 10.298001663817558 2.914427425232134
2017-12-17T12:29:59.000 -88485.73066567995 -374557.9797081495 -128792.85493156385 -88486.5021179798 -374552.52141479036 -128791.14401103048 0.7714522998576285 -5.458293359144591 -1.7109205333690625

@mhvk
mhvk force-pushed the coordinates-moon-use-erfa branch from 1a9745c to 80a5647 Compare May 18, 2021 01:32
Comment thread astropy/coordinates/solar_system.py Outdated
body_pos_bary = icrs_cart.without_differentials()
body_vel_bary = icrs_cart.differentials['s'].to_cartesian()
# TODO: the Meeus algorithm includes light travel time.
# That should be undo somewhere

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I note that, in fact, light travel time is omitted:

**  2) This function is a full implementation of the algorithm
**     published by Meeus (see reference) except that the light-time
**     correction to the Moon's mean longitude has been omitted.

However, given the stated accuracy and the fact that the effect of light travel time to the geocenter amounts to only 0.7" in longitude, it is likely OK to omit the calculation of the light delayed position.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for looking much more carefully! It actually is nicer - I think we might as well include the light travel time correction, making the case of the moon less special.

@dhomeier

Copy link
Copy Markdown
Contributor

RMS errors of 2.9 arcsec in geocentric direction, 6.1 km in position and 36 mm/s in velocity.

I interpreted these as RMS errors in the norm of the position differences, but now that I check more carefully (in GRCS), I see that I get 3" rms for the difference in RA and 1.5" in dec, so those are OK. The position I'm still confused about. The rms in distance difference I get is 27 km, and in X, Y, and Z, it is 21, 18, and 6 km. I now wonder if it is just the documentation not being quite right...

Transversal position errors of 6 km are matching 3" at the distance of the Moon well enough; maybe would need a look into the Meeus paper to find out if a larger uncertainty in distance is to be expected. Also, it's not fully outside the given range or errors

Comparisons with ELP/MPP02 over the interval 1950-2100 gave RMS** errors of 2.9 arcsec in geocentric direction, 6.1 km in position** and 36 mm/s in velocity. The worst case errors were 18.3 arcsec** in geocentric direction, 31.7 km in position and 172 mm/s in** velocity.

OTOH 27 km feels uncomfortably close to the Earth's orbital motion over one light travel time, so maybe that effect is still missing somewhere. Are you getting comparable differences at different phases?

@mkbrewer

Copy link
Copy Markdown
Contributor

I looked into that and he is not.

      Date          Delta_Dist (km)
03/20/16 12:30 PM  -15.0702699522
06/19/16 12:30 PM  -12.1417052862
09/18/16 12:30 PM    9.0757431909
12/18/16 12:30 PM   35.8921882028
03/19/17 12:29 PM   41.1102829622
06/18/17 12:29 PM   35.045768336
09/17/17 12:29 PM   24.9568021735
12/17/17 12:29 PM    5.4122424555

The fact that he is currently using the calculated GCRS position directly rather than differencing the BCRS positions of the Moon and the Earth precludes any effect of the orbital velocity of the Moon around the SSB.

@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

@mkbrewer, @dhomeier - I've started a new issue, #11755, since I think one thing is clear is that this is not related to moving to a new implementation - the answers between our own implementation of Meeus and moon98 are quite consistent with each other. So, from that perspective, there is no reason not to just use the SOFA one and, if there are any issues that are not just lack of understanding on our part, try to move them up to SOFA.

@mhvk
mhvk force-pushed the coordinates-moon-use-erfa branch from 5f0c247 to 14a56fd Compare May 18, 2021 16:50
@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

@pllim -as our "actions" expert, for this PR I've been getting messages that all the action tests are cancelled as duplicates, even though I'm pushing up new stuff. Could it be that somehow things are being run both on my branch as on astropy? As far as I know, though, I have not changed any setting...

@pllim

pllim commented May 18, 2021

Copy link
Copy Markdown
Member

GitHub Actions is having problems right now: Update - We continue to observe our services recover with an increasing number of successful builds, we will keep monitoring until full recovery and will provide more updates soon. May 18, 16:08 UTC

The logs say, "GitHub Actions has encountered an internal error when running your job," which is caused by the upstream problem, not our cancel job.

@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

Thanks!

@mhvk
mhvk marked this pull request as draft May 18, 2021 18:16
@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

I've converted to draft while some additional thinking is going on. My latest addition makes distance better but RA, Dec worse...

@mhvk
mhvk force-pushed the coordinates-moon-use-erfa branch from 14a56fd to 658a6dd Compare May 18, 2021 21:21
@mhvk
mhvk marked this pull request as ready for review May 18, 2021 21:21
@mhvk

mhvk commented May 18, 2021

Copy link
Copy Markdown
Contributor Author

OK, instead of making changes to the light travel time corrections, I now again left it as it was, and just added comments with links to #11755. For the purposes of this PR, which is just to switch out our own implementation of the Meeus algorithm with the SOFA one, I think that is fine. The two codes give consistent results.

So, ready for review, I guess...

@StuartLittlefair

Copy link
Copy Markdown
Contributor

@mhvk now that @mkbrewer has diagnosed the issues relating to light travel time in #11755 (comment), do you want to implement that change in this PR, or shall I review this PR as-is and you can submit a new PR?

I slightly favour the latter. Then this PR essentially keeps functionality the same, just using erfa to remove the use of orbital_elements, whilst the new PR would be an accuracy improvement.

@mhvk

mhvk commented May 20, 2021

Copy link
Copy Markdown
Contributor Author

@StuartLittlefair - I actually am tempted to just do it right in one go. A consequence of the realization that moon98 just gives back a relative position to the Earth, is that things completely simplify: it just gets used directly in _get_body_barycentric_posvel just like plan94 gets used for the planets. All the other moon special-casing is removed. In fact, it may be easiest to just make a new PR and close this one...

mhvk added 3 commits May 20, 2021 12:47
Since moon98 returns the astrometric position relative to Earth,
this meant that the best place to use it is inside
_get_body_barycentric_posvel, and that then no further special
casing is necessary.
@mhvk
mhvk force-pushed the coordinates-moon-use-erfa branch from 658a6dd to dff3564 Compare May 20, 2021 16:58
@mhvk

mhvk commented May 20, 2021

Copy link
Copy Markdown
Contributor Author

@StuartLittlefair, @mkbrewer - OK, the PR is now revised. I like that the code is now much simpler, and of course it helps that it is more precise too!

@mkbrewer

Copy link
Copy Markdown
Contributor

@mhvk This looks good to me.

@mhvk

mhvk commented May 20, 2021

Copy link
Copy Markdown
Contributor Author

OK, great. And thanks of course very much for figuring out what the problem was! And showing that we had not done it quite right until now...

@StuartLittlefair

Copy link
Copy Markdown
Contributor

Lovely! Well done @mhvk and @mkbrewer

Merging

@StuartLittlefair
StuartLittlefair merged commit 769031b into astropy:main May 21, 2021
@mhvk
mhvk deleted the coordinates-moon-use-erfa branch May 21, 2021 14:01
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.

Replace our custom calc_moon with new moon98 in SOFA 18

5 participants