libera_utils.kernel_maker#

High-level kernel creation module for generating Libera’s dynamic SPICE kernels from telemetry data.

Dynamic kernels are time-varying kernels derived from telemetry (spacecraft ephemeris, attitude, Az/El mechanisms), as opposed to static kernels which are fixed-offset and manually updated. This module sits at the top of the libera_spice dependency hierarchy, importing both kernel_manager.py and spice_utils.py.

Functions

add_mechanism_ck_quaternions(df)

Add CK quaternion columns for whichever Az/El encoder column is present, in place.

apply_encoder_corrections(df)

Correct the Az/El encoder columns of a kernel-input DataFrame, in place.

azel_kernel_cli_handler(parsed_args)

Generate SPICE Az/El kernels from command line arguments.

azimuth_error(angle)

Azimuth encoder error at the telemetered angle(s).

correct_azimuth(angle)

Corrected azimuth from telemetered angle(s): corrected = telemetry - error.

correct_elevation(angle)

Corrected elevation from telemetered angle(s): corrected = telemetry - error.

create_jpss_kernel_dataframe_from_csv(csv_path)

Create a Curryer-compatible JPSS kernel DataFrame from a CSV ephemeris file.

create_kernel_dataframe_from_l1a(...)

Create a Curryer-compatible kernel DataFrame from an L1A Dataset.

create_kernel_dataframe_from_l1a_netcdf(...)

Create a Curryer-compatible kernel DataFrame from an L1A NetCDF file.

create_kernel_from_l1a(l1a_data, ...[, ...])

Create a SPICE kernel from a single L1A Dataset for a kernel data product type.

create_kernel_from_packets(input_data_files, ...)

Create a SPICE kernel from one or more input packet files and kernel data product type.

create_kernels_from_manifest(input_manifest, ...)

Generate SPICE kernels from a manifest file of L1A NetCDF products.

elevation_error(angle)

Elevation encoder error at the telemetered angle(s).

jpss_kernel_cli_handler(parsed_args)

Generate SPICE JPSS kernels from command line arguments.

mechanism_quaternions(angles, axis)

SPICE scalar-first quaternions for rotation by each angle about axis.

reverse_encoder_corrections(df)

Recover the raw telemetered Az/El encoder columns from corrected values, in place.

uncorrect_azimuth(corrected)

Recover telemetered azimuth angle(s) from corrected value(s).

uncorrect_elevation(corrected)

Recover telemetered elevation angle(s) from corrected value(s).

libera_utils.kernel_maker._read_alignment_axis(pool_var: str) ndarray#

Read a measured unit-vector axis from the Libera frame kernel pool.

Furnishes the frame kernel only if the keyword is not already in the pool (static kernels are normally furnished via KernelManager.load_static_kernels()), to avoid redundant loads.

libera_utils.kernel_maker.add_mechanism_ck_quaternions(df: DataFrame) DataFrame#

Add CK quaternion columns for whichever Az/El encoder column is present, in place.

Converts the (corrected) encoder angle into per-sample quaternions about the mechanism’s measured axis of rotation (read from the frame kernel), so the generated CK encodes rotation about the true axis rather than a nominal coordinate axis. A no-op when neither encoder column is present (e.g. spacecraft kernels). Returns the same DataFrame.

libera_utils.kernel_maker.apply_encoder_corrections(df: DataFrame) DataFrame#

Correct the Az/El encoder columns of a kernel-input DataFrame, in place.

Corrects whichever of ICIE__AXIS_AZ_FILT / ICIE__AXIS_EL_FILT (radians) are present and leaves other columns untouched, so it is a no-op for non-AXIS_SAMPLE kernel inputs (spacecraft ephemeris/attitude). Returns the same DataFrame instance for convenience.

libera_utils.kernel_maker.azel_kernel_cli_handler(parsed_args: Namespace)#

Generate SPICE Az/El kernels from command line arguments.

Parameters:

