¿API de Python para JPL Horizons?

Encontré el paquete de python HorizonJPL en Python Package Index , pero parece que está limitado a la actividad en 2013. Cuando voy a la página de documentación vinculada https://docs.google.com/document/d/1g9q3ln9LVAATOZ15986HLTCaqcAj_Jd8e_jOGS3YWrE/pub the info es bastante escaso, y los dos enlaces allí conducen a un callejón sin salida en japonés (abajo).

¿Hay alguna manera de acceder a JPL Horizons para tablas de datos (como lo estoy haciendo aquí ) desde una secuencia de comandos de Python? En otras palabras, quiero crear una consulta de URL y recibir un json de texto con vectores de estado a cambio usando urllibo urllib2.


Actualización: Este es un ejemplo típico de lo que quiero hacer:

ingrese la descripción de la imagen aquí


Esto es lo que se muestra en el sitio de pypi: parece que hay nombres/identificadores, pero no sé cómo consultarlos.

Documentación API

https://docs.google.com/document/d/1g9q3ln9LVAATOZ15986HLTCaqcAj_Jd8e_jOGS3YWrE/pub

Recursos

Sistema de datos planetarios: http://pds.nasa.gov/

Laboratorios de propulsión a chorro: http://www.jpl.nasa.gov/

Manual del usuario de HORIZONTE: http://ssd.jpl.nasa.gov/?horizons_doc

Colaboradores


Mateo Mihok (@mattmattmatt)

Dexter Jagula (@djagula)

Siddarth Kalra (@SiddarthKalra)

Tiago Moreira (@Kamots)

Esto es lo que sucede cuando pruebo los enlaces en el documento de Google :

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Si esto no atrae ninguna ayuda en, digamos, otra semana, entonces tal vez sea un buen candidato para la migración a stackoverflow en ese momento. La pythonetiqueta es crítica allí.
¿Ha intentado utilizar telnetlibpara acceder a la interfaz de telnet?
@2012rcampion OK - ¡Lo investigaré hoy! Si lo entiendo correctamente, tendría que escribir una secuencia de comandos de python que básicamente emula a una persona que escribe comandos y recibe indicaciones. Es posible que alguien haya hecho un buen trabajo con esto y haya escrito un buen envoltorio de interfaz; mi objetivo final es ver si alguien ha hecho que algo así esté disponible para el público en general. Mientras tanto , definitivamente probaré lo que me has sugerido. ¡¡Gracias!!
Si no tiene la intención de usar el script durante mucho tiempo, no tiene que procesar las indicaciones en absoluto. Lo que hice fue obtener un conjunto de datos manualmente, luego hacer que mi secuencia de comandos básicamente reprodujera la misma sesión con un parámetro configurable.
@2012rcampion Bien entendido. El manual es útil, pero estoy buscando sesiones de ejemplo, que son más fáciles de digerir para mí. He agregado un ejemplo de lo que quiero hacer en la pregunta. Si lo hago funcionar, lo publicaré como respuesta; si alguien más publica una sesión de telnet de ejemplo similar o un script primero, ¡Dios mío, me veré obligado a aceptarlo ! :)
@uhoh De hecho, intenté comenzar con una API de Java para esto después de que me lo presentaras. La forma más fácil de hacer una API sería usar un rastreador de formularios y ejecutar consultas contra el formulario en la página. Puede interceptar los datos enviados y replicarlos mediante una solicitud POST en el archivo .cgi de backend. Estoy de vacaciones en este momento, pero si quieres que publique un ejemplo de cómo hacer esto en python, estaré encantado de ayudarte. Incluso si no hay API, hay MUCHO que puede hacer con formularios y solicitudes HTTP simples. Incluso el telnet podría funcionar muy bien para automatizar algo.

Respuestas (3)

callhorizons está obsoleto ahora y se refiere a la biblioteca de python, astroqueryque ahora parece ser el camino a seguir.

