SPICE package

ephemeris_tools.spice

SPICE kernel loading and geometry (cspyce wrappers and RSPK port).

ephemeris_tools.spice.common

Shared state for SPICE layer (replaces FORTRAN RSPK_COMMON common block).

class SpiceState(planet_num: int = 0, planet_id: int = 0, pool_loaded: bool = False, obs_id: int = 0, obs_is_set: bool = False, obs_lat: float = 0.0, obs_lon: float = 0.0, obs_alt: float = 0.0, nshifts: int = 0, shift_id: list[int] = <factory>, shift_dt: list[float] = <factory>)[source]

Bases: object

Shared state for SPICE/RSPK layer (replaces FORTRAN RSPK_COMMON).

Holds current planet, observer (ID or geodetic), and time-shift list for moon orbits. Modified by load_spice_files, set_observer_*, set_shift.

nshifts: int = 0
obs_alt: float = 0.0
obs_id: int = 0
obs_is_set: bool = False
obs_lat: float = 0.0
obs_lon: float = 0.0
planet_id: int = 0
planet_num: int = 0
pool_loaded: bool = False
reset_shifts() None[source]

Clear all time shifts (no Fortran equivalent; utility).

shift_dt: list[float]
shift_id: list[int]
get_state() SpiceState[source]

Return the global SpiceState instance (replaces RSPK_COMMON access).

ephemeris_tools.spice.load

SPICE kernel loading (ported from rspk_loadfiles.f and rspk_loadsc.f).

load_spacecraft(sc_id: str, planet: int, version: int = 0, set_obs: bool = True) bool[source]

Load SPICE kernels for a spacecraft at a planet (port of RSPK_LoadSC).

Loads kernels needed for geometry with that spacecraft. Optionally sets the observer to the spacecraft. Call after load_spice_files or in place of it for the same planet.

Parameters:
  • sc_id – Spacecraft identifier (e.g. ‘CAS’, ‘VG1’, ‘NH’, ‘GLL’).

  • planet – Planet index: 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune.

  • version – Ephemeris version, or 0 for latest.

  • set_obs – If True, set observer to this spacecraft.

Returns:

True if kernels were loaded, False otherwise.

load_spice_files(planet: int, version: int = 0, *, force: bool = False) tuple[bool, str | None][source]

Load SPICE kernels for the given planet (port of RSPK_LoadFiles).

Initializes the library for geometry calculations. Must be called before other SPICE/RSPK calls (except set_observer_*). Subsequent calls for the same planet do nothing. Observer is reset to Earth center.

Parameters:
  • planet – Planet index: 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune, 9=Pluto.

  • version – Ephemeris version number, or 0 for latest.

  • force – If True, clear kernel pool and internal state and reload (for tests that need a specific planet after another was loaded).

Returns:

(True, None) if loaded successfully; (False, error_message) on failure.

ephemeris_tools.spice.observer

Observer setup and state (ported from rspk_setobs.f).

observer_state(et: float) ndarray[source]

Return observer state (position and velocity) in J2000 at ephemeris time.

Port of RSPK_ObsLoc. Uses coordinates from set_observer_location or set_observer_id. Position is in km; velocity in km/s.

Parameters:

et – Ephemeris time (e.g. from cspyce.utc2et).

Returns:

position (3) and velocity (3) in km and km/s.

Return type:

Length-6 array

set_observer_id(body_id: int) None[source]

Set the observation point to a SPICE body (e.g. spacecraft).

Port of RSPK_SetObsId. Subsequent geometry calls use this observer. Use 0 to reset to Earth’s center.

Parameters:

body_id – SPICE body ID of the observer, or 0 for Earth center.

set_observer_location(lat_deg: float, lon_deg: float, alt_m: float) None[source]

Set observer to a geodetic location on Earth.

Port of RSPK_SetObs. Subsequent geometry calls are corrected for the observatory’s offset from Earth’s center. If latitude is outside [-90, 90], the observatory offset is disabled (Earth’s center used).

Parameters:
  • lat_deg – Geodetic latitude in degrees. Outside [-90, 90] disables observatory offset.

  • lon_deg – East longitude in degrees.

  • alt_m – Altitude in meters (relative to GRS 80 reference spheroid).

ephemeris_tools.spice.bodmat

Enhanced BODMAT with time-shift and tidally-locked moon fallback (rspk_bodmat.f).

bodmat(body_id: int, et: float) ndarray[source]

Return rotation matrix from J2000 to body-fixed frame (port of RSPK_BODMAT).

Replaces SPICE BODMAT with support for time offsets via set_shift. For moons without PCK data, falls back to orbit-derived orientation (tidally locked).