parsed_args (argparse.Namespace) – Namespace of parsed CLI arguments.

Returns:

Output manifest file containing one or more kernel files.

Return type:

libera_utils.io.manifest.Manifest

libera_utils.kernel_maker.azimuth_error(angle: float | floating | ndarray | Series) float | floating | ndarray | Series#

Azimuth encoder error at the telemetered angle(s).

Parameters:

angle (AngleLike) – Telemetered azimuth angle(s), in radians.

Returns:

Encoder error, in radians, to subtract from the telemetry.

Return type:

AngleLike

libera_utils.kernel_maker.correct_azimuth(angle: float | floating | ndarray | Series) float | floating | ndarray | Series#

Corrected azimuth from telemetered angle(s): corrected = telemetry - error.

Parameters:

angle (AngleLike) – Telemetered azimuth angle(s), in radians.

Returns:

Corrected azimuth angle(s), in radians.

Return type:

AngleLike

libera_utils.kernel_maker.correct_elevation(angle: float | floating | ndarray | Series) float | floating | ndarray | Series#

Corrected elevation from telemetered angle(s): corrected = telemetry - error.

Parameters:

angle (AngleLike) – Telemetered elevation angle(s), in radians.

Returns:

Corrected elevation angle(s), in radians.

Return type:

AngleLike

libera_utils.kernel_maker.create_jpss_kernel_dataframe_from_csv(csv_path: CloudPath | Path) tuple[DataFrame, tuple[datetime, datetime]]#

Create a Curryer-compatible JPSS kernel DataFrame from a CSV ephemeris file.

This function reads a CSV file containing simulated JPSS ephemeris data with GPS time, position, and velocity information. It converts the GPS time to UTC and then to SPICE Ephemeris Time (ET) for use in kernel generation.

Parameters:

csv_path (filenaming.PathType) – Path to the CSV ephemeris file (local or S3).

Returns:

A tuple containing: - DataFrame with ET time columns (ADGPS_JPSS_ET and ADCFA_JPSS_ET)

and position/velocity data fields

  • UTC time range tuple (start, end) for the data

Return type:

tuple[pd.DataFrame, tuple[datetime, datetime]]

Raises:
  • FileNotFoundError – If the CSV file does not exist at the specified path

  • ValueError – If required columns are missing from the CSV file

Notes

  • Requires SPICE leap second kernel (LSK) to be loaded for ET conversion

  • Creates both ADGPS_JPSS_ET and ADCFA_JPSS_ET columns with identical values

libera_utils.kernel_maker.create_kernel_dataframe_from_l1a(l1a_dataset: Dataset, apid: int, sample_group_name: str) tuple[DataFrame, tuple[datetime, datetime]]#

Create a Curryer-compatible kernel DataFrame from an L1A Dataset.

This function extracts sample group data from an L1A Dataset and converts it into a pandas DataFrame suitable for SPICE kernel generation with Curryer. The time coordinates are converted from datetime64 to SPICE Ephemeris Time (ET).

Parameters:
  • l1a_dataset (xr.Dataset) – L1A Dataset containing sample group data with time coordinates. Should be created by parse_packets_to_l1a_dataset() or read from an L1A NetCDF file.

  • apid (int) – The APID (Application Process Identifier) that identifies which packet configuration to use for extracting sample group metadata. Use LiberaApid enum values.

  • sample_group_name (str) – The name of the sample group to extract from the L1A dataset. This is used to infer the time dimension and data fields.

Returns:

A tuple containing: - DataFrame with ET time column and sample data fields - UTC time range tuple (start, end) for the data

Return type:

tuple[pd.DataFrame, tuple[datetime, datetime]]

Raises:
  • ValueError – If the APID has multiple sample groups and sample_group_name is not provided, or if the specified sample_group_name is not found in the packet configuration

  • KeyError – If required fields are missing from the L1A dataset

  • TypeError – If l1a_dataset is not an xarray.Dataset

