SpiceyPy
SpiceyPy is a Python wrapper for NASA's NAIF CSPICE Toolkit, providing tools for computing ephemeris, attitude, event finding, and geometry for spacecraft and celestial bodies. It enables Python users to leverage the powerful CSPICE library. The library is actively maintained with frequent releases, currently at version 8.1.0, and often includes performance enhancements and new features.
Common errors
-
SPICE(NOKERNELDATA): No kernel data available for object/frame 'EARTH' at time...
cause A required SPICE kernel (e.g., an SPK for ephemeris, or PCK for planetary constants) has not been loaded using `spice.furnsh()`.fixBefore calling SPICE functions, ensure all necessary kernels are loaded: `spice.furnsh('/path/to/my_kernel.bsp')`, `spice.furnsh('/path/to/my_lsk.tls')`, etc. Consult NAIF documentation to understand which kernels are needed for your specific calculation. -
FileNotFoundError: [Errno 2] No such file or directory: '/path/to/missing_kernel.bsp'
cause The file path provided to `spice.furnsh()` does not exist or is incorrect.fixVerify that the kernel file exists at the specified path and that the path is spelled correctly. Use absolute paths or ensure the file is in a location accessible by your script. -
TypeError: argument of type 'int' is not iterable
cause A SPICEyPy function expected an array-like input (e.g., a NumPy array or list of numbers) but received a scalar value.fixEnsure inputs match the expected type. For functions expecting an array, pass a `numpy.array([value])` even for single values. Consult the function's docstring for expected input types and shapes.
Warnings
- gotcha Failing to load necessary SPICE kernels (e.g., Leap Seconds, PCK, SPK) via `spice.furnsh()` is the most common pitfall. Many SPICE functions will fail with cryptic errors or return incorrect results without the required data loaded into the kernel pool.
- breaking The order of `NotFound` exception checks and error handling was swapped in v8.0.0. This change aims to prevent spurious `NotFound` exceptions but might subtly alter error propagation for code that previously relied on the exact timing or order of these checks.
- gotcha SpiceyPy v7.0.0 introduced `cyice`, a Cython-accelerated submodule for performance. While largely 'drop-in', functions called via `cyice.function_name` are C-extensions. Debugging or introspection might differ slightly from the `ctypes`-based `spiceypy` functions. Installation on unusual platforms or without appropriate build tools can also be more complex without pre-built wheels.
- gotcha SPICE functions typically operate using Ephemeris Time (ET), which is seconds past J2000 epoch. Direct use of Python's `datetime` objects or UTC strings often requires conversion via functions like `spice.str2et()` and `spice.et2utc()`. Incorrectly mixing time systems is a common source of errors.
Install
-
pip install spiceypy
Imports
- spiceypy
import spiceypy as spice
- Cyice
from spiceypy import cyice
Quickstart
import spiceypy as spice
import os
# A simple kernel file for demonstration
# In a real application, you would download these from NAIF
# For local testing, ensure naif0012.tls is in the script's directory
# or specify its full path.
kernel_path = os.path.join(os.path.dirname(__file__), 'naif0012.tls')
if not os.path.exists(kernel_path):
# This is a dummy for demonstration. You would fetch a real kernel.
print(f"Warning: '{kernel_path}' not found. Please download from NAIF if this isn't a test.")
# Example: You'd typically download like this (replace with actual URL and process)
# import urllib.request
# url = 'https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls'
# urllib.request.urlretrieve(url, kernel_path)
# Load a leap second kernel (LSK) to define Ephemeris Time (ET)
try:
spice.furnsh(kernel_path)
except spice.exceptions.SpiceyPyError as e:
print(f"Failed to load kernel: {e}. Skipping calculations.")
exit()
# Convert a UTC string to Ephemeris Time (ET)
utc_time = '2023-01-01 T00:00:00'
et = spice.str2et(utc_time)
print(f"UTC: {utc_time} -> ET: {et}")
# Get position of Earth relative to the Sun
# Observer: SUN, Target: EARTH, Reference Frame: J2000, Aberration Correction: NONE
pos, lt = spice.spkpos('EARTH', et, 'J2000', 'NONE', 'SUN')
print(f"Position of Earth relative to Sun (km): {pos}")
# Unload all kernels
spice.unload(kernel_path)
# Alternatively, spice.kclear() clears all loaded kernels