Skip to content

Commit 80b562a

Browse files
committed
Add support for new Horizons quantities.
1 parent fa181fa commit 80b562a

File tree

2 files changed

+165
-49
lines changed

2 files changed

+165
-49
lines changed

astroquery/jplhorizons/__init__.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,14 @@ class Conf(_config.ConfigNamespace):
2020
['https://ssd.jpl.nasa.gov/api/horizons.api', ],
2121
'JPL Horizons')
2222

23-
# implement later: sbdb_server = 'https://ssd-api.jpl.nasa.gov/sbdb.api'
24-
2523
timeout = _config.ConfigItem(
2624
30,
2725
'Time limit for connecting to JPL servers.')
2826

2927
# JPL Horizons settings
3028

3129
# quantities queried in ephemerides query (see
32-
# https://ssd.jpl.nasa.gov/?horizons_doc#table_quantities)
33-
# default: all quantities
30+
# https://ssd.jpl.nasa.gov/horizons/manual.html#output)
3431
eph_quantities = ('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
3532
'21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,'
3633
'38,39,40,41,42,43')
@@ -55,7 +52,7 @@ class Conf(_config.ConfigNamespace):
5552
'illumination_flag': ('illumination_flag', '---'),
5653
'nearside_flag': ('nearside_flag', '---'),
5754
'R.A._(ICRF)': ('RA', 'deg'),
58-
'DEC_(ICRF)': ('DEC', 'deg'),
55+
'DEC__(ICRF)': ('DEC', 'deg'),
5956
'R.A.___(ICRF)': ('RA', 'deg'),
6057
'DEC____(ICRF)': ('DEC', 'deg'),
6158
'R.A._(ICRF/J2000.0)': ('RA', 'deg'),
@@ -64,14 +61,18 @@ class Conf(_config.ConfigNamespace):
6461
'DEC_(FK4/B1950.0)': ('DEC', 'deg'),
6562
'R.A._(FK4/B1950)': ('RA', 'deg'),
6663
'DEC_(FK4/B1950)': ('DEC', 'deg'),
64+
'RA_(ICRF-a-app)': ('RA_ICRF_app', 'deg'), # both *_app and *_ICRF_app may be present
65+
'DEC_(ICRF-a-app)': ('DEC_ICRF_app', 'deg'),
6766
'R.A._(a-app)': ('RA_app', 'deg'),
68-
'R.A.__(a-app)': ('RA_app', 'deg'),
6967
'DEC_(a-app)': ('DEC_app', 'deg'),
68+
'R.A.__(a-app)': ('RA_app', 'deg'),
7069
'DEC___(a-app)': ('DEC_app', 'deg'),
7170
'R.A._(r-app)': ('RA_app', 'deg'),
7271
'DEC_(r-app)': ('DEC_app', 'deg'),
7372
'dRA*cosD': ('RA_rate', 'arcsec/hour'),
7473
'd(DEC)/dt': ('DEC_rate', 'arcsec/hour'),
74+
'I_dRA*cosD': ('RA_ICRF_rate', 'arcsec/hour'), # both *_rate and *_ICRF_rate may be present
75+
'I_d(DEC)/dt': ('DEC_ICRF_rate', 'arcsec/hour'),
7576
'Azi_(a-app)': ('AZ', 'deg'),
7677
'Elev_(a-app)': ('EL', 'deg'),
7778
'Azimuth_(a-app)': ('AZ', 'deg'),
@@ -163,7 +164,13 @@ class Conf(_config.ConfigNamespace):
163164
'L_Ap_Hour_Ang': ('hour_angle', '---'),
164165
'phi': ('alpha_true', 'deg'),
165166
'PAB-LON': ('PABLon', 'deg'),
166-
'PAB-LAT': ('PABLat', 'deg')
167+
'PAB-LAT': ('PABLat', 'deg'),
168+
'App_Lon_Sun': ('App_Lon_Sun', 'deg'),
169+
'Sky_motion': ('Sky_motion', 'arcsec/minute'),
170+
'Sky_mot_PA': ('Sky_mot_PA', 'deg'),
171+
'RelVel-ANG': ('RelVel-ANG', 'deg'),
172+
'Lun_Sky_Brt': ('Lun_Sky_Brt', 'mag/arcsec2'),
173+
'sky_SNR': ('sky_SNR', '---'),
167174
}
168175

