Skip to content

Commit e492b9b

Browse files
authored
Merge pull request #2794 from mkelley/jplhorizons-updated-columns-2023.08
Update jplhorizons columns
2 parents 8957201 + a3d52ad commit e492b9b

File tree

5 files changed

+186
-59
lines changed

5 files changed

+186
-59
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ jplhorizons
149149
- Topocentric coordinates can now be specified for both center and target in observer
150150
and vector queries. [#2625]
151151

152+
- Updated returned table columns to match Horizons's updates. [#2794]
153+
154+
- Assign units to ``"hour_angle"``, ``"solartime"``, and ``"siderealtime"`` columns. [#2794]
155+
152156
jplsbdb
153157
^^^^^^^
154158

astroquery/jplhorizons/__init__.py

Lines changed: 17 additions & 10 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')
@@ -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_app', 'arcsec/hour'),
75+
'I_d(DEC)/dt': ('DEC_ICRF_rate_app', 'arcsec/hour'),
7576
'Azi_(a-app)': ('AZ', 'deg'),
7677
'Elev_(a-app)': ('EL', 'deg'),
7778
'Azimuth_(a-app)': ('AZ', 'deg'),
@@ -83,7 +84,7 @@ class Conf(_config.ConfigNamespace):
8384
'X_(sat-prim)': ('sat_X', 'arcsec'),
8485
'Y_(sat-prim)': ('sat_Y', 'arcsec'),
8586
'SatPANG': ('sat_PANG', 'deg'),
86-
'L_Ap_Sid_Time': ('siderealtime', '---'),
87+
'L_Ap_Sid_Time': ('siderealtime', "hour"),
8788
'a-mass': ('airmass', '---'),
8889
'mag_ex': ('magextinct', 'mag'),
8990
'APmag': ('V', 'mag'),
@@ -144,7 +145,7 @@ class Conf(_config.ConfigNamespace):
144145
'N.Pole-DC': ('NPole_DEC', 'deg'),
145146
'GlxLon': ('GlxLon', 'deg'),
146147
'GlxLat': ('GlxLat', 'deg'),
147-
'L_Ap_SOL_Time': ('solartime', '---'),
148+
'L_Ap_SOL_Time': ('solartime', 'hour'),
148149
'399_ins_LT': ('earth_lighttime', 'minute'),
149150
'RA_3sigma': ('RA_3sigma', 'arcsec'),
150151
'DEC_3sigma': ('DEC_3sigma', 'arcsec'),
@@ -159,11 +160,17 @@ class Conf(_config.ConfigNamespace):
159160
'DOP_X_3sig': ('XBand_3sigma', 'Hz'),
160161
'RT_delay_3sig': ('DoppDelay_3sigma', 'second'),
161162
'Tru_Anom': ('true_anom', 'deg'),
162-
'r-L_Ap_Hour_Ang': ('hour_angle', '---'),
163-
'L_Ap_Hour_Ang': ('hour_angle', '---'),
163+
'r-L_Ap_Hour_Ang': ('hour_angle', 'hour'),
164+
'L_Ap_Hour_Ang': ('hour_angle', 'hour'),
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/core.py

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,8 @@ def ephemerides_async(self, *, airmass_lessthan=99,
445445
+------------------+-----------------------------------------------+
446446
| true_anom | True Anomaly (float, deg, ``Tru_Anom``) |
447447
+------------------+-----------------------------------------------+
448-
| hour_angle | local apparent hour angle (string, |
449-
| | sexagesimal angular hours, ``L_Ap_Hour_Ang``) |
448+
| hour_angle | local apparent hour angle (float, |
449+
| | hour, ``L_Ap_Hour_Ang``) |
450450
+------------------+-----------------------------------------------+
451451
| alpha_true | true phase angle (float, deg, ``phi``) |
452452
+------------------+-----------------------------------------------+
@@ -456,6 +456,45 @@ def ephemerides_async(self, *, airmass_lessthan=99,
456456
| PABLat | phase angle bisector latitude |
457457
| | (float, deg, ``PAB-LAT``) |
458458
+------------------+-----------------------------------------------+
459+
| App_Lon_Sun | apparent target-centered longitude of the Sun |
460+
| | (float, hour, ``App_Lon_Sun``) |
461+
+------------------+-----------------------------------------------+
462+
| RA_ICRF_app | airless apparent right ascension of the target|
463+
| | in the ICRF |
464+
| | (float, hour, ``RA_(ICRF-a-app)``) |
465+
+------------------+-----------------------------------------------+
466+
| DEC_ICRF_app | airless apparent declination of the target |
467+
| | in the ICRF |
468+
| | (float, deg, ``DEC_(ICRF-a-app)``) |
469+
+------------------+-----------------------------------------------+
470+
| RA_ICRF_rate_app | RA rate of change in the targets' ICRF |
471+
| | multiplied by the cosine of declination |
472+
| | (float, arcsec/hour, ``I_dRA*cosD``) |
473+
+------------------+-----------------------------------------------+
474+
| DEC_ICRF_rate_app| DEC rate of change in the targets' ICRF |
475+
| | (float, arcsec/hour, ``I_d(DEC)/dt``) |
476+
+------------------+-----------------------------------------------+
477+
| Sky_motion | Total apparent angular rate in the plane-of- |
478+
| | sky |
479+
| | (float, arcsec/minute, ``Sky_motion``) |
480+
+------------------+-----------------------------------------------+
481+
| Sky_mot_PA | position angle direction of motion in the |
482+
| | plane-of-sky |
483+
| | (float, deg, ``Sky_mot_PA``) |
484+
+------------------+-----------------------------------------------+
485+
| RelVel-ANG | flight path angle of the target's relative |
486+
| | motion with respect to the observer's |
487+
| | line-of-sight |
488+
| | (float, deg, ``RelVel-ANG``) |
489+
+------------------+-----------------------------------------------+
490+
| Lun_Sky_Brt | Sky brightness due to moonlight |
491+
| | (float, mag, ``Lun_Sky_Brt``) |
492+
+------------------+-----------------------------------------------+
493+
| sky_SNR | approximate visual signal-to-noise ratio of |
494+
| | the target's brightness divided by lunar sky |
495+
| | brightness |
496+
| | (float, unitless, ``sky_SNR``) |
497+
+------------------+-----------------------------------------------+
459498
460499
461500
Parameters
@@ -1276,7 +1315,7 @@ def _parse_result(self, response, verbose=None):
12761315
break
12771316
raise ValueError(('Ambiguous target name; provide '
12781317
'unique id:\n%s' %
1279-
'\n'.join(src[idx + 2:end_idx])))
1318+
'\n'.join(src[idx + 2: end_idx])))
12801319
# catch unknown target
12811320
if ("Matching small-bodies" in line and "No matches found" in src[idx + 1]):
12821321
raise ValueError(('Unknown target ({:s}). Maybe try '

astroquery/jplhorizons/tests/test_jplhorizons_remote.py

Lines changed: 122 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,59 +7,136 @@
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
1314

1415

1516
@pytest.mark.remote_data
1617
class TestHorizonsClass:
17-
1818
def test_ephemerides_query(self):
19-
# check values of Ceres for a given epoch
20-
# orbital uncertainty of Ceres is basically zero
21-
res = jplhorizons.Horizons(id='Ceres', location='500',
22-
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)
19+
# check all values of Ceres for a given epoch
20+
quantities = ",".join(str(q) for q in range(1, 49))
21+
horizons = jplhorizons.Horizons(
22+
id="Ceres", location="I41", id_type="smallbody", epochs=2451544.5
23+
)
24+
res = horizons.ephemerides(quantities=quantities)
25+
26+
# Retrieved 2023 Aug 01:
27+
values = {
28+
"targetname": "1 Ceres (A801 AA)",
29+
"H": 3.33,
30+
"G": 0.120,
31+
"datetime_jd": 2451544.5,
32+
"datetime_str": "2000-Jan-01 00:00:00.000",
33+
"solar_presence": "*",
34+
"lunar_presence": "",
35+
"RA": 188.70240 * u.deg,
36+
"DEC": 9.09758 * u.deg,
37+
"RA_app": 188.69858 * u.deg,
38+
"DEC_app": 9.09806 * u.deg,
39+
"RA_rate": 35.17815 * u.arcsec / u.hr,
40+
"DEC_rate": -2.74237 * u.arcsec / u.hr,
41+
"AZ": 325.548736 * u.deg,
42+
"EL": -41.062749 * u.deg,
43+
"AZ_rate": 781.92 * u.arcsec / u.minute,
44+
"EL_rate": -426.18 * u.arcsec / u.minute,
45+
"sat_X": -304791.02 * u.arcsec,
46+
"sat_Y": 115814.995 * u.arcsec,
47+
"sat_PANG": 277.607 * u.deg,
48+
"siderealtime": 22.8737254836 * u.hr,
49+
"airmass": 999,
50+
"magextinct": np.ma.masked,
51+
"V": 8.259 * u.mag,
52+
"surfbright": 6.799 * u.mag / u.arcsec**2,
53+
"illumination": 96.17086 * u.percent,
54+
"illum_defect": 0.0225 * u.arcsec,
55+
"sat_sep": 343433.5 * u.arcsec,
56+
"sat_vis": "*",
57+
"ang_width": 0.587419 * u.arcsec,
58+
"PDObsLon": 302.274926 * u.deg,
59+
"PDObsLat": -3.982640 * u.deg,
60+
"PDSunLon": 279.670960 * u.deg,
61+
"PDSunLat": -3.621151 * u.deg,
62+
"SubSol_ang": 112.55 * u.deg,
63+
"SubSol_dist": 0.11 * u.arcsec,
64+
"NPole_ang": 22.6777 * u.deg,
65+
"NPole_dist": -0.271 * u.arcsec,
66+
"EclLon": 161.3828 * u.deg,
67+
"EclLat": 10.4528 * u.deg,
68+
"r": 2.551099025883 * u.au,
69+
"r_rate": 0.1744491 * u.km / u.s,
70+
"delta": 2.26317926925737 * u.au,
71+
"delta_rate": -21.7732311 * u.km / u.s,
72+
"lighttime": 18.82228803 * u.minute,
73+
"vel_sun": 19.3602212 * u.km / u.s,
74+
"vel_obs": 27.0721344 * u.km / u.s,
75+
"elong": 95.3982 * u.deg,
76+
"elongFlag": "/L",
77+
"alpha": 22.5696 * u.deg,
78+
"lunar_elong": 32.9 * u.deg,
79+
"lunar_illum": 27.4882 * u.percent,
80+
"sat_alpha": 62.0400 * u.deg,
81+
"sunTargetPA": 292.552 * u.deg,
82+
"velocityPA": 296.849 * u.deg,
83+
"OrbPlaneAng": -1.53489 * u.deg,
84+
"constellation": "Vir",
85+
"TDB-UT": 64.183887 * u.s,
86+
"ObsEclLon": 184.3424861 * u.deg,
87+
"ObsEclLat": 11.7988212 * u.deg,
88+
"NPole_RA": 291.42763 * u.deg,
89+
"NPole_DEC": 66.76033 * u.deg,
90+
"GlxLon": 289.863376 * u.deg,
91+
"GlxLat": 71.544870 * u.deg,
92+
"solartime": 16.1587871790 * u.hour,
93+
"earth_lighttime": 0.000354 * u.minute,
94+
"RA_3sigma": 0.000 * u.arcsec,
95+
"DEC_3sigma": 0.000 * u.arcsec,
96+
"SMAA_3sigma": 0.00012 * u.arcsec,
97+
"SMIA_3sigma": 0.00005 * u.arcsec,
98+
"Theta_3sigma": -24.786 * u.deg,
99+
"Area_3sigma": 0.0000000 * u.arcsec**2,
100+
"RSS_3sigma": 0.000 * u.arcsec,
101+
"r_3sigma": 0.0904 * u.km,
102+
"r_rate_3sigma": 0.0000000 * u.km / u.s,
103+
"SBand_3sigma": 0.00 * u.Hz,
104+
"XBand_3sigma": 0.00 * u.Hz,
105+
"DoppDelay_3sigma": 0.000001 * u.s,
106+
"true_anom": 7.1181 * u.deg,
107+
"hour_angle": 10.293820034 * u.hour,
108+
"alpha_true": 22.5691 * u.deg,
109+
"PABLon": 172.8355 * u.deg,
110+
"PABLat": 11.3478 * u.deg,
111+
"App_Lon_Sun": 309.1603680 * u.deg,
112+
"RA_ICRF_app": 188.70238 * u.deg,
113+
"DEC_ICRF_app": 9.09628 * u.deg,
114+
"RA_ICRF_rate_app": 35.17809 * u.arcsec / u.hour,
115+
"DEC_ICRF_rate_app": -2.74321 * u.arcsec / u.hour,
116+
"Sky_motion": 0.5880814 * u.arcsec / u.minute,
117+
"Sky_mot_PA": 94.457576 * u.deg,
118+
"RelVel-ANG": -53.53947 * u.deg,
119+
"Lun_Sky_Brt": np.ma.masked,
120+
"sky_SNR": np.ma.masked,
121+
}
122+
123+
# the ephemeris changes with Ceres's and the planets' orbital elements,
124+
# which can be updated at any time, so only check for 0.1% tolerance, this
125+
# is enough to verify that most columns are not being confused, and that
126+
# units are correct
127+
128+
for column, value in values.items():
129+
if isinstance(value, (u.Quantity, Angle)):
130+
# A few columns have varied a lot more than the others
131+
if column in ["H", "G", "V", "surfbright"]:
132+
rtol = 0.1
133+
else:
134+
rtol = 0.001
135+
assert u.isclose(res[column], value, rtol=rtol)
136+
elif value is np.ma.masked:
137+
assert is_masked(res[column])
138+
else:
139+
assert res[column] == value
63140

64141
def test_ephemerides_query_two(self):
65142
# check comet ephemerides using options

docs/jplhorizons/jplhorizons.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ skips the query and only returns the query payload. To pass additional settings
244244
to the request use the ``optional_settings`` passing a key-value
245245
dictionary.
246246

247-
:meth:`~astroquery.jplhorizons.HorizonsClass.ephemerides` queries by default all
247+
:meth:`~astroquery.jplhorizons.HorizonsClass.ephemerides` queries by default most
248248
available quantities from the JPL Horizons servers. This might take a while. If
249249
you are only interested in a subset of the available quantities, you can query
250250
only those. The corresponding optional parameter to be set is ``quantities``.

0 commit comments

Comments
 (0)