Skip to content

NAIF Ephemeris Kernels

NAIF (Navigation and Ancillary Information Facility) is NASA JPL's archive for planetary ephemeris data. Brahe provides functions to download DE (Development Ephemeris), satellite ephemeris, and lunar-orientation kernels from the NAIF archive.

What are DE Kernels?

DE kernels are binary SPK (SPICE Kernel) files containing numerical integration results for planetary positions and velocities. Each version represents a different JPL Development Ephemeris model, with newer versions incorporating improved observations and models.

Supported Kernels

Brahe supports downloading the following kernel files, enumerated by SPICEKernel (Rust). The Python bh.datasets.naif.download_spice_kernel(name, ...) function and the Rust brahe::datasets::naif::download_spice_kernel(kernel, ...) function both accept any of these — by name (str) in Python, by SPICEKernel variant in Rust:

Kernel File Size Description
de430 ~120 MB Standard precision, extended time span
de432s ~11 MB Designed for New Horizons targeting Pluto
de435 ~120 MB Higher accuracy for inner planets
de438 ~120 MB Standard precision
de440 ~120 MB Latest standard precision (1550-2650)
de440s ~33 MB Small variant of DE440 (1849-2150)
de442 ~120 MB Intended for the MESSENGER mission to Mercury
de442s ~33 MB Small variant of DE442
mar099s ~68 MB Mars satellite ephemeris — Phobos, Deimos (1995-2050)
mar099 ~1.1 GB Mars satellite ephemeris, wider time span (1600-2600)
jup365 ~1.1 GB Jupiter satellite ephemeris — Io, Europa, Ganymede, Callisto (1600-2200)
sat441 ~662 MB Saturn satellite ephemeris — Titan and mid-size moons (1750-2250)
ura184 ~387 MB Uranus satellite ephemeris — Miranda, Ariel, Umbriel, Titania, Oberon (1600-2399)
nep097 ~105 MB Neptune satellite ephemeris — Triton (1600-2400)
plu060 ~135 MB Pluto-system ephemeris — Charon (1800-2200)
moon_pa_de440 ~13 MB Lunar principal-axis binary PCK (orientation, not SPK)

Choosing a Kernel

For most applications, de440s provides a good balance between file size and accuracy. The "s" (small) variants cover a shorter time span but are significantly smaller files. The satellite ephemeris kernels (mar099s, jup365, sat441, ura184, nep097) are downloaded automatically the first time a planet body-center *_spice function (e.g. mars_position_spice) is called — see Ephemerides.

Binary PCK Kernels

Brahe also downloads and caches the moon_pa_de440 binary PCK (lunar principal-axis orientation) the same way. Load it with bh.load_spice_kernel("moon_pa_de440"), or with bh.load_common_spice_kernels(), which loads de440s and moon_pa_de440 together — see SPICE Kernels for orientation queries against it.

Caching Behavior

DE kernels are large files that do not change over time. Brahe implements permanent caching:

  • Cache location: ~/.cache/brahe/naif/ (or $BRAHE_CACHE/naif/ if set)
  • Cache duration: Permanent (kernels are stable long-term products)
  • Cache check: Simple file existence check - no age validation

Once a kernel is downloaded, it remains cached indefinitely and subsequent calls return the cached file path without re-downloading.

Usage

Basic Download

Download a kernel and use the cached location:

import brahe as bh

# Initialize EOP data
bh.initialize_eop()

# Download de440s kernel (smaller variant, ~33MB)
# This will download once and cache for future use
kernel_path = bh.datasets.naif.download_spice_kernel("de440s")

print(f"Kernel cached at: {kernel_path}")

# Subsequent calls use the cached file - no re-download
kernel_path_again = bh.datasets.naif.download_spice_kernel("de440s")
print(f"Retrieved from cache: {kernel_path_again}")

# Optionally copy to a specific location
output_path = "/tmp/my_kernel.bsp"
copied_path = bh.datasets.naif.download_spice_kernel("de440s", output_path)
print(f"Copied to: {copied_path}")
use brahe as bh;

fn main() {
    bh::initialize_eop().unwrap();

    // Download de440s kernel (smaller variant, ~33MB)
    // This will download once and cache for future use
    let kernel_path =
        bh::datasets::naif::download_spice_kernel(bh::spice::SPICEKernel::DE440s, None).unwrap();

    println!("Kernel cached at: {}", kernel_path.display());

    // Subsequent calls use the cached file - no re-download
    let kernel_path_again =
        bh::datasets::naif::download_spice_kernel(bh::spice::SPICEKernel::DE440s, None).unwrap();
    println!("Retrieved from cache: {}", kernel_path_again.display());

    // Optionally copy to a specific location
    let output_path = std::path::PathBuf::from("/tmp/my_kernel.bsp");
    let copied_path = bh::datasets::naif::download_spice_kernel(
        bh::spice::SPICEKernel::DE440s,
        Some(output_path),
    )
    .unwrap();
    println!("Copied to: {}", copied_path.display());
}
Output


The first call downloads and caches the kernel. Subsequent calls immediately return the cached file path.

Error Handling

The Python binding takes a kernel name as a string and validates it before attempting a download; invalid names raise an error immediately:

1
2
3
4
5
try:
    bh.datasets.naif.download_spice_kernel("de999")
except RuntimeError as e:
    print(e)
    # "Unsupported kernel name 'de999'. Supported kernels: de430, de432s, ..."

In Rust, download_spice_kernel takes a SPICEKernel enum value directly rather than a string, so an unsupported kernel name cannot be passed at all — the enum only has the 16 valid variants. To validate a name obtained at runtime (e.g. from user input), resolve it through SPICEKernel::from_name first:

1
2
3
4
5
6
7
match bh::spice::SPICEKernel::from_name("de999") {
    Some(kernel) => {
        let path = bh::datasets::naif::download_spice_kernel(kernel, None).unwrap();
        println!("Downloaded to {}", path.display());
    }
    None => println!("Unsupported kernel name 'de999'"),
}

See Also