astroquery ( GitHub , readthedocs ) es "un paquete afiliado a astropy que contiene una colección de herramientas para acceder a datos astronómicos en línea. Cada servicio web tiene su propio subpaquete", donde hacer consultas de Horizons es solo una de muchas opciones. Es parte del Proyecto Astropy más grande, que es "un esfuerzo de la comunidad para desarrollar un paquete básico común para Astronomy in Python y fomentar un ecosistema de paquetes de astronomía interoperables".

Recomiendo leer la página de documentación para las consultas de JPL Horizons para astroquery que se pueden encontrar aquí: https://astroquery.readthedocs.io/en/latest/jplhorizons/jplhorizons.html Enumera algunos buenos ejemplos, por ejemplo:

from astroquery.jplhorizons import Horizons
obj = Horizons(id='Ceres', location='568',
                epochs={'start':'2010-01-01', 'stop':'2010-03-01', 'step':'10d'})
eph = obj.ephemerides()
print(eph)

targetname    datetime_str   datetime_jd ...   GlxLat  RA_3sigma DEC_3sigma
   ---            ---             d      ...    deg      arcsec    arcsec
---------- ----------------- ----------- ... --------- --------- ----------
   1 Ceres 2010-Jan-01 00:00   2455197.5 ... 24.120057       0.0        0.0
   1 Ceres 2010-Jan-11 00:00   2455207.5 ... 20.621496       0.0        0.0
   1 Ceres 2010-Jan-21 00:00   2455217.5 ... 17.229529       0.0        0.0
   1 Ceres 2010-Jan-31 00:00   2455227.5 ...  13.97264       0.0        0.0
   1 Ceres 2010-Feb-10 00:00   2455237.5 ... 10.877201       0.0        0.0
   1 Ceres 2010-Feb-20 00:00   2455247.5 ...  7.976737       0.0        0.0

También recomiendo hojear los documentos de HorizonsClass . En particular, inicialmente estaba confundido de que establecer el objetivo id=399no apuntaba a la Tierra, pero eso se debió a que la clase también toma un id-typeargumento que por defecto es smallbody(asteroides y similares), y necesitaba cambiarse a majorbody.

Parece muy sencillo de usar, y es claramente el camino a seguir ahora.

PD: Mencionaré que recibí un error KeyError: 'Obsrv-lon'para mi consulta en particular, pero el problema está siendo investigado.

Esta es una buena información, pero se beneficiaría de una explicación un poco más amplia en la publicación en lugar de solo un enlace. ¿El proyecto de astroconsulta tiene un archivo Léame o una declaración de misión que podría citar aquí, tal vez?
Ok, agregué un poco más de información :)

¡Ya hay uno! Acabo de encontrarme con el paquete python callhorizons en github y Python Package Index .

Hay más información en readthedocis.io que ayuda a explicar cómo hacer consultas si está buscando asteroides/cuerpos menores, para los cuales hay miles de millones y los nombres pueden ser nombres de personas o alfanuméricos.

Intentaré probarlo más y actualizar aquí. Parece que hay mucha capacidad aquí, pero no puedo decirlo con certeza todavía. Hay una publicación de blog de un astrónomo , pero es de enero de 2016.

Fue una instalación de una línea, es decir, pip install callhorizons. ¡Luego escribí la demostración simple en la parte superior de la página de PyPI y obtuve una respuesta!

>>> import callhorizons
>>> eros = callhorizons.query('Eros')
>>> eros.set_discreteepochs([2457446.177083, 2457446.182343])
>>> eros.get_ephemerides(568)
2
>>> print(eros['RA'], eros['DEC'])
(array([ 292.46003,  292.46332]), array([-27.44392, -27.44335]))
>>>

¡Vaya pitón!

La versión actual es un script de Python puro y contiene el comentario:

CALLHORIZONS - a Python interface to access JPL HORIZONS
ephemerides and orbital elements.

This module provides a convenient python interface to the JPL
HORIZONS system by directly accessing and parsing the HORIZONS
website. Ephemerides can be obtained through get_ephemerides,
orbital elements through get_elements. Function
export2pyephem provides an interface to the PyEphem module.

michael.mommert (at) nau.edu, latest version: v1.0.5, 2017-05-05.
This code is inspired by code created by Alex Hagen.

