lunartrace.display_sun
Repository display geometry from pinned NAIF DE421 kernels, not observation science.
Generates the display-only Sun direction and site elevation/azimuth carried by
lunartrace.projection.DisplaySunProjection. The geometry is computed with SPICE
(spiceypy) from the byte-pinned kernels listed in contracts/spice-kernels.manifest.json.
Frame and aberration MOON_ME_DE421 matches the Site01 source raster’s mean-Earth frame (MOON_PA would rotate the mapped coordinates). The aberration correction is NONE, meaning simultaneous geometric Sun/Moon positions, not apparent or photometric illumination.
Limits No terrain occlusion is computed. The result is a display parameter and never changes the standing of an observation.
Concurrency
SPICE owns process-global state: use an otherwise empty kernel pool, and do not call
other SPICE code concurrently with this generator. Calls to compute_display_sun
within one process are serialised by an internal lock.
load_kernel_manifest
Section titled “load_kernel_manifest”function
def load_kernel_manifest() -> list[DisplayKernel]Read the committed SPICE kernel manifest and return its kernels in load order.
Reads spice-kernels.manifest.json from the package’s _contracts copy of
contracts/. The manifest is validated for schema and frame; the kernel bytes themselves are not read here.
Callers must pass each kernel through verify_kernel before use, so that cached
files are never admitted on name alone.
Returns
Section titled “Returns”list of DisplayKernel— Kernels in the order the manifest lists them, which is the load order.
Raises
Section titled “Raises”ValueError— If the manifest schema is notlunartrace.spice_kernels/v0, its frame is notMOON_ME_DE421, or the kernel entries fail validation.
verify_kernel
Section titled “verify_kernel”function
def verify_kernel(path: Path, kernel: DisplayKernel) -> NoneCheck that a kernel file matches its pinned size and SHA-256 digest.
Missing files and integrity mismatches are distinct, actionable failures.
Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
path | Path | Local path of the kernel file. |
kernel | DisplayKernel | Pinned name, size in bytes and SHA-256 digest to check against. |
Raises
Section titled “Raises”FileNotFoundError— Ifpathdoes not exist.ValueError— If the file size or SHA-256 digest does not matchkernel.
site01_centre
Section titled “site01_centre”function
def site01_centre() -> DisplaySiteReturn the display location at the grid extent midpoint of the Site01 projection.
This is the midpoint of the grid extent, not the ROI centroid. The midpoint is
transform(cols / 2, rows / 2) in rasterio affine order, at pixel corners.
The projected midpoint is then inverted with a spherical south-polar stereographic
projection, using the radius and lon_0 stated in the fixture CRS.
Returns
Section titled “Returns”DisplaySite— NamedSite01 grid extent centre, with latitude and longitude in degrees (east-positive).
Raises
Section titled “Raises”ValueError— If the fixture’scrs_proj4is not the documented spherical polar CRS+proj=stere +lat_0=-90 +lat_ts=-90 +lon_0=0 +x_0=0 +y_0=0 +R=1737400 +units=m.FileNotFoundError— If the packaged copy of the Site01 fixture is absent (a broken installation).
The fixture is contracts/fixtures/pgda78-site01.slope-quality.projection.json, read
from its packaged copy. The
CRS radius is 1737400 m, which matches MOON_RADIUS_KM (1737.4 km). The inverse
uses latitude = 2 atan(rho / (2 R)) - 90 degrees and longitude = atan2(x, y), where
rho = hypot(x, y) and x and y are in metres.
compute_display_sun
Section titled “compute_display_sun”function
def compute_display_sun( epoch_utc: str, kernel_dir: Path = DEFAULT_KERNEL_DIR, *, site: DisplaySite | None = None,) -> DisplaySunProjectionGenerate the display Sun direction and site elevation/azimuth for a UTC epoch.
Parameters
Section titled “Parameters”| Name | Type | Description |
|---|---|---|
epoch_utc | str | Explicit ISO-8601 UTC instant ending in Z, for example 2026-10-10T00:00:00Z. Local times without the Z suffix are rejected. |
kernel_dir | Path | Directory holding the pinned kernel files, named as in the manifest. Defaults to build/spice under the repository root. Kernels are not shipped in the wheel: an installed user must run tools/fetch_spice.py from a checkout, then pass the directory here. Default DEFAULT_KERNEL_DIR. |
site | DisplaySite | Display location. When None, site01_centre is used. Default None. |
Returns
Section titled “Returns”DisplaySunProjection— Display-only result in frameMOON_ME_DE421with aberration correctionNONE.
Raises
Section titled “Raises”ValueError— Ifepoch_utcdoes not end inZor is not a valid ISO-8601 instant, or if a kernel fails the size or SHA-256 check inverify_kernel.FileNotFoundError— If a kernel file is absent fromkernel_dir. The message namestools/fetch_spice.pyand thekernel_dirparameter.RuntimeError— If the SPICE kernel pool is not empty on entry.
The direction is the Sun position relative to the Moon centre, in km, normalised to a
unit vector. The site vector up is the unit normal of a sphere of radius
MOON_RADIUS_KM. The site-to-Sun vector is local = S - R * up, where S is
the Moon-to-Sun position. Elevation is asin(local . up / |local|) in degrees, and
azimuth is atan2(east, north) modulo 360 degrees, measured clockwise from north.
The result is a display parameter, never tied to an observation or used to change its
standing. Calls are serialised by an internal lock, and the kernel pool is cleared in a
finally block even when a kernel fails to load.