Parameters:
  • body_id – SPICE body ID.

  • et – Ephemeris time (e.g. from cspyce.utc2et).

Returns:

3x3 rotation matrix (J2000 to body-fixed). Identity on failure for moons.

bodmat_from_orbit(body_id: int, et: float) ndarray[source]

Rotation matrix for tidally-locked moon from orbit (port of RSPK_BODMAT_from_orbit).

X-axis toward planet, Z-axis is orbit pole (X cross V). Uranus pole direction is reversed to match convention.

Parameters:
  • body_id – SPICE body ID of the moon.

  • et – Ephemeris time.

Returns:

3x3 rotation matrix (J2000 to body-fixed).

ephemeris_tools.spice.geometry

Body geometry: RA/Dec, phase, ranges, lat/lon (ported from rspk_* body routines).

anti_sun(et: float, body_id: int) tuple[float, float][source]

Return anti-Sun right ascension and declination (radians).

Port of RSPK_AntiSun. Returns the direction away from the Sun as seen from the body’s frame, in J2000 RA/Dec.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Tuple of (ra, dec) in radians.

body_latlon(et: float, body_id: int) tuple[float, float, float, float][source]

Return sub-observer and sub-solar latitude and longitude (radians).

Port of RSPK_BodyLatLon. Longitudes are from the body’s prime meridian; the longitude beneath a fixed observer increases with time.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Tuple of (subobs_lat, subsol_lat, subobs_long, subsol_long) in radians.

Raises:

ValueError – If observer or Sun direction in body frame has zero length.

body_lonlat(et: float, body_id: int) tuple[float, float, float, float][source]

Return sub-observer and sub-solar longitude and latitude (radians).

Port of RSPK_BodyLonLat. Same as body_latlon but returns (lon, lat) order. Longitude increases with time (east for Uranus, west for others).

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Tuple of (subobs_lon, subobs_lat, subsol_lon, subsol_lat) in radians.

body_phase(et: float, body_id: int) float[source]

Return solar phase angle of a body as seen from the observer (radians).

Port of RSPK_BodyPhase. Uses standard SPKAPP with ‘LT’ (no time shift).

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Phase angle in radians.

body_radec(et: float, body_id: int) tuple[float, float][source]

Return observed J2000 right ascension and declination of a body at a time.

Port of RSPK_BodyRaDec. Returns values for Earth center or an observatory depending on set_observer_location/set_observer_id. Coordinates are in the barycenter frame and are not corrected for stellar aberration (correct relative to cataloged star positions).

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Tuple of (ra, dec) in radians.

body_ranges(et: float, body_id: int) tuple[float, float][source]

Return Sun-body and observer-body distances (km).

Port of RSPK_BodyRanges.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body_id – SPICE body ID.

Returns:

Tuple of (sundist, observer_dist) in km.

conjunction_angle(et: float, body1_id: int, body2_id: int) float[source]

Return angular distance between two bodies as seen from the observer (radians).

Port of RSPK_Conjunc.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • body1_id – SPICE body ID of first body.

  • body2_id – SPICE body ID of second body.

Returns:

Angular separation in radians.

limb_radius(et: float) tuple[float, float][source]

Return planet radius (km) and projected angular radius (radians).

Port of RSPK_LimbRad.

Parameters:

et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

Returns:

Tuple of (rkm, rradians).

moon_tracker_offsets(et: float, moon_ids: list[int]) tuple[list[float], float][source]

Return projected angular offsets of moons from planet axis (radians).

Port of RSPK_MoonDist. Positive offsets are on the morning ansa (higher RA); negative on the evening ansa. Values apply to Earth center or observatory depending on observer setup.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • moon_ids – List of SPICE body IDs for the moons.

Returns:

Tuple of (list of offset angles in radians per moon, limb radius in radians).

planet_phase(et: float) float[source]

Return solar phase angle of the planet as seen from the observer (radians).

Port of RSPK_Phase. Works for arbitrary observers (Earth or spacecraft).

Parameters:

et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

Returns:

Phase angle in radians.

planet_ranges(et: float, *, planet_id: int | None = None) tuple[float, float][source]

Return Sun-planet and observer-planet distances (km).

Port of RSPK_Ranges.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • planet_id – Optional SPICE body ID for the planet. When omitted, uses get_state().planet_id so existing callers are unchanged.

Returns:

Tuple of (sundist, observer_dist) in km.

ephemeris_tools.spice.orbits

Moon orbit geometry: orbit opening, moon angular offsets.

Ported from rspk_orbitopen, rspk_moondist.

moon_distances(et: float, moon_ids: list[int]) tuple[ndarray, float][source]

