[AstroPy] consistency of reference frames between SkyCoord and JPL Horizons

Paolo Tanga Paolo.Tanga at oca.eu
Fri Apr 24 09:00:22 EDT 2020


Hi all

I am trying to plug the results by JPL Horizons into the appropriate 
reference system of a SkyCoord object, but it looks very trick. (bewore 
long message, I hope the explanation is clear for the specialists of 
reference systems)

The Horizons server returns two types of equatorial coordinates: 
"astrometric" (1) and (2) "apparent".

Their description is the following:

- (1): astrometric RA and Dec with respect to the observing site 
(coordinate origin) in the reference frame of
the planetary ephemeris (ICRF). Compensated for down-leg light-time 
delay aberration.

- (2): Airless apparent RA and Dec of the target with respect to an 
instantaneous reference frame defined by the Earth equator of-date 
(z-axis) and meridian containing the Earth equinox of-date (x-axis, 
IAU76/80). Compensated for down-leg light-time delay, gravitational 
deflection of light, stellar aberration, precession & nutation. Note: 
equinox (RA origin) is offset -53 mas from the of-date frame defined by 
the IAU06/00a P & N system.

My guess is none of these two systems correspond to either ICRS or GCRS 
as defined in astropy. The simplest possibility for me, would have been 
to assimilate (1), computed for the Solar System barycenter, to ICRS. 
But definitely (2) is not GCRS and the test below easily proves that.

Verification (see the attached notebook if you want to play with) :

- I queried for Solar System barycentric coordinates (1) of an asteroid 
at one epoch. I inserted them in a SkyCoord object as ICRS and use the 
transform_to(GCRS) towards geocentric, at the given epoch.

- I queried again JPL Horizons for the apparent coordinates (2) from the 
geocenter, directly.

As expected, by comparing the results I get the patent confirmation that 
GCRS is not the frame of (2), with a discrepancy of 16 arcmin in my 
case. SO, IT DOES NOT WORK, AS EXPECTED. Let's put apparent coordinates 
(2) aside for the moment.

Second possibility (see notebook again).

I take coordinates (1), for the geocentric observer. I insert them as 
GCRS in a SkyCoord object. I trasform_to(ICRS) (barycentric observer) 
and compare the result to a query of (1) directly for the barycentric 
observer.

Again this SHOULD NOT WORK accurately. In fact the definition of (1) 
does not contain annual aberration and light deflection that are part of 
GCRS. A difference of several arcsec (mostly due to annual aberration) 
SHOULD show up. And in fact IT DOES, ~8 arcsec of difference.

The conclusions if that using SkyCoord with the output of JPL Horizons 
is far from obvious to the end user...

----

So, my final questions/remarks are:

- How to get a fully accurate consistency between a SkyCoord frame and 
JPL Horizons output, in the case of a barycentric, geocentric or 
topocentric observer, for both "astrometric" and "apparent" coordinates 
as provided by JPL? Which reference SkyCoord should use and how?

- Does astropy implement GCRS correctly in the case of Solar System 
objects, by taking into account aberration and light deflection in the 
relativistic form, for an object at finite distance (different than for 
the stars!) ?

- ...or... Am I missing something fundamental in my interpretation?

- Eventually, this query to Horizons turns our to be tricky to manage as 
SkyCoord for the final user. I think it would be useful to provide the 
correct recipe and/or directly a SkyCoord as output of the query...

Best regards

Paolo


-- 
---------------------------------------------------------------------
Paolo Tanga                              Astronomer
Deputy director of Laboratoire Langrange / UMR 7293
Observatoire de la Côte d'Azur           Tel  +33(0)492003042
Bv de l'Observatoire - CS 34229          Fax  +33(0)492003121
06304 Nice Cedex 4 - France              http://www.oca.eu/tanga
                                          https://twitter.com/ziggypao

