Skip to content

Add vec_table as an API Parameter for JPL Horizons #3273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions astroquery/jplhorizons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,36 @@ class Conf(_config.ConfigNamespace):
'VX': ('vx', 'AU/d'),
'VY': ('vy', 'AU/d'),
'VZ': ('vz', 'AU/d'),

'X_s': ('x_s', 'AU'),
'Y_s': ('y_s', 'AU'),
'Z_s': ('z_s', 'AU'),
'VX_s': ('vx_s', 'AU/d'),
'VY_s': ('vy_s', 'AU/d'),
'VZ_s': ('vz_s', 'AU/d'),

'A_s': ('a_s', 'AU'),
'C_s': ('c_s', 'AU'),
'N_s': ('n_s', 'AU'),
'VA_s': ('va_s', 'AU/d'),
'VC_s': ('vc_s', 'AU/d'),
'VN_s': ('vn_s', 'AU/d'),

'R_s': ('r_s', 'AU'),
'T_s': ('t_s', 'AU'),
# N_s is repeated here.
'VR_s': ('vr_s', 'AU/d'),
'VT_s': ('vt_s', 'AU/d'),
# VN_s is repeated here.

# Note: A_s is duplicated for POS (p) and ACN (a) uncertainties. It
# is up to the user to differentiate them! (They have the same units.)
'D_s': ('d_s', 'AU'),
# R_s is repeated here.
'VA_RA_s': ('va_ra_s', 'AU/d'),
'VD_DEC_s': ('va_dec_s', 'AU/d'),
# VR_s is repeated here.