Actualmente, solo genera la URL de consulta para una tabla de observadores, no vectores de estado, pero sin duda podría personalizarse fácilmente para obtener vectores de estado. Aquí hay una pequeña parte, se agregan parámetros adicionales a la cadena de URL antes de que se use.

### construct URL for HORIZONS query
url = "http://ssd.jpl.nasa.gov/horizons_batch.cgi?batch=l" \
      + "&TABLE_TYPE='OBSERVER'" \
      + "&QUANTITIES='" + str(quantities) + "'" \
      + "&CSV_FORMAT='YES'" \
      + "&ANG_FORMAT='DEG'" \
      + "&CAL_FORMAT='BOTH'" \
      + "&SOLAR_ELONG='" + str(solar_elongation[0]) + "," \
      + str(solar_elongation[1]) + "'" \
      + "&CENTER='"+str(observatory_code)+"'"

Está bien, prueba con una nave espacial, también vista desde Mauna Kea. Desde JPL Horizons con la siguiente configuración:

ingrese la descripción de la imagen aquí

da (se desplaza horizontalmente):

**********************************************************************************************************************************
Date_________JDUT, , ,R.A._(ICRF/J2000.0), DEC_(ICRF/J2000.0),  APmag, S-brt,            delta,     deldot,    S-O-T,/r,    S-T-O,
**********************************************************************************************************************************
$$SOE
2457754.500000000,*,m,20 01 24.54,-56 59 28.4,   n.a.,  n.a., 1.7047550022E+10, 18.9796569,  36.6514,/T,   0.2976,
2457784.500000000,*,m,20 03 22.69,-56 58 00.2,   n.a.,  n.a., 1.7080283550E+10,  6.5439542,  40.6419,/L,   0.3218,
2457814.500000000,*,m,20 05 08.36,-57 01 24.2,   n.a.,  n.a., 1.7082950019E+10, -3.4910462,  59.2751,/L,   0.4270,
2457844.500000000,*,m,20 06 16.02,-57 09 10.1,   n.a.,  n.a., 1.7065586218E+10, -8.4792450,  82.4692,/L,   0.4975,
2457874.500000000,*,m,20 06 30.25,-57 19 39.5,   n.a.,  n.a., 1.7043227392E+10, -7.3046878, 106.0860,/L,   0.4870,
2457904.500000000,*,m,20 05 49.21,-57 30 32.2,   n.a.,  n.a., 1.7031649793E+10, -0.4854246, 127.5819,/L,   0.4048,
2457934.500000000,*,m,20 04 24.98,-57 39 21.6,   n.a.,  n.a., 1.7043463848E+10, 10.1577911, 141.9907,/L,   0.3144,
$$EOE
**********************************************************************************************************************************

Comparar con este script:

import callhorizons
import numpy as np

JDs = [2457754.5 + 30*i for i in range(7)] # 01-Jan-2017 00:00 UTC + n*30 days

V2  = callhorizons.query(-32, smallbody=False)     # -32 for Voyager 2

V2.set_discreteepochs(JDs)

V2.get_ephemerides(568)    # 568 for Mauna Kea 

radecs = np.vstack((V2['RA'], V2['DEC']))

for JD, radec in zip(JDs, radecs.T):
    print JD, radec

Un control al azar muestra que estos son iguales, ¡genial! Para su información, el gran movimiento aparente se debe a la paralaje: la Tierra cambia su perspectiva cada mes. Después de un año, la posición en realidad solo cambia unas pocas décimas de grado.

