Skyfield: HomeTable of ContentsAPI Reference

Planets, and Choosing an Ephemeris

If you are interested in observing the planets, the Jet Propulsion Laboratory (JPL) has prepared long tables that predict the positions of the planets both in the the distant past and out into the future. A table of positions is called an ephemeris and those supplied by the JPL are of very high accuracy.

You can ask Skyfield to download an ephemeris from the JPL by giving load() a filename. Or you can load an ephemeris that you’ve already saved to disk with load_file().

A popular choice of ephemeris is DE421. It is recent, has good precision, was designed for general-purpose use, and is only 17 MB in size:

from skyfield.api import load
planets = load('de421.bsp')

Once an ephemeris file has been downloaded to your current directory, re-running your program will simply reuse the copy on disk instead of downloading it all over again.

After you have loaded an ephemeris and have used a statement like:

mars = planets['Mars']

— to retrieve a planet, consult the chapter Positions and Coordinates to learn about all the positions that you can use it to generate.

Making an excerpt of an ephemeris

Several of the ephemeris files listed below are very large. While most programmers will follow the example above and use DE421, if you wish to go beyond its 150-year period you will need a larger ephemeris. And programmers interested in the moons of Jupiter will need JUP310, which weighs in at nearly a gigabyte.

What if you need data from a very large ephemeris, but don’t require its entire time span?

When you installed Skyfield another library named jplephem will have been installed. When invoked from the command line, it can build an excerpt of a larger ephemeris without needing to download the entire file, thanks to the fact that HTTP supports a Range: header that asks for only specific bytes of a file. For example, let’s pull two weeks of data for Jupiter’s moons (using a shell variable $u for the URL only to make the command less wide here on the screen and easier to read):

$ u=https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/satellites/jup310.bsp
$ python -m jplephem excerpt 2018/1/1 2018/1/15 $u jup_excerpt.bsp

The resulting file jup_excerpt.bsp weighs in at only 0.2 MB instead of 932 MB but supports all of the same objects as the original JUP310 over the given two-week period:

$ python -m jplephem spk jup_excerpt.bsp
File type DAF/SPK and format LTL-IEEE with 13 segments:
2458119.75..2458210.50  Jupiter Barycenter (5) -> Io (501)
2458119.50..2458210.50  Jupiter Barycenter (5) -> Europa (502)
2458119.00..2458210.50  Jupiter Barycenter (5) -> Ganymede (503)
2458119.00..2458210.50  Jupiter Barycenter (5) -> Callisto (504)
...

You can load and use it directly off of disk with load_file().

How segments are linked to predict positions

You can print() an ephemeris to learn which objects it supports.

print(planets)
SPICE kernel file 'de421.bsp' has 15 segments
  JD 2414864.50 - JD 2471184.50  (1899-07-28 through 2053-10-08)
      0 -> 1    SOLAR SYSTEM BARYCENTER -> MERCURY BARYCENTER
      0 -> 2    SOLAR SYSTEM BARYCENTER -> VENUS BARYCENTER
      0 -> 3    SOLAR SYSTEM BARYCENTER -> EARTH BARYCENTER
      0 -> 4    SOLAR SYSTEM BARYCENTER -> MARS BARYCENTER
      0 -> 5    SOLAR SYSTEM BARYCENTER -> JUPITER BARYCENTER
      0 -> 6    SOLAR SYSTEM BARYCENTER -> SATURN BARYCENTER
      0 -> 7    SOLAR SYSTEM BARYCENTER -> URANUS BARYCENTER
      0 -> 8    SOLAR SYSTEM BARYCENTER -> NEPTUNE BARYCENTER
      0 -> 9    SOLAR SYSTEM BARYCENTER -> PLUTO BARYCENTER
      0 -> 10   SOLAR SYSTEM BARYCENTER -> SUN
      3 -> 301  EARTH BARYCENTER -> MOON
      3 -> 399  EARTH BARYCENTER -> EARTH
      1 -> 199  MERCURY BARYCENTER -> MERCURY
      2 -> 299  VENUS BARYCENTER -> VENUS
      4 -> 499  MARS BARYCENTER -> MARS

Bodies in JPL ephemeris files are each identified by an integer, but Skyfield translates them so that you do not have to remember that a code like 399 stands for the Earth and 499 for Mars.

Each ephemeris segment predicts the position of one body with respect to another. Sometimes several segments sometimes have to be combined to generate a complete position. The DE421 ephemeris shown above, for example, can produce the position of the Sun directly. But if you ask it for the position of Earth then it will have to add together two distances:

This happens automatically behind the scenes. All you have to say is planets[399] or planets['Earth'] and Skyfield will put together a solution using the segments provided.

earth = planets['earth']
print(earth)
Sum of 2 vectors:
 + Segment 'de421.bsp' 0 SOLAR SYSTEM BARYCENTER -> 3 EARTH BARYCENTER
 + Segment 'de421.bsp' 3 EARTH BARYCENTER -> 399 EARTH

Each time you ask this earth object for its position at a given time, Skyfield will compute both of these underlying vectors and add them together to generate the position.