Source code for ephemeris_tools.spice.shifts

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

from __future__ import annotations

import cspyce
import numpy as np

from ephemeris_tools.spice.common import MAXSHIFTS, get_state


[docs] def set_shift(body_id: int, dt: float) -> None: """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. """ state = get_state() for i in range(state.nshifts): if state.shift_id[i] == body_id: state.shift_dt[i] = dt return if state.nshifts >= MAXSHIFTS: raise RuntimeError('Number of moon orbit time shifts exceeded in set_shift()') state.shift_id[state.nshifts] = body_id state.shift_dt[state.nshifts] = dt state.nshifts += 1
[docs] def spkapp_shifted( body_id: int, et: float, ref: str, obs_pv: np.ndarray | list[float], aberr: str, ) -> tuple[np.ndarray, float]: """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). """ state = get_state() obs = obs_pv if hasattr(obs_pv, '__len__') else np.array(obs_pv) for i in range(state.nshifts): if state.shift_id[i] != body_id: continue dt_shift = state.shift_dt[i] if dt_shift == 0.0: break planet_dpv, planet_lt = cspyce.spkapp(state.planet_id, et + dt_shift, ref, obs, aberr) body_dpv, body_lt = cspyce.spkapp(body_id, et + dt_shift, ref, obs, aberr) temp_pos = [ body_dpv[0] - planet_dpv[0], body_dpv[1] - planet_dpv[1], body_dpv[2] - planet_dpv[2], ] temp_vel = [ body_dpv[3] - planet_dpv[3], body_dpv[4] - planet_dpv[4], body_dpv[5] - planet_dpv[5], ] planet_dpv_at_et, planet_lt_at_et = cspyce.spkapp(state.planet_id, et, ref, obs, aberr) out_pos = [ temp_pos[0] + planet_dpv_at_et[0], temp_pos[1] + planet_dpv_at_et[1], temp_pos[2] + planet_dpv_at_et[2], ] out_vel = [ temp_vel[0] + planet_dpv_at_et[3], temp_vel[1] + planet_dpv_at_et[4], temp_vel[2] + planet_dpv_at_et[5], ] return ( np.array(out_pos + out_vel, dtype=np.float64), body_lt - planet_lt + planet_lt_at_et, ) body_dpv, lt = cspyce.spkapp(body_id, et, ref, obs, aberr) return (np.array(body_dpv, dtype=np.float64), lt)