libera_utils.kernel_maker.create_kernel_dataframe_from_l1a_netcdf(netcdf_path: CloudPath | Path, apid: int, sample_group_name: str) tuple[DataFrame, tuple[datetime, datetime]]#

Create a Curryer-compatible kernel DataFrame from an L1A NetCDF file.

This convenience function opens an L1A NetCDF file and extracts sample group data for SPICE kernel generation. It wraps create_kernel_dataframe_from_l1a() to provide a simpler interface when working with NetCDF files.

Parameters:
  • netcdf_path (filenaming.PathType) – Path to the L1A NetCDF file (local or S3). The file should be created by parse_packets_to_l1a_dataset() or equivalent processing.

  • apid (int) – The APID (Application Process Identifier) that identifies which packet configuration to use for extracting sample group metadata. Use LiberaApid enum values.

  • sample_group_name (str) – The name of the sample group to extract from the L1A dataset.

Returns:

A tuple containing: - DataFrame with ET time column and sample data fields - UTC time range tuple (start, end) for the data

Return type:

tuple[pd.DataFrame, tuple[datetime, datetime]]

Raises:
  • FileNotFoundError – If the NetCDF file does not exist at the specified path

  • ValueError – If the file cannot be opened as a valid NetCDF file, or if validation errors occur in create_kernel_dataframe_from_l1a()

Examples

>>> from libera_utils.constants import LiberaApid
>>> df, utc_range = create_kernel_dataframe_from_l1a_netcdf(
...     netcdf_path="path/to/l1a_file.nc",
...     apid=LiberaApid.jpss_sc_pos,
...     sample_group_name="ADGPS"
... )
libera_utils.kernel_maker.create_kernel_from_l1a(l1a_data: str | CloudPath | Path | Dataset, kernel_identifier: str | DataProductIdentifier, output_dir: str | CloudPath | Path, overwrite=False) CloudPath | Path#

Create a SPICE kernel from a single L1A Dataset for a kernel data product type.

This operates on a single L1A Dataset (or path to an L1A NetCDF file). The assumption is that this L1A file should contain all the necessary data to create the requested SPICE kernel type. Multiple inputs are expected to be handled at the level of creating the L1A data product from source data (packets).

Parameters:
  • l1a_data (str | filenaming.PathType | xr.Dataset) – L1A Dataset or path to L1A NetCDF file containing decoded packet data suitable for generating the requested SPICE kernel.

  • kernel_identifier (str | DataProductIdentifier) – Data product identifier that is associated with a kernel.

  • output_dir (str | filenaming.PathType) – Output location for the SPICE kernels and output manifest.

  • overwrite (bool) – Option to overwrite any existing similar-named SPICE kernels.

Returns:

Output kernel file path.

Return type:

filenaming.PathType

libera_utils.kernel_maker.create_kernel_from_packets(input_data_files: list[str | CloudPath | Path], kernel_identifier: str | DataProductIdentifier, output_dir: str | CloudPath | Path, overwrite=False) CloudPath | Path#

Create a SPICE kernel from one or more input packet files and kernel data product type.

The packet files passed as input must be convertible to L1A Dataset products. This function is a light wrapper around the core kernel creation logic that handles creating kernels from L1A Datasets.

This function is not intended for use in the production pipeline since L1A processing is a a separate step from kernel generation. However, for development and analysis purposes, this allows us to run both steps in one function call: packets -> L1A Dataset -> SPICE kernel.

Parameters:
  • input_data_files (list[str, filenaming.PathType]) – List of packet files to process. Multiple files are combined into a single L1A dataset before extracting data for kernel generation.

  • kernel_identifier (str | DataProductIdentifier) – Data product identifier that is associated with a kernel.

  • output_dir (str | filenaming.PathType) – Output location for the SPICE kernels and output manifest.

  • overwrite (bool) – Option to overwrite any existing similar-named SPICE kernels.

Returns:

