libera_utils.libera_spice.kernel_manager#

SPICE Kernel Manager

This module provides a clean interface for managing SPICE kernels for the Libera instrument. It separates kernel lifecycle management from computation logic to improve maintainability and performance.

Classes

KernelManager([temp_dir_base, ...])

Manages SPICE kernel loading and lifecycle for Libera geolocation calculations.

class libera_utils.libera_spice.kernel_manager.KernelManager(temp_dir_base: str | Path | None = None, download_naif_url: str = 'https://naif.jpl.nasa.gov/pub/naif/generic_kernels/', use_test_naif_url: bool = False, use_high_precision_earth: bool = True, cache_timeout_days: int = 7)#

Manages SPICE kernel loading and lifecycle for Libera geolocation calculations.

Kernel paths are validated against the SPICE 80-character limit (see Notes). Short temporary workspaces (temp_dir_base) help generated kernels stay within that limit.

Parameters:
  • temp_dir_base (str | Path | None) – Base directory for temporary kernel files. If None, uses platform default. Can also be controlled via LIBERA_TEMP_DIR environment variable.

  • download_naif_url (str) – Base URL for NAIF generic kernel downloads.

  • use_test_naif_url (bool) – When True, use a flat test index layout instead of NAIF subdirectory structure.

  • use_high_precision_earth (bool) – When True (default), load the NAIF ITRF93 Earth-orientation bundle: association FK, extended predict binary PCK (earth_*_predict.bpc), and ops high-precision binary PCK (earth_000101_*.bpc). Files are discovered in GENERIC_KERNEL_DIR or downloaded from NAIF. When False, only base kernels (leap seconds, DE, text PCK) are loaded; use only when ITRF93 / Libera+JPSS geolocation is not required. The name is historical; this flag gates the full ITRF93 stack, not a precision-only toggle.

  • cache_timeout_days (int) – Maximum age in days before cached NAIF kernels are refreshed.

Notes

The path length limit is fixed by the class attribute _max_path_length (80) and is not a constructor argument. load_static_kernels validates paths before furnishing kernels.

Methods

ensure_kernel_coverage(targets, start_ugps, ...)

Verify the furnished kernels cover every target across a time window.

ensure_known_kernels_are_furnished()

Method to verify all known kernels are furnished by SPICE.

load_libera_dynamic_kernels(...[, ...])

Load dynamic kernels from an explicit sequence of sources (typically manifest order).

load_naif_kernels([cache_time_out])

Load NAIF generic kernels into SPICE.

load_static_kernels()

Load Libera static kernels into SPICE.

unload_all()

Unload all SPICE kernels and clean up resources.

_create_temporary_static_kernels() → Path#

Curryer uses json based kernel configuration files to generate SPICE kernels. These configuration files need to be processed into actual SPICE kernel files before they can be loaded. This method creates a temporary directory, copies the necessary configuration files, and generates the static kernels into that directory.

This method will start by furnishing the naif kernels to ensure the leap second kernel is available, as it is required for static kernel generation.

Returns:

Path to the created temporary directory containing static kernels.

Return type:

Path

Raises:

RuntimeError – If kernel creation fails or path exceeds length limit.

_delete_temporary_static_kernels() → None#

Delete the temporary static kernels directory.

Safely removes the directory and all contents. Logs warnings but doesn’t raise exceptions to allow cleanup to proceed.

static _output_basename_for_static_kernel_config(config_path: Path) → str#

Binary kernel filename produced by make_kernel for a static JSON config.

_prepare_static_kernel_workspace() → None#

Ensure user-cache copies of generated static kernels exist, building on cache miss.

static _static_generated_kernel_basenames() → list[str]#

Basenames of generated static binaries from LIBERA_KERNEL_STATIC_CONFIGS.

ensure_kernel_coverage(targets: Sequence[int | str], start_ugps: int, stop_ugps: int, error: bool = True) → None#

Verify the furnished kernels cover every target across a time window.

Wraps curryer.kernels.coverage.coverage_gaps(), scoped to the kernels this manager furnished. Raises rather than warns: an uncovered window otherwise surfaces as a SPICE failure deep inside a later computation, or as silently wrong numbers with no traceback at all.