169176
elem_columns = {'targetname': ('targetname', '---'),

astroquery/jplhorizons/tests/test_jplhorizons_remote.py

Lines changed: 151 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from astropy.coordinates import spherical_to_cartesian
88
from astropy.tests.helper import assert_quantity_allclose
99
import astropy.units as u
10+
from astropy.coordinates import Angle
1011
from astropy.utils.exceptions import AstropyDeprecationWarning
1112

1213
from ... import jplhorizons
@@ -16,50 +17,158 @@
1617
class TestHorizonsClass:
1718

1819
def test_ephemerides_query(self):
19-
# check values of Ceres for a given epoch
20+
# check all values of Ceres for a given epoch
2021
# orbital uncertainty of Ceres is basically zero
21-
res = jplhorizons.Horizons(id='Ceres', location='500',
22+
res = jplhorizons.Horizons(id='Ceres', location='I41',
2223
id_type='smallbody',
23-
epochs=2451544.5).ephemerides()[0]
24-
25-
assert res['targetname'] == "1 Ceres (A801 AA)"
26-
assert res['datetime_str'] == "2000-Jan-01 00:00:00.000"
27-
assert res['solar_presence'] == ""
28-
assert res['lunar_presence'] == ""
29-
assert res['elongFlag'] == '/L'
30-
assert res['airmass'] == 999
31-
32-
assert is_masked(res['AZ'])
33-
assert is_masked(res['EL'])
34-
assert is_masked(res['magextinct'])
35-
36-
assert_quantity_allclose(
37-
[2451544.5,
38-
3.33, .120,
39-
188.7028, 9.09829, 34.40955, -2.68359,
40-
96.17083,
41-
161.3828, 10.4528, 2.551099027865, 0.1744491,
42-
2.26315121010004, -21.9390512, 18.82205467,
43-
95.3996, 22.5698, 292.551,
44-
296.85,
45-
184.3426241, 11.7996517, 289.864335,
46-
71.545654,
47-
0.0, 0.0],
48-
[res['datetime_jd'],
49-
res['H'], res['G'],
50-
res['RA'], res['DEC'], res['RA_rate'], res['DEC_rate'],
51-
res['illumination'],
52-
res['EclLon'], res['EclLat'], res['r'], res['r_rate'],
53-
res['delta'], res['delta_rate'], res['lighttime'],
54-
res['elong'], res['alpha'], res['sunTargetPA'],
55-
res['velocityPA'],
56-
res['ObsEclLon'], res['ObsEclLat'], res['GlxLon'],
57-
res['GlxLat'],
58-
res['RA_3sigma'], res['DEC_3sigma']], rtol=1e-3)
59-
60-
# V and surfbright tend to vary a lot more than the others. Give them a
61-
# more generous test:
62-
assert_quantity_allclose([8.239, 6.779], [res['V'], res['surfbright']], rtol=0.1)
24+
epochs=2451544.5,
25+
quantities=",".join(str(q) for q in range(1, 49))
26+
).ephemerides()[0]
27+
28+
# Retrieved 2023 Aug 01:
29+
values = {
30+
"datetime_str": "2000-Jan-01 00:00:00.000",
31+
"solar_presence": "*",
32+
"lunar_presence": "",
33+
"RA": Angle("12 34 48.58", unit="hr"),
34+
"DEC": Angle("+09 05 51.3", unit="deg"),
35+
"RA_app": Angle("12 34 47.66", unit="hr"),
36+
"DEC_app": Angle("+09 05 53.0", unit="deg"),
37+
"RA_rate": 35.17815 * u.arcsec / u.hr,
38+
"DEC_rate": -2.74237 * u.arcsec / u.hr,
39+
"AZ": 325.548736 * u.deg,
40+
"EL": -41.062749 * u.deg,
41+
"AZ_rate": 781.92 * u.arcsec / u.minute,
42+
"EL_rate": -426.18 * u.arcsec / u.minute,
43+
"sat_X": -304791.02 * u.arcsec,
44+
"sat_Y": 115814.995 * u.arcsec,
45+
"sat_PANG": 277.607 * u.deg,
46+
"siderealtime": "22 52 25.4117",
47+
"airmass": 999,
48+
"magextinct": np.ma.masked,
49+
"V": 8.259 * u.mag,
50+
"surfbright": 6.799 * u.mag / u.arcsec**2,
51+
"illumination": 96.17086 * u.percent,
52+
"illum_defect": 0.0225 * u.arcsec,
53+
"sat_sep": 343433.5 * u.arcsec,
54+
"sat_vis": "*",
55+
"ang_width": 0.587419 * u.arcsec,
56+
"PDObsLon": 302.274926 * u.deg,
57+
"PDObsLat": -3.982640 * u.deg,
58+
"PDSunLon": 279.670960 * u.deg,
59+
"PDSunLat": -3.621151 * u.deg,
60+
"SubSol_ang": 112.55 * u.deg,
61+
"SubSol_dist": 0.11 * u.arcsec,
62+
"NPole_ang": 22.6777 * u.deg,
63+
"NPole_dist": -0.271 * u.arcsec,
64+
"EclLon": 161.3828 * u.deg,
65+
"EclLat": 10.4528 * u.deg,
66+
"r": 2.551099025883 * u.au,
67+
"r_rate": 0.1744491 * u.km / u.s,
68+
"delta": 2.26317926925737 * u.au,
69+
"delta_rate": -21.7732311 * u.km / u.s,
70+
"lighttime": 18.82228803 * u.minute,
71+
"vel_sun": 19.3602212 * u.km / u.s,
72+
"vel_obs": 27.0721344 * u.km / u.s,
73+
"elong": 95.3982 * u.deg,
74+
"elongFlag": "/L",
75+
"alpha": 22.5696 * u.deg,
76+
"lunar_elong": 32.9 * u.deg,
77+
"lunar_illum": 27.4882 * u.percent,
78+
"sat_alpha": 62.0400 * u.deg,
79+
"sunTargetPA": 292.552 * u.deg,
80+
"velocityPA": 296.849 * u.deg,
81+
"OrbPlaneAng": -1.53489 * u.deg,
82+
"constellation": "Vir",
83+
"TDB-UT": 64.183887 * u.s,
84+
"ObsEclLon": 184.3424861 * u.deg,
85+
"ObsEclLat": 11.7988212 * u.deg,
86+
"NPole_RA": 291.42763 * u.deg,
87+
"NPole_DEC": 66.76033 * u.deg,
88+
"GlxLon": 289.863376 * u.deg,
89+
"GlxLat": 71.544870 * u.deg,
90+
"solartime": "16 09 31.6338",
91+
"earth_lighttime": 0.000354 * u.minute,
92+
"RA_3sigma": 0.000 * u.arcsec,
93+
"DEC_3sigma": 0.000 * u.arcsec,
94+
"SMAA_3sigma": 0.00012 * u.arcsec,
95+
"SMIA_3sigma": 0.00005 * u.arcsec,
96+
"Theta_3sigma": -24.786 * u.deg,
97+
"Area_3sigma": 0.0000000 * u.arcsec**2,
98+
"RSS_3sigma": 0.000 * u.arcsec,
99+
"r_3sigma": 0.0904 * u.km,
100+
"r_rate_3sigma": 0.0000000 * u.km / u.s,
101+
"SBand_3sigma": 0.00 * u.Hz,
102+
"XBand_3sigma": 0.00 * u.Hz,
103+
"DoppDelay_3sigma": 0.000001 * u.s,
104+
"true_anom": 7.1181 * u.deg,
105+
"hour_angle": "10 17 37.752",
106+
"alpha_true": 22.5691 * u.deg,
107+
"PABLon": 172.8355 * u.deg,
108+
"PABLat": 11.3478 * u.deg,
109+
"App_Lon_Sun": 309.1603680 * u.deg,
110+
"RA_ICRF_app": Angle("12 34 48.57", unit=u.hr),
111+
"DEC_ICRF_app": Angle("+09 05 46.6", unit=u.deg),
112+
"RA_ICRF_rate": 35.17809 * u.arcsec / u.hour,
113+
"DEC_ICRF_rate": -2.74321 * u.arcsec / u.hour,
114+
"Sky_motion": 0.5880814 * u.arcsec / u.minute,
115+
"Sky_mot_PA": 94.457576 * u.deg,
116+
"RelVel-ANG": -53.53947 * u.deg,
117+
"Lun_Sky_Brt": np.masked,
118+
"sky_SNR": np.masked,
119+
}
120+
121+
# the ephemeris changes with Ceres's and the planets' orbital elements,
122+
# which can be updated at any time, so only check for 1% tolerance, this
123+
# is enough to verify that columns are not being confused, and that
124+
# units are correct
125+
126+
for column, value in values.items():
127+
if u.isinstance(value, (u.Quantity, u.Angle)):
128+
assert u.isclose(res[column], value, rtol=0.001)
129+
elif value is np.ma.masked:
130+
assert is_masked(res[column])
131+
else:
132+
assert res[column] == value
133+
134+
# assert res['targetname'] == "1 Ceres (A801 AA)"
135+
# assert res['datetime_str'] == "2000-Jan-01 00:00:00.000"
136+
# assert res['solar_presence'] == ""
137+
# assert res['lunar_presence'] == ""
138+
# assert res['elongFlag'] == '/L'
139+
# assert res['airmass'] == 999
140+
141+
# assert is_masked(res['AZ'])
142+
# assert is_masked(res['EL'])
143+
# assert is_masked(res['magextinct'])
144+
145+
# assert_quantity_allclose(
146+
# [2451544.5,
147+
# 3.33, .120,
148+
# 188.7028, 9.09829, 34.40955, -2.68359,
149+
# 96.17083,
150+
# 161.3828, 10.4528, 2.551099027865, 0.1744491,
151+
# 2.26315121010004, -21.9390512, 18.82205467,
152+
# 95.3996, 22.5698, 292.551,
153+
# 296.85,
154+
# 184.3426241, 11.7996517, 289.864335,
155+
# 71.545654,
156+
# 0.0, 0.0],
157+
# [res['datetime_jd'],
158+
# res['H'], res['G'],
159+
# res['RA'], res['DEC'], res['RA_rate'], res['DEC_rate'],
160+
# res['illumination'],
161+
# res['EclLon'], res['EclLat'], res['r'], res['r_rate'],
162+
# res['delta'], res['delta_rate'], res['lighttime'],
163+
# res['elong'], res['alpha'], res['sunTargetPA'],
164+
# res['velocityPA'],
165+
# res['ObsEclLon'], res['ObsEclLat'], res['GlxLon'],
166+
# res['GlxLat'],
167+
# res['RA_3sigma'], res['DEC_3sigma']], rtol=1e-3)
168+
169+
# # V and surfbright tend to vary a lot more than the others. Give them a
170+
# # more generous test:
171+
# assert_quantity_allclose([8.239, 6.779], [res['V'], res['surfbright']], rtol=0.1)
63172

64173
def test_ephemerides_query_two(self):
65174
# check comet ephemerides using options

0 commit comments

Comments
 (0)