nav.feature
Feature layer for autonomous navigation.
Each scene element the orchestrator considers is decomposed into
NavFeature instances emitted by registered NavModel instances.
Features carry their own uncertainty, preferred filter, and reliability;
techniques pick them up by feature type and produce per-technique offsets.
Modules:
feature_type
NavFeatureTypeenum (single canonical list of feature types).geometry
NavFeatureGeometrysum type and per-type geometry payload dataclasses.flags
NavFeatureFlagssum type and per-type flag dataclasses.feature
NavFeaturedataclass andNavReliabilityBreakdown.reliability
FeatureReliabilityGateand per-type reliability thresholds.constantsModule-level physical constants (cap angles, sentinel values).
Thread safety: every class in this package is stateless or is wrapped in a
frozen dataclass. Concurrent access from multiple threads is safe so long
as each thread holds its own ObsSnapshotInst (the underlying oops
Backplane queries mutate global precision state).
NavFeature — the smallest independently-navigable scene element.
Every scene that the orchestrator considers is decomposed into NavFeatures by the registered feature extractors. Each feature carries everything a technique needs to know to use it or ignore it: identity, geometry, uncertainty, a preferred filter, a reliability score, and which technique types are allowed to consume it.
- class NavFeature(feature_id: str, feature_type: NavFeatureType, source_model: str, geometry: StarGeometry | LimbPolyline | TerminatorPolyline | RingEdgePolyline | BodyDiscGeometry | BodyBlobGeometry | RingAnnulusGeometry | CartographicModelGeometry, subject_range_km: float, position_cov_px: ndarray[tuple[Any, ...], dtype[floating[Any]]] | None, intensity_sigma_rel: float, preferred_filter: NavFilterSpec, reliability: float, reliability_reasons: NavReliabilityBreakdown, usable_types: frozenset[NavFeatureType], flags: StarFlags | LimbArcFlags | TerminatorArcFlags | RingEdgeFlags | BodyDiscFlags | BodyBlobFlags | RingAnnulusFlags | CartographicModelFlags, template_img: ndarray[tuple[Any, ...], dtype[floating[Any]]] | None = None, template_mask: ndarray[tuple[Any, ...], dtype[bool]] | None = None)[source]
Bases:
objectA single navigable scene element with everything techniques need.
NavFeatures are produced per-image by stateless extractors; no cross-image state is involved. They carry their own uncertainty in image-plane pixel units, a preferred filter for the matching metric, and a self-assessed reliability score that the orchestrator’s gate consults before invoking techniques.
- Parameters:
feature_id – Unique identifier within a single NavResult. Format is
<type_lc>:<scope>; e.g.star:UCAC4:144787700,limb_arc:MIMAS,ring_edge:SATURN:A_outer. Two features with the same ID is an extractor bug.feature_type – One of the
NavFeatureTypevalues.source_model – Name of the NavModel that produced this feature (
'stars','body','rings', etc.).geometry – One of the
NavFeatureGeometryvariants matching the feature type.subject_range_km – Distance from observer to the feature subject in kilometers. Used to depth-sort body features when building combined templates.
template_img – Optional pre-rendered model template (small postage stamp). Set for BODY_DISC, RING_ANNULUS, and CARTOGRAPHIC_MODEL;
Nonefor feature types whose geometry alone is sufficient.template_mask – Optional boolean mask matching
template_img;Truewhere the template carries signal.position_cov_px – 2x2 image-plane covariance in pixels for scalar features (STAR, BODY_BLOB).
Nonefor polyline-payload and template-payload features whose covariance is per-vertex or derived from the matching peak.intensity_sigma_rel – Relative brightness uncertainty (scalar in
[0, 1]);0is “perfect brightness prediction”.preferred_filter – NavFilterSpec the feature requests for both the template and the surrounding image patch.
reliability – Self-assessed reliability score in
[0, 1].reliability_reasons – Per-component breakdown of the reliability score; lets the curator surface why a feature was scored confidently or rejected.
usable_types – Frozen set of feature types this feature is allowed to be consumed as. Always contains its own
feature_typeand may include compatible cohabitants (a body’s LIMB_ARC and BODY_DISC are separate features with the same body_name; they differ only in payload shape).flags – Typed feature-type-specific flags dataclass.
- __post_init__() → None[source]
Validate invariants and freeze numpy arrays.
Raises ValueError on out-of-range reliability, empty feature_id, or covariance matrices that are not 2x2 symmetric positive-semidefinite.
- property body_name: str
SPICE body name this feature traces, or
''for non-body features.Reads the structured
body_namecarried on the body-feature flag dataclasses (LimbArcFlags,TerminatorArcFlags,BodyDiscFlags,BodyBlobFlags,CartographicModelFlags). Star and ring flags have no body, so the value is''. Consumers should prefer this over parsing thefeature_idstring.
- feature_type: NavFeatureType
- flags: StarFlags | LimbArcFlags | TerminatorArcFlags | RingEdgeFlags | BodyDiscFlags | BodyBlobFlags | RingAnnulusFlags | CartographicModelFlags
- geometry: StarGeometry | LimbPolyline | TerminatorPolyline | RingEdgePolyline | BodyDiscGeometry | BodyBlobGeometry | RingAnnulusGeometry | CartographicModelGeometry
- preferred_filter: NavFilterSpec
- reliability_reasons: NavReliabilityBreakdown
- usable_types: frozenset[NavFeatureType]
- class NavReliabilityBreakdown(predicted_snr: float | None = None, visible_arc_fraction: float | None = None, incidence_factor: float | None = None, albedo_penalty: float | None = None, shadow_occluded_fraction: float | None = None, visible_lit_fraction: float | None = None, overflow_fraction: float | None = None, blob_snr: float | None = None, blob_extent_px: float | None = None, in_body_silhouette: bool | None = None, in_saturation_or_cosmic: bool | None = None, smear_length_ok: bool | None = None)[source]
Bases:
objectPer-component reliability contributions for a NavFeature.
All fields are optional
[0, 1]floats (or booleans where noted). A missing field means “not applicable for this feature type”, not zero.- Parameters:
predicted_snr – STAR — detection contribution derived from the star’s magnitude margin to the limiting magnitude (effective SNR), not a DN-based photometric SNR.
visible_arc_fraction – LIMB_ARC, TERMINATOR_ARC, RING_EDGE — fraction of total predicted arc length in extfov and not occluded.
incidence_factor – LIMB_ARC — limb-incidence-angle softening factor.
albedo_penalty – TERMINATOR_ARC — albedo-variation penalty term.
shadow_occluded_fraction – RING_EDGE — fraction of polyline vertices dropped to planet shadow.
visible_lit_fraction – BODY_DISC — fraction of the whole predicted disc (lit + dark) that is both lit (cos(incidence) >= 0) and inside the sensor. Despite the name the denominator is the entire disc, not the lit hemisphere, so this falls with phase even for a fully-framed body — intentional, so the BODY_DISC gate screens out thin high-phase crescents (a poor disc template) as well as partially-framed discs.
overflow_fraction – BODY_DISC — fraction of the predicted disc area outside the sensor.
blob_snr – BODY_BLOB — image SNR within the predicted body bbox.
blob_extent_px – BODY_BLOB — predicted body extent (longer axis) in pixels.
in_body_silhouette – STAR — True if the predicted star is inside a predicted body silhouette.
in_saturation_or_cosmic – STAR — True if the predicted star pixel falls inside a saturation/cosmic-ray mask pixel.
smear_length_ok – STAR — True if smear length is below the
stars.max_smearreject gate.
- body_names_from_features(features: Iterable[NavFeature]) → frozenset[str][source]
Return the set of non-empty body names across
features.Uses each feature’s structured
NavFeature.body_namerather than parsingfeature_idstrings, so the source-body identity a technique reports cannot silently diverge from a change to the feature-id format.
Enum of feature types produced by NavFeatureExtractors.
A NavFeature carries one of these tags identifying which kind of independently-navigable scene element it represents.
Modules:
The single canonical list of NavFeatureType values. New types are added by adding an enum value here and providing an extractor that emits it.
- class NavFeatureType(*values)[source]
Bases:
EnumThe kind of scene element a NavFeature represents.
Each value names a category of independently-navigable scene element with its own geometry, uncertainty model, and consuming techniques.
STAR: a single catalog star (one(v, u)point).LIMB_ARC: one body’s lit limb expressed as a polyline of vertices.TERMINATOR_ARC: one body’s terminator polyline.BODY_DISC: a body disc rendered as a pixel template for correlation.BODY_BLOB: a body that is too irregular or under-resolved to fit a limb arc; carries only a predicted centroid and bounding box.RING_EDGE: a single named ring edge expressed as a polyline.RING_ANNULUS: a multi-ring composite rendered as a pixel template, used when individual edges cannot be separated at the image resolution.TITAN_LIMB: reserved for atmospheric-body navigation; never emitted by the current extractor set (the algorithm is unimplemented).CARTOGRAPHIC_MODEL: a pre-built cartographic mosaic of a body reprojected into the predicted body silhouette for high-detail correlation.
- BODY_BLOB = 'BODY_BLOB'
- BODY_DISC = 'BODY_DISC'
- CARTOGRAPHIC_MODEL = 'CARTOGRAPHIC_MODEL'
- LIMB_ARC = 'LIMB_ARC'
- RING_ANNULUS = 'RING_ANNULUS'
- RING_EDGE = 'RING_EDGE'
- STAR = 'STAR'
- TERMINATOR_ARC = 'TERMINATOR_ARC'
- TITAN_LIMB = 'TITAN_LIMB'
Sum-type variants describing the geometry of a NavFeature.
Each NavFeature carries a geometry payload whose concrete dataclass
type matches the feature_type. The payload holds whatever the consuming
technique needs to know about where in the image the feature lives —
image-side operations remain global, so no payload describes a per-feature
image crop.
Coordinates are in extended-FOV (extfov) image coordinates (v, u). Bounding
boxes are half-open in the numpy slicing sense: v_min, u_min, v_max,
u_max with arr[v_min:v_max, u_min:u_max] covering the box.
- class BodyBlobGeometry(predicted_center_vu: tuple[float, float], bbox_extfov_vu: tuple[int, int, int, int], predicted_diameter_px: float)[source]
Bases:
objectGeometry payload for a BODY_BLOB feature.
Carries only the predicted centroid and bounding extent of an under- resolved or irregular body. No template is rendered.
- Parameters:
predicted_center_vu – Predicted body center in extfov coordinates.
bbox_extfov_vu – Half-open bounding box around the predicted body.
predicted_diameter_px – Predicted disc diameter in pixels (longer axis of the predicted ellipse silhouette).
- class BodyDiscGeometry(bbox_extfov_vu: tuple[int, int, int, int], predicted_center_vu: tuple[float, float], overflow_fraction: float)[source]
Bases:
objectGeometry payload for a BODY_DISC feature.
The body’s full-disc rendering is carried on
NavFeature.template_img; the geometry payload only records the position of that template within the extfov image, the predicted body-center pixel, and the fraction of the predicted disc area that falls outside the sensor.- Parameters:
bbox_extfov_vu – Half-open bounding box where the template sits.
predicted_center_vu – Predicted body center in extfov coordinates.
overflow_fraction – Fraction of the disc area outside the sensor
[0, 1];0means fully in-FOV.
- class CartographicModelGeometry(bbox_extfov_vu: tuple[int, int, int, int], predicted_center_vu: tuple[float, float], overflow_fraction: float)[source]
Bases:
objectGeometry payload for a CARTOGRAPHIC_MODEL feature.
A pre-built cartographic mosaic of a body, reprojected into the predicted body silhouette and stored on
NavFeature.template_img. Same shape asBodyDiscGeometry— the difference is that the template carries surface detail rather than smooth Lambert shading.- Parameters:
bbox_extfov_vu – Half-open bounding box where the template sits.
predicted_center_vu – Predicted body center in extfov coordinates.
overflow_fraction – Fraction of the disc area outside the sensor.
- class LimbPolyline(vertices_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], normals_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_normal_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_tangent_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], bbox_extfov_vu: tuple[int, int, int, int])[source]
Bases:
objectGeometry payload for a LIMB_ARC feature.
A polyline of vertices along a body’s predicted limb, after extraction-time cropping for occlusion / off-FOV / shadow. Each vertex carries its own normal direction and per-vertex anisotropic uncertainty.
- Parameters:
vertices_vu –
(N, 2)array of (v, u) per surviving vertex.normals_vu –
(N, 2)array of outward limb normal per vertex.sigma_normal_per_vertex_px –
(N,)per-vertex sigma along normal.sigma_tangent_per_vertex_px –
(N,)per-vertex sigma along tangent; typically a small constant (~0.5 px) reflecting polyline sampling resolution.bbox_extfov_vu – Half-open bounding box of the polyline.
- NavFeatureGeometry = nav.feature.geometry.StarGeometry | nav.feature.geometry.LimbPolyline | nav.feature.geometry.TerminatorPolyline | nav.feature.geometry.RingEdgePolyline | nav.feature.geometry.BodyDiscGeometry | nav.feature.geometry.BodyBlobGeometry | nav.feature.geometry.RingAnnulusGeometry | nav.feature.geometry.CartographicModelGeometry
Sum type spanning every NavFeatureType’s geometry payload.
- class RingAnnulusGeometry(bbox_extfov_vu: tuple[int, int, int, int], predicted_center_vu: tuple[float, float])[source]
Bases:
objectGeometry payload for a RING_ANNULUS feature.
Multi-ring composite template carried on
NavFeature.template_img; this payload records only the template’s location in the extfov image and the predicted ring-system center.- Parameters:
bbox_extfov_vu – Half-open bounding box where the template sits.
predicted_center_vu – Predicted planet center for the ring system.
- class RingEdgePolyline(vertices_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], normals_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_radial_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_along_edge_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], is_straight_line: bool, bbox_extfov_vu: tuple[int, int, int, int])[source]
Bases:
objectGeometry payload for a RING_EDGE feature.
Polyline of vertices along one named ring edge. Each vertex’s per-axis uncertainty is along the radial direction (across the edge) and along the edge tangent. The straight-line flag is set when the projected polyline’s deviation from a best-fit straight line is below threshold; in that case its rank-1 covariance must be combined with another feature to resolve a 2-D offset.
- Parameters:
vertices_vu –
(N, 2)(v, u) per vertex.normals_vu –
(N, 2)radially outward per vertex.sigma_radial_per_vertex_px –
(N,)sigma across the edge (radial).sigma_along_edge_per_vertex_px –
(N,)sigma along the edge.is_straight_line –
Trueif the polyline’s max-deviation from a best-fit straight line is below the curvature threshold.bbox_extfov_vu – Half-open bounding box of the polyline.
- class StarGeometry(predicted_vu: tuple[float, float], catalog_vu: tuple[float, float], bbox_extfov_vu: tuple[int, int, int, int])[source]
Bases:
objectGeometry payload for a STAR feature.
Single (v, u) point in extended-FOV coordinates plus the catalog-derived prediction from which it was generated. The two are equal at extraction time and may differ after a refinement step records the matched detection.
- Parameters:
predicted_vu – Predicted star (v, u) in extfov coordinates.
catalog_vu – Catalog-aberrated star (v, u) in extfov coordinates. Equal to
predicted_vuat extraction; may differ after refinement.bbox_extfov_vu – Half-open bounding box
(v_min, u_min, v_max, u_max)covering the postage stamp around the predicted position.
- class TerminatorPolyline(vertices_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], normals_vu: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_normal_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], sigma_tangent_per_vertex_px: ndarray[tuple[Any, ...], dtype[floating[Any]]], bbox_extfov_vu: tuple[int, int, int, int])[source]
Bases:
objectGeometry payload for a TERMINATOR_ARC feature.
Mirrors
LimbPolylinewith terminator-specific semantics — the vertices lie along the terminator (wherecos(incidence) == 0) rather than the silhouette. Per-vertex sigma_normal is generally larger than the matching limb because albedo variation softens the photometric edge.Parameters: see
LimbPolyline(identical field set).
Sum-type flag dataclasses carried on NavFeature.flags.
Each feature type has a small dataclass listing the technique-specific
boolean / scalar flags relevant to that type. Carrying them as a typed sum
type instead of a free-form dict[str, Any] lets static type checkers see
which fields exist for each type and lets curator code copy known fields by
attribute.
- class BodyBlobFlags(body_name: str = '', predicted_diameter_px: float = 0.0, phase_angle_deg: float = 0.0, phase_irregularity_factor: float = 0.0, sub_solar_dir_vu: tuple[float, float] = (0.0, 0.0))[source]
Bases:
objectFlags carried on a BODY_BLOB feature.
- Parameters:
body_name – SPICE body name whose blob this feature represents.
predicted_diameter_px – Predicted disc diameter in pixels (longer axis of the predicted ellipse silhouette). Must be
>= 0.phase_angle_deg – Phase angle (Sun -> body -> observer) at the body’s center, in degrees. Recorded for diagnostic inspection; the BLOB confidence formula consumes
phase_irregularity_factorinstead, since raw phase alone understates the centroid uncertainty for an irregular body. Must be in[0, 180].phase_irregularity_factor – Dimensionless coupling of phase angle and shape irregularity, computed by the body NavModel as
(ellipsoid_rms_residual_km / body_radius_km) * (1 + 2 * sin^2(phase / 2)). Captures the centroid-bias risk that the lit-weighted predicted centroid cannot fully correct for. The fractionalresidual / radiusterm is ~ 0.005 for regular moons and ~ 0.05-0.10 for irregular satellites; the phase factor goes from 1 at full-phase (rotational orientation always unknown) to 3 at full crescent (most of the body unlit, hiding most of the irregularity). Must be>= 0.sub_solar_dir_vu – Unit
(v, u)image-plane direction from the body’s geometric center toward the bright limb (the projection of the body-to-Sun vector).(0.0, 0.0)when the direction is unknown or undefined (a near-full-phase body whose lit centroid coincides with its geometric center).BodyBlobNavorients its phase-aware coarse-acquisition template along this direction so a high-phase crescent displaced beyond its predicted bounding box is still found; a filled-disc template cannot match a thin crescent. Both components must lie in[-1, 1].
- class BodyDiscFlags(body_name: str = '', overflow_fov_fraction: float = 0.0)[source]
Bases:
objectFlags carried on a BODY_DISC feature.
- Parameters:
body_name – SPICE body name whose disc this feature renders.
overflow_fov_fraction – Fraction of the disc area outside the sensor
[0, 1]. Same value asBodyDiscGeometry.overflow_fraction; duplicated here for type-specific access.
- class CartographicModelFlags(body_name: str = '', mosaic_source: str = '')[source]
Bases:
objectFlags carried on a CARTOGRAPHIC_MODEL feature.
- Parameters:
body_name – SPICE body name the cartographic mosaic represents.
mosaic_source – Identifier of the mosaic file (e.g. file basename or URL).
- class LimbArcFlags(body_name: str = '', visible_arc_fraction: float = 0.0)[source]
Bases:
objectFlags carried on a LIMB_ARC feature.
- Parameters:
body_name – SPICE body name whose limb this arc traces.
visible_arc_fraction – Fraction of total limb length inside extfov and not occluded
[0, 1].
- NavFeatureFlags = nav.feature.flags.StarFlags | nav.feature.flags.LimbArcFlags | nav.feature.flags.TerminatorArcFlags | nav.feature.flags.RingEdgeFlags | nav.feature.flags.BodyDiscFlags | nav.feature.flags.BodyBlobFlags | nav.feature.flags.RingAnnulusFlags | nav.feature.flags.CartographicModelFlags
Sum type spanning every NavFeatureType’s flag dataclass.
- class RingAnnulusFlags(planet_name: str = '', constituent_edge_count: int = 0)[source]
Bases:
objectFlags carried on a RING_ANNULUS feature.
- Parameters:
planet_name – Planet whose ring system this annulus represents.
constituent_edge_count – Number of catalog edges fused into this annulus template. Must be a non-negative integer.
- class RingEdgeFlags(is_straight_line: bool = False, polarity_predictable: bool = False, edge_name: str = '', planet_name: str = '')[source]
Bases:
objectFlags carried on a RING_EDGE feature.
- Parameters:
is_straight_line – True when the polyline’s deviation from a straight-line fit is below threshold. Triggers rank-1 covariance handling at the technique level.
polarity_predictable – True only when the per-edge static-catalog entry guarantees the gradient direction across the edge in this scene. Default is False.
edge_name – Name of the ring edge in the static catalog.
planet_name – Planet whose rings this edge belongs to.
- class StarFlags(saturated: bool = False, smear_length_px: float = 0.0, in_body_silhouette: bool = False, in_saturation_or_cosmic_mask: bool = False, predicted_snr: float = 0.0, vmag: float | None = None)[source]
Bases:
objectFlags carried on a STAR feature.
- Parameters:
saturated – True if the detected star peak hit the camera’s full-well DN; centroiding switches from peak-Gaussian-fit to annular brightness-weighted moment.
smear_length_px – Expected smear length in pixels at this image’s spacecraft attitude rate. Must be
>= 0.in_body_silhouette – True if the predicted star position falls inside a predicted body silhouette in extfov.
in_saturation_or_cosmic_mask – True if the predicted star position falls inside a saturation or cosmic-ray mask pixel.
predicted_snr – Magnitude-margin-derived effective SNR for the catalog star (
SNR_REF * 2.512 ** (mag_limit - vmag)), not a DN-based photometric SNR. Monotone in catalog brightness, soStarUniqueMatchNavcan still rank stars by it when picking the unique-bright pair.0.0for fixtures or features whose model did not populate it. Must be>= 0.vmag – Catalog V-band magnitude of the star, or
Nonewhen the catalog entry has no magnitude. Used byStarUniqueMatchNavto compute the magnitude margin to the next-brightest star.
- class TerminatorArcFlags(body_name: str = '', visible_arc_fraction: float = 0.0, phase_angle_factor: float = 0.0)[source]
Bases:
objectFlags carried on a TERMINATOR_ARC feature.
- Parameters:
body_name – SPICE body name whose terminator this arc traces.
visible_arc_fraction – Fraction of total terminator length inside extfov and lit
[0, 1].phase_angle_factor –
sin(phase_angle)factor used in reliability; peaks at 90-degree crescent. Must lie in[0, 1].
Compose template-bearing features into a single ext-FOV image and mask.
Some downstream consumers (the manual-navigation dialog, the summary-PNG
overlay) want a single 2-D representation of “what the predicted scene
looks like” rather than a per-feature collection. This module builds that
composite by Z-buffer painting every feature that carries a
template_img / template_mask payload, ordered by subject range so
nearer features paint over farther ones.
compose_template_features() is the bitmap-only composer (limbs,
terminators, ring edges are skipped; their geometry belongs to the
annotation pipeline). compose_dialog_overlay() extends it by
rasterizing every polyline-bearing feature on top — that is the composite
the manual-navigation dialog overlays on the source image so an operator
sees limbs / terminators / ring edges even when the body emits no
full-disc template.
- compose_dialog_overlay(features: list[NavFeature], extfov_shape_vu: tuple[int, int]) → tuple[ndarray[tuple[Any, ...], dtype[floating[Any]]], ndarray[tuple[Any, ...], dtype[bool]]][source]
Compose the manual-navigation dialog’s full-scene overlay.
Starts from
compose_template_features()(BODY_DISC, RING_ANNULUS, CARTOGRAPHIC_MODEL templates) and additionally rasterizes:every polyline-bearing feature’s
vertices_vuas single-pixel marks (LIMB_ARC, TERMINATOR_ARC, RING_EDGE);every BODY_BLOB’s predicted-diameter circle outline at the predicted centroid;
every STAR feature’s bbox as a rectangle outline at the predicted-vu position so the operator can manually align catalog stars with the observed bright pixels.
All rasterization is intentionally minimal — it is a visibility aid, not a precise renderer; the autonomous DT / RANSAC pipeline owns the quantitative fit.
Vertices and markers that fall outside the ext-FOV bounds are silently dropped (the polyline samplers can hand back partially-clipped polylines near the FOV edge; star markers near the FOV edge are clipped to the visible portion).
- Parameters:
features – The feature list (templated + polyline + plain).
extfov_shape_vu – Shape
(v, u)of the ext-FOV array to build.
- Returns:
Tuple
(image, mask)whereimageis float64 in ext-FOV coordinates andmaskis a boolean array of the same shape. Every painted pixel (template or polyline or marker) is True in the mask.
- compose_template_features(features: list[NavFeature], extfov_shape_vu: tuple[int, int]) → tuple[ndarray[tuple[Any, ...], dtype[floating[Any]]], ndarray[tuple[Any, ...], dtype[bool]]][source]
Z-buffer paint template features into a single ext-FOV image+mask.
Features are sorted by
subject_range_kmascending (nearer features last), so the closest body’s pixels overwrite farther bodies’ on overlap. Each feature’s template is placed at itsgeometry.bbox_extfov_vulocation; pixels marked True in the feature’stemplate_maskcarry the template’s value into the composite, and the composite mask becomes the OR of every painted feature’s mask.Features without a
template_imgortemplate_maskare skipped.- Parameters:
features – The feature list (may include non-template features).
extfov_shape_vu – Shape
(v, u)of the ext-FOV array to build.
- Returns:
Tuple
(image, mask)whereimageis float64 in ext-FOV coordinates andmaskis a boolean array of the same shape.
Reliability gate — drops features whose self-assessed reliability is too low.
Each feature carries a [0, 1] reliability score it computed at extraction time. The orchestrator runs this gate between extraction and technique invocation; gated-out features are recorded in the feature inventory with their rejection reason but are not passed to any technique.
The thresholds live in config_520_features.yaml per feature type with
optional per-instrument overrides. Default values defined here are used
when no override is supplied by the loader.
- DEFAULT_RELIABILITY_THRESHOLDS: Final[dict[NavFeatureType, float]] = {NavFeatureType.BODY_BLOB: 0.2, NavFeatureType.BODY_DISC: 0.3, NavFeatureType.CARTOGRAPHIC_MODEL: 0.3, NavFeatureType.LIMB_ARC: 0.3, NavFeatureType.RING_ANNULUS: 0.3, NavFeatureType.RING_EDGE: 0.3, NavFeatureType.STAR: 0.2, NavFeatureType.TERMINATOR_ARC: 0.3, NavFeatureType.TITAN_LIMB: 0.3}
Default per-type reliability thresholds.
Feature types not present in this map fall through with a 0.0 threshold (no gate). Values are placeholders subject to empirical calibration.
- class FeatureReliabilityGate(thresholds: dict[~nav.feature.feature_type.NavFeatureType, float]=<factory>)[source]
Bases:
objectStateless gate filtering features by per-type reliability threshold.
- Parameters:
thresholds – Mapping
feature_type -> minimum reliability. Falls back to 0.0 (no gate) for missing keys.- Raises:
TypeError – if any key in
thresholdsis not aNavFeatureTypeor any value is not numeric.ValueError – if any threshold is non-finite or outside
[0, 1].
- apply(features: list[NavFeature]) → tuple[list[NavFeature], list[GatedFeatureRecord]][source]
Split
featuresinto kept and gated lists.- Parameters:
features – All features emitted by extractors.
- Returns:
Tuple
(kept, gated)wheregatedcarries rejection reasons.
- thresholds: dict[NavFeatureType, float]
- class GatedFeatureRecord(feature: NavFeature, reason: str)[source]
Bases:
objectDiagnostic record for a feature dropped by the gate.
- Parameters:
feature – The feature that was dropped.
reason – Stable string describing why; used by the curator and tests.
- feature: NavFeature
Module-level constants used across feature extraction and reliability scoring.
These constants encode physically-motivated thresholds and caps referenced across feature-extraction and confidence-scoring formulas. Keeping them in one file makes the formulas self-documenting at the point of use and gives a single edit-site when calibration changes their values.
Each constant carries a one-line docstring with units and intent. Constants that have a YAML-config equivalent (per-instrument tunables) belong in the config files; only physically-motivated values live here.
- AGREEMENT_FACTOR_CAP: float = 1.5
Maximum boost (multiplicative) the ensemble agreement factor may apply.
Bounds the
1 + 0.5 * max(0, log2(n_significant))formula; even when many techniques agree, the boost never exceeds this multiplier.
- COMBINED_CONFIDENCE_CAP: float = 0.99
Maximum value the precision-weighted combined confidence may take.
Two correlated estimators agreeing strongly is treated as honest 0.99, never 1.0 — confidence is a calibrated proxy, not a probability.
- INCIDENCE_FACTOR_ANGLE_CAP_DEG: float = 80.0
Incidence angle (degrees) at which the softening factor saturates.
Beyond this angle,
incidence_factoris clamped toMAX_INCIDENCE_FACTOR_CAPrather than continuing to grow.
- INCIDENCE_FACTOR_CLIP_DEG: float = 85.0
Maximum incidence angle (degrees) used in cosine projection.
Used inside
cos(min(i, INCIDENCE_FACTOR_CLIP_DEG))to keep the cosine positive and bounded. Slightly larger than the saturation angle so the clamp behavior is smooth across the boundary.
- JSON_INF_SENTINEL: float = 1000000000.0
Finite sentinel substituted for
infin JSON output.In-memory
NavResultkeeps realinffor unbounded uncertainty axes (e.g. flat-ring-only scenes); the JSON curator clamps to this finite value for cross-language compatibility (strict JSON disallowsInfinity). Downstream consumers should treat any value>= 1e8as “axis unconstrained”.
- MAX_INCIDENCE_FACTOR_CAP: float = 4.76
Cap on incidence-angle softening factor (dimensionless).
Equal to
1 / cos(80 deg) - 1. Beyond an incidence angle of 80 degrees, the cosine projection becomes so steep that the limb pixel contributes essentially zero useful information about limb position; treating any pixel beyond 80 deg as having the same softness factor is the principled cap.
- MIN_ANISOTROPIC_SMEAR_PX: float = 0.5
Smear length below which star centroid covariance becomes isotropic.
When
L < MIN_ANISOTROPIC_SMEAR_PX, the smear axis is shorter than the PSF and anisotropy is sub-pixel-meaningless; the extractor uses(sigma_PSF / sqrt(SNR))^2 * I_2instead of the anisotropic formula.