2457754.5 [ 300.35226  -56.99121]
2457784.5 [ 300.84454  -56.96671]
2457814.5 [ 301.28482  -57.0234 ]
2457844.5 [ 301.56676  -57.1528 ]
2457874.5 [ 301.62605  -57.32765]
2457904.5 [ 301.45504  -57.50895]
2457934.5 [ 301.10407  -57.65601]
¡Parece una biblioteca genial! Habría recomendado SpiceyPy, que es una interfaz para SPICE, y SPICE ejecuta JPL Horizons. Pero luego tienes que reescribir toda la lógica.
@ChrisR Voy a echar un vistazo. ¿Puedes considerar dejar una respuesta corta mencionando SpiceyPy? Los comentarios son, por definición, temporales, e incluso si no coinciden perfectamente con "¿API de Python para JPL Horizons?" hace algo lo suficientemente similar como para que los futuros lectores se beneficien al conocerlo. No tiene que ser una respuesta larga, solo un enlace y una explicación de que cuando uno quiere acceder a Horizons automáticamente, en realidad solo está accediendo a SPICE y, por lo tanto, debe saber que el intermediario de Horizons no siempre es necesario.

Elija sus parámetros de entrada en Horizons, luego haga clic en este enlace (enlace de "mostrar datos de archivo por lotes" en la página de Horizons): https://ssd.jpl.nasa.gov/horizons.cgi?show=1#results

Obtendrás algo como esto:

!$$SOF

COMANDO= '-64'

CENTRO= '500@0'

MAKE_EPHEM= 'SI'

TABLE_TYPE= 'VECTORES'

START_TIME= '2018-10-1'

STOP_TIME= '2018-10-30'

STEP_SIZE= '1 d'

OUT_UNITS= 'AU-D'

REF_PLANO= 'ECLÍPTICA'

REF_SYSTEM= 'J2000'

VECT_CORR= 'NINGUNO'

VEC_LABELS= 'SI'

VEC_DELTA_T= 'NO'

CSV_FORMAT= 'NO'

OBJ_DATA= 'SI'

VEC_TABLA= '3'

!$$EOF

Elimina las líneas que empiezan por "!".

Copie el texto restante en su editor de texto+hexadecimal favorito y realice estos reemplazos:

0d0a --> & (retorno de carro a "&") ' --> %27 espacio --> %20

Obtendrá una sola línea para agregar a esta URL parcial:

https://ssd.jpl.nasa.gov/horizons_batch.cgi?batch=1&

El resultado está en formato "CSV mixto" (es decir, CSV con basura...)

Esta fuente de JavaScript convertirá la salida de Horizons en una URL válida y la abrirá:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>NASA Horizons URL generator</title>
  </head>
  <script src="js/jquery.js"></script>
  <script>
  $( document ).ready(function() { // After page load is complete...
		$("#btnGo" ).click(function() { // Associate function to the button to monitor clicking.
			commandsText = $('textarea#commands').val(); // Upon clicking, assign textarea content to variable.		  
			commandsText = commandsText.replace(/\r/g,'&'); // Replace carriage returns
			commandsText = commandsText.replace(/\n/g,'&');	 // Replace carriage returns	  
			commandsText = commandsText.replace(/ /g,"%20"); // Replace spaces			  
			commandsText = commandsText.replace(/\'/g,'%27'); // Replace quotes	  
			var fullURL = 	"https://ssd.jpl.nasa.gov/horizons_batch.cgi?batch=1&" + commandsText; //* Prepend URL base
			$('textarea#URL').val(fullURL)           
            window.open(fullURL); // Open Url
            });     
      });
  </script>
  <body>
  <a href="https://ssd.jpl.nasa.gov/horizons.cgi">Source</a>:<br>
    <textarea id="commands" name="commands" rows = "30" cols = "50"></textarea><br>
    <br>
    Resulting URL:<br>
    <textarea id="URL" name="URL" rows = "30" cols = "50"></textarea><br>
    <button id="btnGo" name="btnGo">Go</button>
    </body>
</html>
agregó la fuente de Javascript (también preguntó "Quiero crear una consulta de URL y recibir un json de texto con vectores de estado a cambio"). Desafortunadamente, no puedo ver ninguna opción de salida JSON en Horizons.
oh tienes razón, lo hice! Eso fue hace 2,5 años, cerca de cuando empecé. Tengo esta alergia a las llaves, así que solo puedo usar Python. Creo que su respuesta es útil y he votado, pero ahora hay varios paquetes de Python que hacen esto. Sin embargo, ya no usaría un JSON. ¡Gracias de nuevo!