Skip to content

Commit 5b1435c

Browse files
committed
Better separate id and location coordinate formatting and test.
1 parent 42154e3 commit 5b1435c

File tree

2 files changed

+83
-9
lines changed

2 files changed

+83
-9
lines changed

astroquery/jplhorizons/core.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -615,7 +615,7 @@ def ephemerides_async(self, *, airmass_lessthan=99,
615615
if self.id is None:
616616
raise ValueError("'id' parameter not set. Query aborted.")
617617
elif isinstance(self.id, dict):
618-
commandline = "g:" + self._format_site_coords(self.id)
618+
commandline = self._format_id_coords(self.id)
619619
else:
620620
commandline = str(self.id)
621621
if self.location is None:
@@ -850,16 +850,20 @@ def elements_async(self, *, get_query_payload=False,
850850

851851
URL = conf.horizons_server
852852

853-
# check for required information
853+
# check for required information and assemble commandline stub
854854
if self.id is None:
855855
raise ValueError("'id' parameter not set. Query aborted.")
856+
elif isinstance(self.id, dict):
857+
commandline = self._format_id_coords(self.id)
858+
else:
859+
commandline = str(self.id)
860+
856861
if self.location is None:
857862
self.location = '500@10'
858863
if self.epochs is None:
859864
self.epochs = Time.now().jd
860865

861-
# assemble commandline based on self.id_type
862-
commandline = str(self.id)
866+
# expand commandline based on self.id_type
863867
if self.id_type in ['designation', 'name',
864868
'asteroid_name', 'comet_name']:
865869
commandline = ({'designation': 'DES=',
@@ -878,7 +882,7 @@ def elements_async(self, *, get_query_payload=False,
878882
commandline += ' NOFRAG;'
879883

880884
if isinstance(self.location, dict):
881-
raise ValueError(('cannot use topographic position in orbital'
885+
raise ValueError(('cannot use topographic position in orbital '
882886
'elements query'))
883887

884888
# configure request_payload for ephemerides query
@@ -1099,7 +1103,7 @@ def vectors_async(self, *, get_query_payload=False,
10991103
if self.id is None:
11001104
raise ValueError("'id' parameter not set. Query aborted.")
11011105
elif isinstance(self.id, dict):
1102-
commandline = "g:" + self._format_site_coords(self.id)
1106+
commandline = self._format_id_coords(self.id)
11031107
else:
11041108
commandline = str(self.id)
11051109
if self.location is None:
@@ -1211,6 +1215,7 @@ def _prep_loc_dict(loc_dict, attr_name):
12111215
@staticmethod
12121216
def _location_to_params(loc_dict):
12131217
"""translate a 'location' dict to request parameters"""
1218+
12141219
location = {
12151220
"CENTER": f"coord@{loc_dict['body']}",
12161221
"COORD_TYPE": "GEODETIC",
@@ -1219,10 +1224,20 @@ def _location_to_params(loc_dict):
12191224
return location
12201225

12211226
@staticmethod
1222-
def _format_site_coords(coords):
1223-
# formats lon/lat/elevation/body (e.g., id and location dictionaries) for the Horizons API
1227+
def _format_coords(coords):
1228+
"""Dictionary to Horizons API formatted lon/lat/elevation coordinate triplet."""
12241229
return (f"{coords['lon'].to_value('deg')},{coords['lat'].to_value('deg')},"
1225-
f"{coords['elevation'].to_value('km')}@{coords['body']}")
1230+
f"{coords['elevation'].to_value('km')}")
1231+
1232+
@staticmethod
1233+
def _format_site_coords(coords):
1234+
"""`location` dictionary to SITE_COORDS parameter."""
1235+
return HorizonsClass._format_coords(coords)
1236+
1237+
@staticmethod
1238+
def _format_id_coords(coords):
1239+
"""`id` dictionary to COMMAND parameter's coordinate format."""
1240+
return f"g:{HorizonsClass._format_coords(coords)}@{coords['body']}"
12261241

12271242
def _parse_result(self, response, verbose=None):
12281243
"""

astroquery/jplhorizons/tests/test_jplhorizons.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from numpy.ma import is_masked
88
from astropy.tests.helper import assert_quantity_allclose
99
from astropy.utils.exceptions import AstropyDeprecationWarning
10+
from astropy import units as u
1011

1112
from astroquery.utils.mocks import MockResponse
1213
from ...query import AstroQuery
@@ -291,3 +292,61 @@ def test_id_type_deprecation():
291292

292293
with pytest.warns(AstropyDeprecationWarning):
293294
jplhorizons.Horizons(id='Ceres', id_type='majorbody')
295+
296+
297+
def test_id_geodetic_coords():
298+
"""Test target based on geodetic coordinates.
299+
300+
From the Horizons manual:
301+
302+
For example, while 301 specifies the target to be the center of the Moon,
303+
and Apollo-11 @ 301 specifies the Apollo-11 landing site as target, the
304+
following:
305+
306+
g: 348.8, -43.3, 0 @ 301
307+
308+
specifies an ephemeris for the crater Tycho on the Moon (body 301), at
309+
geodetic (planetodetic) coordinates 348.8 degrees east longitude, -43.3
310+
degrees latitude (south), and zero km altitude with respect to the Moon’s
311+
mean-Earth reference frame and ellipsoid surface.
312+
313+
"""
314+
315+
target = {
316+
"lon": 348.8 * u.deg,
317+
"lat": -43.3 * u.deg,
318+
"elevation": 0 * u.m,
319+
"body": 301
320+
}
321+
322+
q = jplhorizons.Horizons(id=target)
323+
for payload in (q.ephemerides(get_query_payload=True),
324+
q.vectors(get_query_payload=True),
325+
q.elements(get_query_payload=True)):
326+
assert payload["COMMAND"] == '"g:348.8,-43.3,0.0@301"'
327+
328+
329+
def test_location_topocentric_coords():
330+
"""Test location from topocentric coordinates.
331+
332+
Similar to `test_id_geodetic_coords`.
333+
334+
"""
335+
336+
location = {
337+
"lon": 348.8 * u.deg,
338+
"lat": -43.3 * u.deg,
339+
"elevation": 0 * u.m,
340+
"body": 301
341+
}
342+
343+
q = jplhorizons.Horizons(id=399, location=location)
344+
for payload in (q.ephemerides(get_query_payload=True),
345+
q.vectors(get_query_payload=True)):
346+
assert payload["CENTER"] == 'coord@301'
347+
assert payload["COORD_TYPE"] == "GEODETIC"
348+
assert payload["SITE_COORD"] == "'348.8,-43.3,0.0'"
349+
350+
# not allowed for elements
351+
with pytest.raises(ValueError):
352+
q.elements(get_query_payload=True)

0 commit comments

Comments
 (0)