'LT': ('lighttime', 'd'),
'RG': ('range', 'AU'),
'RR': ('range_rate',
Expand Down
52 changes: 43 additions & 9 deletions astroquery/jplhorizons/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -959,8 +959,8 @@
def vectors_async(self, *, get_query_payload=False,
closest_apparition=False, no_fragments=False,
get_raw_response=False, cache=True,
refplane='ecliptic', aberrations='geometric',
delta_T=False,):
refplane='ecliptic', vector_table="3",
aberrations='geometric', delta_T=False,):
"""
Query JPL Horizons for state vectors.

Expand Down Expand Up @@ -1057,6 +1057,14 @@

See :ref:`Horizons Reference Frames <jpl-horizons-reference-frames>`
in the astroquery documentation for details.

vector_table : string, optional
Selects the table of vectors to be returned. Options are numbers 1-6,
followed by any string of characters in the list [``'x'``, ``'a'``,
``'r'``, ``'p'``]. Default: ``'3'``.

See `Horizons User Manual <https://ssd-api.jpl.nasa.gov/doc/horizons.html#vec_table>`_
for details.

aberrations : string, optional
Aberrations to be accounted for: [``'geometric'``,
Expand Down Expand Up @@ -1156,6 +1164,7 @@
('VEC_CORR', {'geometric': '"NONE"',
'astrometric': '"LT"',
'apparent': '"LT+S"'}[aberrations]),
('VEC_TABLE', vector_table),
('VEC_DELTA_T', {True: 'YES', False: 'NO'}[delta_T]),
('OBJ_DATA', 'YES')]
)
Expand Down Expand Up @@ -1314,16 +1323,19 @@
elif (self.query_type == 'elements' and "JDTDB," in line):
headerline = str(line).split(',')
headerline[-1] = '_dump'
# read in vectors header line
elif (self.query_type == 'vectors' and "JDTDB," in line):
headerline = str(line).split(',')
headerline[-1] = '_dump'
# identify end of data block
if "$$EOE" in line:
data_end_idx = idx
# identify start of data block
if "$$SOE" in line:
data_start_idx = idx + 1

# read in vectors header line
# reading like this helps fix issues with commas after JDTDB
if self.query_type == 'vectors':
headerline_raw = str(src[idx - 2]).replace("JDTDB,", "JDTDB")
headerline = [" JDTDB", *str(headerline_raw).split("JDTDB")[1].split(',')]
headerline[-1] = '_dump'
Comment on lines +1333 to +1338
Copy link
Member

Choose a reason for hiding this comment

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

For the record, I haven't checked the correctness for all these changes, but trust the tests and the other review that these and the rest below are correct.

# read in targetname
if "Target body name" in line:
targetname = line[18:50].strip()
Expand Down Expand Up @@ -1404,6 +1416,20 @@
# strip whitespaces from column labels
headerline = [h.strip() for h in headerline]

# add numbers to duplicates
headerline_seen = {} # format - column_name: [headerline_idx, count]
dup_col_to_orig = {} # format - remapped_column_name: [original_column_name, index], used for later processing
for i, col in enumerate(headerline):
if col in headerline_seen:
headerline_seen[col][1] += 1
headerline[headerline_seen[col][0]] = f"{col}_1"
dup_col_to_orig[f"{col}_1"] = [col, 1]

Check warning on line 1426 in astroquery/jplhorizons/core.py

View check run for this annotation

Codecov / codecov/patch

astroquery/jplhorizons/core.py#L1424-L1426

Added lines #L1424 - L1426 were not covered by tests

headerline[i] = f"{col}_{headerline_seen[col][1]}"
dup_col_to_orig[headerline[i]] = [col, headerline_seen[col][1]]

Check warning on line 1429 in astroquery/jplhorizons/core.py

View check run for this annotation

Codecov / codecov/patch

astroquery/jplhorizons/core.py#L1428-L1429

Added lines #L1428 - L1429 were not covered by tests
else:
headerline_seen[col] = [i, 1]

# remove all 'Cut-off' messages
raw_data = [line for line in src[data_start_idx:data_end_idx]
if 'Cut-off' not in line]
Expand Down Expand Up @@ -1469,14 +1495,22 @@
# set column units
rename = []
for col in data.columns:
data[col].unit = column_defs[col][1]
if data[col].name != column_defs[col][0]:
# fetch from original definition, not remapped
col_unit = column_defs[dup_col_to_orig[col][0] if col in dup_col_to_orig.keys() else col]

data[col].unit = col_unit[1]
if data[col].name != col_unit[0]:
rename.append(data[col].name)

# rename columns
for col in rename:
try:
data.rename_column(data[col].name, column_defs[col][0])
if col in dup_col_to_orig.keys(): # preserve index on duplicate columns
to_rename = f"{column_defs[dup_col_to_orig[col][0]][0]}_{dup_col_to_orig[col][1]}"

Check warning on line 1509 in astroquery/jplhorizons/core.py

View check run for this annotation

Codecov / codecov/patch

astroquery/jplhorizons/core.py#L1509

Added line #L1509 was not covered by tests
else:
to_rename = column_defs[col][0]

data.rename_column(data[col].name, to_rename)
except KeyError:
pass

Expand Down
1 change: 1 addition & 0 deletions astroquery/jplhorizons/tests/test_jplhorizons.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ def test_vectors_query_payload():
('TP_TYPE', 'ABSOLUTE'),
('VEC_LABELS', 'YES'),
('VEC_CORR', '"NONE"'),
('VEC_TABLE', '3'),
('VEC_DELTA_T', 'NO'),
('OBJ_DATA', 'YES'),
('CENTER', "'500@10'"),
Expand Down
36 changes: 36 additions & 0 deletions astroquery/jplhorizons/tests/test_jplhorizons_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,42 @@ def test_vectors_query(self):
res['vz'],
res['lighttime'], res['range'],
res['range_rate']], rtol=1e-3)

def test_vectors_query_two(self):
# check values of Ceres for a given epoch, with vector_table="2xarp" to get all possible information
# orbital uncertainty of Ceres is basically zero
res = jplhorizons.Horizons(id='Ceres', location='500@10',
id_type='smallbody',
epochs=2451544.5).vectors(vector_table="2xarp",)[0]

assert res['targetname'] == "1 Ceres (A801 AA)"
assert res['datetime_str'] == "A.D. 2000-Jan-01 00:00:00.0000"

assert_quantity_allclose(
[2451544.5,
-2.377530292832982E+00, 8.007772359639206E-01,
4.628376133882323E-01, -3.605422228805115E-03,
-1.057883336698096E-02, 3.379790443661611E-04,
1.69636278E-10, 4.38650236E-10, 1.97923277E-10,
1.94851194E-12, 5.56918627E-13, 2.05288488E-12,
4.69444042E-10, 2.17944530E-11, 1.98774780E-10,
8.81447488E-14, 1.83081418E-12, 2.22745222E-12,
2.54838011E-11, 4.69258226E-10, 1.98774780E-10,
1.83140694E-12, 7.48243991E-14, 2.22745222E-12,
4.68686492E-10, 2.00119134E-10, 2.54838011E-11,
1.17091788E-13, 2.22563061E-12, 1.83140694E-12,],
[res['datetime_jd'],
res['x'], res['y'],
res['z'], res['vx'],
res['vy'], res['vz'],
res['x_s'], res['y_s'], res['z_s'],
res['vx_s'], res['vy_s'], res['vz_s'],
res['a_s_1'], res['c_s'], res['n_s_1'],
res['va_s'], res['vc_s'], res['vn_s_1'],
res['r_s_1'], res['t_s'], res['n_s_2'],
res['vr_s_1'], res['vt_s'], res['vn_s_2'],
res['a_s_2'], res['d_s'], res['r_s_2'],
res['va_ra_s'], res['va_dec_s'], res['vr_s_2'],], rtol=1e-3)

def test_vectors_query_raw(self):
# deprecated as of #2418
Expand Down
Loading