-------------- next part --------------
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from astropy.table import Table\n",
    "import numpy as np\n",
    "from astroquery.jplhorizons import Horizons\n",
    "from astropy import coordinates as coord\n",
    "from astropy.coordinates import GCRS, ICRS, Distance, solar_system_ephemeris\n",
    "from astropy.time import Time\n",
    "import astropy.units as u"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ScienceState solar_system_ephemeris: 'de432s'>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "solar_system_ephemeris.set('de432s') "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Test on (358) Apollonia, April 9, 2020, 07h16m UT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "time = Time('2020-04-09T07:16:00', scale='utc')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### First test - apparent vs astrometric"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Query JPL Horizons for barycentric and transform to GCRS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "asteroid = Horizons(id='Apollonia', location='@0', epochs=time.jd)  # '@0' defines the Solar Sytem barycenter\n",
    "ast_eph_baryc = asteroid.ephemerides(quantities='1,19,20,21',extra_precision=True)\n",
    "\n",
    "# Build SkyCoord object in ICRS\n",
    "ast_coord_ICRS = coord.SkyCoord(ra=ast_eph_baryc['RA'],dec=ast_eph_baryc['DEC'],distance=ast_eph_baryc['delta'],frame='icrs')\n",
    "# Transform it to GCRS at the epoch above\n",
    "ast_coord_GCRS= ast_coord_ICRS.transform_to(GCRS(obstime=time))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Query JPL Horizons for apparent coordinates, referred to the geocenter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "asteroid = Horizons(id='Apollonia', location='500', epochs=time.jd)  # '@0' defines the Solar Sytem barycenter\n",
    "ast_eph_app = asteroid.ephemerides(quantities='2,19,20,21',extra_precision=True)\n",
    "\n",
    "# Build SkyCoord from apparent coordinates assuming that it is GCRS \n",
    "ast_coord_app=coord.SkyCoord(ra=ast_eph_app['RA_app'],dec=ast_eph_app['DEC_app'],distance=ast_eph_app['delta'],frame='gcrs',obstime=time)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Separation between the two positions (barycentric transformed to GCRS, and apparent intrpreted as GCRS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Separation  0d16m46.1082s\n",
      "Separation RA  0d15m36.2532s\n"
     ]
    }
   ],
   "source": [
    "print('Separation ',ast_coord_app.separation(ast_coord_GCRS)[0])\n",
    "print('Separation RA ',(ast_coord_app.ra-ast_coord_GCRS.ra)[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is clearly VERY large. Implying there is a clear difference in the reference frame (especially in RA), not only in \"small\" corrections.\n",
    "Our assumption (apparent coordinates are GCRS) is wrong."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Second test - astrometric geocentric interpreted as GCRS"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Query JPL Horizons for ITRF geocentric and consider these are GCRS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "asteroid = Horizons(id='Apollonia', location='500', epochs=time.jd)  # '@0' defines the Solar Sytem barycenter\n",
    "ast_eph_geoc = asteroid.ephemerides(quantities='1,19,20,21',extra_precision=True)\n",
    "\n",
    "# Build SkyCoord object in GCRS\n",
    "ast_coord_GCRS_2 = coord.SkyCoord(ra=ast_eph_geoc['RA'],dec=ast_eph_geoc['DEC'],distance=ast_eph_geoc['delta'],frame='gcrs',obstime=time)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Transform it to ICRS barycentric at the epoch above\n",
    "ast_coord_ICRS_2= ast_coord_GCRS_2.transform_to(ICRS)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Difference between the two barycentric positions "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Separation  0d00m08.0641s\n"
     ]
    }
   ],
   "source": [
    "print('Separation ',ast_coord_ICRS_2.separation(ast_coord_ICRS)[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Difference between geocentric ICRS queried from JPL, and GCRS obtained from barycentric transformation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Separation  0d00m11.6936s\n"
     ]
    }
   ],
   "source": [
    "print('Separation ',ast_coord_GCRS_2.separation(ast_coord_GCRS)[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}


More information about the AstroPy mailing list