Config and Static Data
Every RMS-NAV subsystem reads its tunables from a single
Config object loaded from a stack of YAML files. The
files split cleanly into two kinds: runtime configuration (knobs an operator
might want to tune per run — search ranges, emission thresholds, label fonts) and
static data (per-body shape tables, per-ring catalogues, per-instrument
calibration constants curated from external publications). Both kinds load through
the same loader; they differ in how they are reviewed and updated.
This chapter documents the loader, the section structure, the file layout, and the static-data citation discipline.
The Config object
Config lazily loads its YAML stack on first attribute
access. The stack is, in order (later files override earlier ones for the same key):
The bundled
src/nav/config_files/*.yamlfiles, sorted by filename. The 3-digit numeric prefix is the merge order; the file groups are documented under File layout below.nav_default_config.yamlin the current working directory (if present), for per-checkout personal defaults.Any files passed via
--config-file PATHon the CLI (repeatable; each merges in order).The handful of CLI flags that map to config keys (
--pds3-holdings-root,--nav-results-root, etc.) override the correspondingenvironmentblock entry.
Direct programmatic use:
from nav.config import Config, DEFAULT_CONFIG
cfg = Config() # lazy; reads the stack on first access
cfg.update_config('custom.yaml') # merge in an override file
print(cfg.offset.correlation_fft_upsample_factor)
print(cfg.environment.pds3_holdings_root)
The module-level DEFAULT_CONFIG singleton is what
most subsystems read when no explicit config= keyword is supplied.
Per-class config properties on
NavBase subclasses surface the same singleton
through dependency injection.
Sections
Top-level YAML keys are exposed as
AttrDict properties so code can write
cfg.bodies.use_lambert instead of cfg['bodies']['use_lambert']. The
shipping sections:
general— logging levels and other global settings.offset— correlation and star-refinement parameters.stars— star-model and ring-occlusion parameters; see Star Navigation Model.bodies— body rendering parameters; see Body Navigation Model.rings— ring-model parameters (planet shadow removal, fade widths, per-planetring_features); see Ring Navigation Model.titan— Titan-specific parameters (placeholder).bootstrap— bootstrap navigation parameters.backplanes— the list of body and ring backplanes to generate; see Backplanes.pds4— per-dataset PDS4 template directories and bundle names; see PDS4 Bundle Generation.environment— runtime paths (pds3_holdings_root,nav_results_root,backplane_results_root,bundle_results_root).body_shape— static per-body shape catalogue (see Static data: catalogues and citation discipline below).coiss/vgiss/gossi/nhlorri— per-camera blocks (noise,mag_offset,image_quality_thresholds,source_image_filter, etc.).techniques— per-NavTechniquetunables and confidence-formula coefficients; see Navigation Techniques.satellites— per-planet satellite lists used by the bodyNavModel’s inventory query.feature_emission— per-planetRING_EDGEvsRING_ANNULUSgates; see Ring Annulus Correlate (RingAnnulusNav).
The user-facing tour at Configuration covers how operators override these defaults with their own files; this chapter is the reference for what ships and where.
File layout
The numeric prefix encodes the load order and hints at the section’s role. The ranges are conventional, not enforced by the loader:
Prefix |
Group |
Files |
|---|---|---|
|
Global / model-shared |
|
|
Catalogues |
|
|
Per-target tables (static data) |
|
|
Per-planet ring catalogues (static data) |
|
|
Per-instrument camera blocks (mixed runtime + static) |
|
|
Per-technique tunables |
|
|
Downstream-product settings |
|
Per-file contents
Each shipping file and what it holds:
config_010_general— general settings, including all logging levels.config_020_offset— offset-finding and star-refinement parameters.config_030_stars— star-model and ring-occlusion parameters.config_040_bodies— body (planet / moon) rendering parameters.config_050_rings— ring-model parameters.config_060_titan— Titan-specific navigation parameters.config_070_bootstrap— bootstrap navigation parameters (angles in degrees).config_100_satellites— satellite definitions for each planet.config_220_body_shape— per-body shape table (radii, ellipsoid residual, crater scale, albedo) consumed by the body NavModel and feature extractors; see Static data: catalogues and citation discipline.config_300_jupiter_rings/config_310_saturn_rings/config_320_uranus_rings/config_330_neptune_rings— per-planet ring system parameters.config_400_inst_coiss— Cassini ISS instrument-specific settings.config_410_inst_gossi— Galileo SSI instrument-specific settings.config_420_inst_nhlorri— New Horizons LORRI instrument-specific settings.config_430_inst_vgiss— Voyager ISS instrument-specific settings.config_440_sim— simulated-image settings.config_510_techniques— per-NavTechnique confidence-formula coefficients and runtime tunables (spurious-detection thresholds, at-edge tolerances, minimum arc lengths) plus the planet-specificfeature_emission.ring_annulusblock that decides RING_EDGE vs RING_ANNULUS emission.config_900_backplanes— backplane-generation settings.config_950_pds4— PDS4 metadata and export settings for generated products, PDS4 label-template overrides, and the mapping of internal fields to PDS4 keys.
Loader rules
YAML mappings are deep-merged, not overwritten. A user override that sets
bodies.use_lambert: falsedoes not unset every other key underbodies.Lists are overwritten wholesale. A user override of
stars.catalogsoverwrites the bundled list rather than appending to it.Mapping keys whose name starts with
_are stripped at load time. This is the strip-rule that lets static-data files carry_sourcesblocks alongside their numeric values without bloating the parsedConfigobject; see Static data: catalogues and citation discipline.
Numeric values are typed by YAML; downstream consumers convert with explicit
casts where the section schema is mixed (e.g. the per-instrument
image_quality_thresholds block constructs a frozen
ImageQualityThresholds
dataclass).
Path resolution
The environment block carries the four downstream output roots:
pds3_holdings_root— read root for PDS3 holdings (default$PDS3_HOLDINGS_DIR, falling back tohttps://pds-rings.seti.org/holdings).nav_results_root— write root for_metadata.jsonand_summary.pngfiles produced bynav_offset.backplane_results_root— write root for backplane FITS / NumPy products produced bynav_backplanes.bundle_results_root— write root for PDS4 bundles produced bynav_create_bundle.
Each value may be a local path or a URL; filecache-aware consumers handle
both. Environment-variable overrides
(PDS3_HOLDINGS_DIR, NAV_RESULTS_ROOT, BACKPLANE_RESULTS_ROOT,
BUNDLE_RESULTS_ROOT) take precedence over the YAML defaults; CLI flags
take precedence over the env vars.
Static data: catalogues and citation discipline
The pipeline treats a small set of YAML files as static data: per-body shape parameters, per-ring radial uncertainties, and per-instrument photometric / noise constants. These tables substitute for cross-image statistical learning — no run depends on the result of any other run, but every run benefits from values that astronomers and instrument teams have already calibrated.
Static-data files
config_220_body_shape.yamlpopulatesconfig.body_shape— per-body radii, ellipsoid residuals, albedo, crater scale; consumed byshape_for_body()and from there by every bodyNavTechnique’s covariance and reliability formula. See Body Navigation Model.config_3N0_*_rings.yamlpopulateconfig.rings.<planet>.ring_features— per-ring-edge radii, eccentricities, RMS radial precision; consumed by the ring-edge extractor to derive per-edgesigma_radial. See Ring Navigation Model.config_4N0_inst_*.yamlpopulateconfig.<camera>— per-cameranoise,mag_offset,image_quality_thresholds, andsource_image_filterblocks; consumed by the orchestrator preflight, the star photometry helper, and the per-instrument PSF model.
Citation requirement
Every numeric value in config_220_body_shape.yaml and any new value added
to a config_4N0_inst_*.yaml noise: / mag_offset: block requires
an accurate, non-fabricated citation. The reasoning:
Navigation trust is downstream-safety-critical. An invented
ellipsoid_rms_residual_kmpropagates silently into every per-feature uncertainty estimate for that body for every image forever.The runtime has no cross-image cross-check that would catch a wrong value; the orchestrator trusts the static data and feeds it directly into reliability scores and technique covariances.
Schema
Each body block in config_220_body_shape.yaml is wrapped in a top-level
body_shape: mapping; each entry is keyed by upper-case SPICE body name and
carries an optional sibling _sources mapping. Keys beginning with _
are stripped at config-load time so the documentation does not bloat the
parsed Config — the citation lives in the file for human review only.
body_shape:
MIMAS:
radii_km: [207.4, 196.8, 190.6]
ellipsoid_rms_residual_km: 1.4
crater_scale_km: 3.0
albedo_mean: 0.96
albedo_variation: 0.05
shape_class_hint: regular
_sources:
radii_km: 'Thomas (2010), Icarus 208(1):395-401, Table 3, Mimas row.
doi:10.1016/j.icarus.2010.01.025'
ellipsoid_rms_residual_km: '...'
# ... and so on for every numeric field.
Anti-hallucination procedure
AI agents drafting body-shape entries:
Cite only documents fetched in-session. Every citation must be traceable to a
WebFetch/WebSearchlookup performed in the same session, or to anoops-package data file read directly. No citing from training-data memory.If a value cannot be sourced from a fetched document, leave it as
nulland write'PLACEHOLDER — no source found, calibration pending'as the_sourcesentry. The runtime fallback (10 % radius default plus a reliability cap of 0.3) handlesnullvalues.DOIs and paper titles must verify against a real
https://doi.org/<DOI>lookup; agents do not invent identifiers.Any draft PR that lists a citation an AI agent invented (caught in human review) is reverted in full and re-drafted by a different process.
Human review
Every PR touching config_220_body_shape.yaml requires a reviewer to
spot-check at least 5 randomly-selected citations by opening the cited
document and verifying the value appears at the cited location. PRs are
merged only after the reviewer marks the PR with the
cited-values-spot-checked label. To keep review tractable, an
initial-population PR is broken into ≤ 10 bodies per PR.
Validation tests
tests/nav/config_files/test_body_shape_citations.py enforces:
Every body declares a
_sourcesmapping.Every required numeric / list field on a body has a corresponding
_sourcesentry that is a non-empty string.No
_sourcesvalue contains the substringsTODO/FIXME/XXX(case-insensitive).PLACEHOLDERis allowed only when the value itself isnull.
The same validation pattern extends to per-camera noise /
mag_offset blocks in config_4N0_inst_*.yaml and to any new entries
added to config_3N0_*_rings.yaml. Existing ring-catalogue values are
grandfathered (they were curated by orbit-fitting astronomers and the
catalogues document their pedigree in the file header) — only new
additions need explicit _sources entries.
Strip-rule guarantee
Config._load_yaml strips every mapping key whose
name starts with _ before merging, so _sources blocks never appear in
the parsed Config object. The runtime accessors
(config.body_shape, config.<camera>.mag_offset, etc.) see only the
value-bearing fields. Tests assert this behaviour explicitly so the strip
rule cannot regress silently.
Adding a new tunable
When a new YAML knob is added:
Pick the file whose section it belongs to (e.g. a new
bodieskey goes inconfig_040_bodies.yaml). If no existing file fits, allocate a new numeric prefix per the layout table above.Add the key with a sensible default and a one-line YAML comment naming the consumer.
Document the key on the consumer’s dev-guide page (for example, Body Navigation Model lists every key under
bodies). The page lists name, type, default, units, and consumer.If the key represents static data (a measured constant rather than a knob), add the
_sourcesentry per the citation discipline above.Add or extend a unit test under
tests/nav/config_files/that asserts the loader exposes the key with the expected default.