Opt-in, and order matters: call it once after the kernels for a run are furnished and before the first computation that reads them. Nothing calls it automatically, because the manager cannot know which targets or which window a caller needs – those come from the algorithm (the instrument frame it points, the granule it processes), not from the kernel set. Checking every furnished object over its own coverage union would answer a different and much weaker question. Skipping the call changes no other behavior; what it costs is the early, named failure.

Parameters:
  • targets (sequence of int or str) – Objects that must be covered across the whole window: body IDs or names for SPK coverage, frame IDs or names for CK. Binary PCKs are also in scope, and their coverage is keyed on the frame class ID rather than the body or frame ID – pass the frame name and curryer resolves it. Names require the kernels that define them to be furnished.

  • start_ugps (int) – Window start, in microseconds since the GPS epoch.

  • stop_ugps (int) – Window stop, in microseconds since the GPS epoch.

  • error (bool) – Raise on a coverage gap (default). Set False to warn instead, for callers that already degrade gracefully per sample and want the gap surfaced rather than fatal.

Raises:
  • RuntimeError – If this manager has furnished no kernels.

  • ValueError – If error is True and a target has no coverage in any furnished kernel, or the requested window is not fully covered for every target.

ensure_known_kernels_are_furnished() → None#

Method to verify all known kernels are furnished by SPICE.

Raises:

RuntimeError – If kernels are not properly loaded.

load_libera_dynamic_kernels(dynamic_kernel_sources: Sequence[str | Path | S3Path], *, needs_static_kernels: bool = True, needs_naif_kernels: bool = True) → None#

Load dynamic kernels from an explicit sequence of sources (typically manifest order).

This will load static and NAIF kernels first when requested and they are not already loaded.

Every source is materialized through KernelFileCache with max_cache_age equal to cache_timeout_days from construction.

Parameters:
  • dynamic_kernel_sources (sequence of str, pathlib.Path, or cloudpathlib.S3Path) – One cache entry per element; see KernelFileCache for local paths vs remote URLs. Use [single_path] or ["https://..."] — bare Path / str / bytes arguments are rejected because str is a Python Sequence.

  • needs_static_kernels (bool) – Whether to ensure static kernels are loaded before loading dynamic kernels (default: True).

  • needs_naif_kernels (bool) – Whether to ensure NAIF kernels are loaded before loading dynamic kernels (default: True).

Raises:
  • FileNotFoundError – If paths do not exist, or the sequence is empty.

  • ValueError – If an entry resolves to a directory instead of a kernel file.

  • TypeError – If dynamic_kernel_sources is not a non-string sequence (pass Path objects inside a tuple/list).

load_naif_kernels(cache_time_out: int | None = None) → None#

Load NAIF generic kernels into SPICE. This method will first look in the generic kernel directory, and if no local versions of the needed kernels are found, it will download them from the NAIF server and cache them locally.

These include leap seconds, planetary ephemeris, and Earth orientation data. When use_high_precision_earth is True, ITRF93 kernels (association FK, predict and ops binary PCK) are included; see KernelManager parameter documentation.

Raises:
  • FileNotFoundError – If kernel files cannot be found at expected paths.

  • RuntimeError – If kernel loading fails, or if no leapsecond kernel is among the NAIF kernels.

Notes

The leapsecond kernel is the one file two libraries have to agree on. This method furnishes it into the pool and then points LEAPSECOND_FILE_ENV at its directory. Curryer resolves an LSK for every kernel-making call through spicetime.leapsecond.find_default_file, whose precedence is LEAPSECOND_USER_FILE_PATH, then LEAPSECOND_FILE_ENV, then the kernel packaged with curryer plus any newer one in curryer’s own cache.

Since curryer 0.5.2 that packaged kernel resolves on its own, so the override is not what makes kernel creation work. It is set so curryer builds against the same LSK that is in the pool: Libera kernel configs name no leapsecond_kernel, so without it curryer could pick a different one and a run would carry two leapsecond definitions.

load_static_kernels() → None#

Load Libera static kernels into SPICE.

Static kernels include instrument orientation and configuration data that doesn’t change with time. This only needs to be called once. This method also guarantees NAIF kernels are loaded (including leap-second setup) so callers can rely on a consistent initialization contract for both static cache-hit and static rebuild paths.

Raises:
  • FileNotFoundError – If kernel files cannot be found at expected paths.

  • RuntimeError – If kernel loading fails or paths exceed length limits.

unload_all() → None#

Unload all SPICE kernels and clean up resources.

This should be called when done with calculations to free memory and ensure clean state for subsequent operations.