Output kernel file path.

Return type:

filenaming.PathType

libera_utils.kernel_maker.create_kernels_from_manifest(input_manifest: str | CloudPath | Path, kernel_product_ids: str | DataProductIdentifier | list[str | DataProductIdentifier], output_dir: str | CloudPath | Path, overwrite=False)#

Generate SPICE kernels from a manifest file of L1A NetCDF products.

Parameters:
  • input_manifest (str | filenaming.PathType) – Input manifest file containing one or more L1A NetCDF product files containing decoded packet data suitable for generating the requested SPICE kernels.

  • kernel_product_ids (str | DataProductIdentifier | list[str | DataProductIdentifier]) – One or more SPICE kernel data product identifiers for SPICE kernel products to generate.

  • output_dir (str | filenaming.PathType) – Output location for the SPICE kernels and output manifest.

  • overwrite (bool, optional) – Option to overwrite any existing similar-named SPICE kernels.

Returns:

Output manifest file containing one or more kernel files.

Return type:

libera_utils.io.manifest.Manifest

libera_utils.kernel_maker.elevation_error(angle: float | floating | ndarray | Series) float | floating | ndarray | Series#

Elevation encoder error at the telemetered angle(s).

Parameters:

angle (AngleLike) – Telemetered elevation angle(s), in radians.

Returns:

Encoder error, in radians, to subtract from the telemetry.

Return type:

AngleLike

libera_utils.kernel_maker.jpss_kernel_cli_handler(parsed_args: Namespace)#

Generate SPICE JPSS kernels from command line arguments.

Parameters:

parsed_args (argparse.Namespace) – Namespace of parsed CLI arguments.

Returns:

Output manifest file containing one or more kernel files.

Return type:

libera_utils.io.manifest.Manifest

libera_utils.kernel_maker.mechanism_quaternions(angles: float | floating | ndarray | Series, axis: ndarray) ndarray#

SPICE scalar-first quaternions for rotation by each angle about axis.

q = [cos(theta/2), sin(theta/2) * axis] represents R(axis, theta), the mechanism frame’s rotation relative to its parent. Returns an (N, 4) array ordered (c, x, y, z).

Notes

The Az/El CK configs must declare FLIP SPICE QUATERNIONS (not plain SPICE QUATERNIONS) for these to load correctly. With FLIP, MSOPCK yields pxform(mechanism, parent) = R(axis, +angle); plain SPICE QUATERNIONS stores the transpose (the inverse rotation), which shows up as a large pointing error. This pairing of the scalar-first half-angle form with the FLIP declaration was pinned empirically against a controlled single-axis rotation, so the two must stay in sync.

libera_utils.kernel_maker.reverse_encoder_corrections(df: DataFrame) DataFrame#

Recover the raw telemetered Az/El encoder columns from corrected values, in place.

Inverse of apply_encoder_corrections(); a no-op for DataFrames without the encoder columns. Returns the same DataFrame instance for convenience.

libera_utils.kernel_maker.uncorrect_azimuth(corrected: float | floating | ndarray | Series) float | floating | ndarray | Series#

Recover telemetered azimuth angle(s) from corrected value(s).

Inverse of correct_azimuth(), solved by fixed-point iteration on telemetry = corrected + azimuth_error(telemetry).

Parameters:

corrected (AngleLike) – Corrected azimuth angle(s), in radians.

Returns:

Telemetered azimuth angle(s), in radians.

Return type:

AngleLike

libera_utils.kernel_maker.uncorrect_elevation(corrected: float | floating | ndarray | Series) float | floating | ndarray | Series#

Recover telemetered elevation angle(s) from corrected value(s).

Inverse of correct_elevation(), solved by fixed-point iteration on telemetry = corrected + elevation_error(telemetry).

Parameters:

corrected (AngleLike) – Corrected elevation angle(s), in radians.

Returns:

Telemetered elevation angle(s), in radians.

Return type:

AngleLike