Return projected angular offsets of moons from planet axis (port of RSPK_MoonDist).

Positive offsets are on the morning ansa (higher RA); negative on the evening ansa. Values apply to Earth center or observatory per observer setup.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • moon_ids – List of SPICE body IDs for the moons.

Returns:

Tuple of (offsets array in radians, limb radius in radians).

orbit_opening(et: float, moon_id: int) tuple[float, float][source]

Return observed opening angle of a moon’s orbital plane (port of RSPK_OrbitOpen).

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • moon_id – SPICE body ID of the moon.

Returns:

opening angle in radians and observer longitude relative to moon in radians.

Return type:

Tuple of (obs_b, obs_long)

ephemeris_tools.spice.rings

Ring geometry: opening angles, RA/Dec of ring points.

Ported from rspk_ringopen, ringradec, ansaradec.

class RingGeometry(obs_b: float, sun_b: float, sun_db: float, is_dark: bool, obs_long: float, sun_long: float)[source]

Bases: object

Ring opening and lighting geometry (output of ring_opening, port of RSPK_RingOpen).

is_dark: bool
obs_b: float
obs_long: float
sun_b: float
sun_db: float
sun_long: float
ansa_radec(et: float, radius_km: float, is_right: bool) tuple[float, float][source]

Return observed J2000 RA and Dec of a ring ansa (port of RSPK_AnsaRaDec).

Right ansa is near 90 deg longitude; left ansa near 270 deg. Coordinates apply to Earth center or observatory; not corrected for stellar aberration.

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • radius_km – Ring radius in km.

  • is_right – True for right ansa, False for left ansa.

Returns:

Tuple (ra_offset, dec_offset) in radians. When the computed ratio is outside [-1.0, 1.0] (invalid ansa geometry), ansa_radec returns the sentinel (0.0, 0.0); callers should check for this instead of expecting an exception.

Raises:
  • ValueError – If geometry is edge-on (denom ~ 0). No exception is raised

  • for the out-of-range ratio case; callers must detect the (0.0, 0.0)

  • sentinel.

Notes

The (0.0, 0.0) sentinel for out-of-range geometry mirrors FORTRAN behavior for observer-too-close or extreme opening geometries; tests may assert ansa_radec returns (0.0, 0.0) for such cases.

ring_opening(et: float) RingGeometry[source]

Return observed ring opening and lighting geometry (port of RSPK_RingOpen).

Returns opening angle, sub-observer/sub-solar longitudes, and whether the visible ring side is lit. Longitudes are from the equatorial plane J2000 ascending node. Both sides are treated as lit while Sun crosses ring plane.

Parameters:

et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

Returns:

RingGeometry with obs_b, sun_b, sun_db, is_dark, obs_long, sun_long.

ring_radec(et: float, radius_km: float, lon_rad: float) tuple[float, float][source]

Return observed J2000 RA and Dec of a point on the ring (port of RSPK_RingRaDec).

Applies to Earth center or observatory per set_observer_*. Coordinates are not corrected for stellar aberration (correct relative to star catalogs).

Parameters:
  • et – Ephemeris time of the observation (e.g. from cspyce.utc2et).

  • radius_km – Ring radius in km.

  • lon_rad – Longitude on ring in radians; positive = ring rotation direction.

Returns:

Tuple of (ra, dec) in radians.

ephemeris_tools.spice.shifts

Time shift support for moon orbits (ported from rspk_setshift.f and rspk_spkapp.f).

set_shift(body_id: int, dt: float) None[source]

Apply a fixed time shift to a moon’s orbit (port of RSPK_SetShift).

Positive dt means the moon leads its ephemeris; negative means it lags. Time shift is stored and used by spkapp_shifted.

Parameters:
  • body_id – SPICE body ID of the moon.

  • dt – Time shift in seconds.

Raises:

RuntimeError – If the limit on number of time-shifted bodies is reached.

spkapp_shifted(body_id: int, et: float, ref: str, obs_pv: ndarray | list[float], aberr: str) tuple[ndarray, float][source]

Return apparent state of body; supports time offsets for moon orbits.

Port of RSPK_SPKAPP. Same interface as cspyce.spkapp; if set_shift was called for this body, the moon’s position is adjusted by the time shift.

Parameters:
  • body_id – SPICE body ID.

  • et – Ephemeris time.

  • ref – Reference frame (e.g. ‘J2000’).

  • obs_pv – Observer state (6) in km, km/s.

  • aberr – Aberration correction (e.g. ‘LT’, ‘LT+S’).

Returns:

Tuple of (body state 6-vector, light-time in seconds).