curryer.correction.config¶
Configuration models and enumerations for the geolocation correction pipeline.
This module defines the data structures that represent the complete configuration for a correction analysis run, including:
ParameterType– enum of the three parameter application strategiesParameterSpec– sampling specification for a single correction parameterParameterConfig– assembles a parameter’s type, kernel file, and sampling specGeolocationConfig– SPICE kernel paths and instrument settingsNetCDFParameterMetadata/NetCDFConfig– NetCDF output metadata (re-exported from io_config)GeolocationSetup– durable, mission-specific setup (built once, reused across sweeps)Sweep– the lightweight, frequently-varied parameter experimentOutputConfig– output settings (NetCDF metadata + filename)KernelContext,CalibrationData,ImageMatchingContext– lightweight NamedTuples used to pass state between pipeline helper functionsload_setup_from_json/load_sweep_from_json/load_config_files– build thesetup/sweep/outputmodels from a JSON file
All mission-specific values (kernel filenames, parameter ranges, instrument names)
live in mission configuration modules (e.g. tests/test_correction/clarreo_config.py)
and are injected via GeolocationSetup / Sweep.
All config objects are pydantic.BaseModel subclasses which provide:
- Automatic type validation and clear ValidationError messages on construction
- Free JSON serialization via model_dump_json() / model_validate_json()
- IDE autocomplete on every field
Parameter configuration — three cooperating classes¶
These three classes each capture a distinct, orthogonal concern:
ParameterType(enum)How the value is applied to the pipeline. Each member maps to a different pipeline code path:
CONSTANT_KERNEL— replace the kernel value with the sampled valueOFFSET_KERNEL— shift the existing kernel value by the sampled offsetOFFSET_TIME— shift the input timestamps by the sampled offset
ParameterTypebelongs onParameterConfig(not onParameterSpec) because it describes application mechanics, not sampling statistics.ParameterSpecHow to draw samples. Holds the statistical description of the search space: the nominal
current_value, theboundsthat clip samples, thesigmafor normal-distribution sampling, physicalunits, and optionalfield/coordinate_frameshints consumed by kernel-creation routines.ParameterSpecis intentionally agnostic about how any drawn value will be applied — that isParameterType’s job.ParameterConfigAssembles the three concerns. A single
ParameterConfiganswers: “vary this kernel file (config_file), applied as this kind of change (ptype), drawing samples according to this spec (spec).”ParameterConfigis also the right place for cross-field validation (e.g. confirming thatdata.fieldis provided wheneverptyperequires it).
Typical construction:
ParameterConfig(
ptype=ParameterType.OFFSET_TIME,
config_file=None, # time offsets need no kernel file
spec=ParameterSpec(
current_value=0.0,
bounds=[-50.0, 50.0],
sigma=10.0,
units="milliseconds",
field="time_ugps", # required for OFFSET_KERNEL / OFFSET_TIME
),
)
Attributes¶
Classes¶
Context for SPICE kernel loading during geolocation. |
|
Pre-loaded calibration data for image matching. |
|
Context data needed for image matching operations. |
|
Configuration for config-driven internal data loading. |
|
Parameter types used in the correction configuration. |
|
Strategy used to generate parameter sets during correction analysis. |
|
Typed sampling specification for a single correction parameter. |
|
A single parameter to vary during correction analysis. |
|
SPICE kernel paths and instrument settings for geolocation. |
|
Verification requirements / thresholds. |
|
Configuration for PSF sampling during image matching. |
|
Configuration for the image-matching correlation search grid. |
|
Configuration for GCP chip regridding. |
|
Direct paths to instrument calibration inputs. |
|
Durable, mission-specific setup for geolocation correction/verification. |
|
A parameter-variation experiment run against a |
|
Output settings for a correction run. |
|
A single input set for the correction loop. |
Functions¶
|
Load a |
|
Load a |
|
Load |
Module Contents¶
- curryer.correction.config.logger¶
- class curryer.correction.config.KernelContext¶
Bases:
NamedTupleContext for SPICE kernel loading during geolocation.
- mkrn: curryer.meta.MetaKernel¶
- dynamic_kernels: list[pathlib.Path]¶
- param_kernels: list[pathlib.Path]¶
- class curryer.correction.config.CalibrationData¶
Bases:
NamedTuplePre-loaded calibration data for image matching.
- los_vectors: numpy.ndarray | None¶
- optical_psfs: list | None¶
- class curryer.correction.config.ImageMatchingContext¶
Bases:
NamedTupleContext data needed for image matching operations.
- gcp_pairs: list[tuple]¶
- params: list[tuple]¶
- pair_idx: int¶
- sci_key: str¶
- class curryer.correction.config.DataConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelConfiguration for config-driven internal data loading.
Replaces mission-specific loader callables with a declarative specification of how files should be read. The pipeline reads telemetry and science data directly from the provided file paths using pandas/xarray, applying the
time_scale_factorto convert the science time column to uGPS.- file_format¶
File format for both telemetry and science data files.
"csv"usespandas.read_csv();"netcdf"converts viaxarray.open_dataset();"hdf5"usespandas.read_hdf().
- time_scale_factor¶
Multiply science timestamps by this factor to obtain uGPS (microseconds since GPS epoch). For example,
1e6converts GPS seconds to uGPS;1.0means the file already contains uGPS. The time column name is taken fromGeolocationConfig.time_field(single source of truth).
- position_columns¶
Explicit column name mappings for telemetry spacecraft-position data, e.g.
["sc_pos_x", "sc_pos_y", "sc_pos_z"].Nonemeans use mission defaults from the geolocation configuration.
- file_format: Literal['csv', 'netcdf', 'hdf5'] = 'csv'¶
- time_scale_factor: float = 1.0¶
- position_columns: list[str] | None = None¶
- class curryer.correction.config.ParameterType¶
Bases:
str,enum.EnumParameter types used in the correction configuration.
Specifies how a parameter is applied during geolocation analysis: whether as a constant kernel value, a kernel offset, or a time offset. String-valued so JSON configs use readable names (
"OFFSET_TIME").- CONSTANT_KERNEL¶
Set a specific kernel value (e.g., fixed rotation angles).
- OFFSET_KERNEL¶
Modify input kernel data by an offset.
- OFFSET_TIME¶
Modify input timetags by an offset.
- CONSTANT_KERNEL = 'CONSTANT_KERNEL'¶
- OFFSET_KERNEL = 'OFFSET_KERNEL'¶
- OFFSET_TIME = 'OFFSET_TIME'¶
- class curryer.correction.config.SearchStrategy¶
Bases:
str,enum.EnumStrategy used to generate parameter sets during correction analysis.
- RANDOM¶
Monte Carlo random walk (current default). Each iteration draws an independent sample from a normal distribution centered on the parameter’s
current_valuewith the specifiedsigma, clipped tobounds. Requiresseedandn_iterationsonSweep.
- GRID_SEARCH¶
Deterministic cartesian-product sweep. For every parameter,
grid_points_per_paramevenly-spaced values are generated across the fullboundsoffset range and the cartesian product of all per-parameter grids is enumerated.n_iterationsis ignored.
- SINGLE_OFFSET¶
Deterministic single-parameter sweep. Each parameter is varied independently across
n_iterationsevenly-spaced values (spanning itsboundsoffset range) while all other parameters are held at their nominalcurrent_value. Total parameter sets produced:len(parameters) × n_iterations.
- RANDOM = 'random'¶
- GRID_SEARCH = 'grid'¶
- SINGLE_OFFSET = 'single'¶
- class curryer.correction.config.ParameterSpec(/, **data: Any)¶
Bases:
pydantic.BaseModelTyped sampling specification for a single correction parameter.
Strict by design (
extra="forbid"): unknown fields raise aValidationErrorso typos surface immediately. Mission-specific extras that the pipeline does not interpret go inmetadata.- current_value¶
Baseline parameter value(s). A scalar for OFFSET_KERNEL/OFFSET_TIME and a 3-element list
[roll, pitch, yaw]for CONSTANT_KERNEL.
- bounds¶
[min, max]offset limits (same units assigma).
- sigma¶
Standard deviation for normal-distribution sampling.
Nonemeans the parameter is held fixed atcurrent_value.
- units¶
Physical units string, e.g.
"arcseconds"or"milliseconds".
- distribution¶
Sampling distribution name. Stored for documentation purposes; the current implementation always uses a normal distribution.
- field¶
Telemetry / science DataFrame column that this parameter modifies (required for
OFFSET_KERNELandOFFSET_TIME).
- transformation_type¶
Optional hint consumed by kernel-creation routines (e.g.
"dcm_rotation"or"angle_bias").
- coordinate_frames¶
Optional list of SPICE frame names affected by this parameter.
- metadata¶
Free-form mission-specific extras not interpreted by the pipeline (e.g. a display
"name", provenance, calibration date).
- model_config¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- current_value: float | list[float] = 0.0¶
- bounds: list[float] = None¶
- sigma: float | None = None¶
- units: str | None = None¶
- distribution: str = 'normal'¶
- field: str | None = None¶
- transformation_type: str | None = None¶
- coordinate_frames: list[str] | None = None¶
- metadata: dict[str, Any] = None¶
- class curryer.correction.config.ParameterConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelA single parameter to vary during correction analysis.
- ptype¶
How this parameter is applied (constant kernel, offset kernel, or time offset).
- config_file¶
Path to the SPICE kernel JSON template, or
Nonefor time offsets that require no kernel file.
- spec¶
Sampling specification. Accepts a plain
dictorNoneon construction (Pydantic coerces both toParameterSpecautomatically;Nonebecomes an emptyParameterSpec()).
- ptype: ParameterType¶
- config_file: pathlib.Path | None = None¶
- spec: ParameterSpec = None¶
- class curryer.correction.config.GeolocationConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelSPICE kernel paths and instrument settings for geolocation.
- meta_kernel_file¶
Path to the mission meta-kernel JSON file.
- generic_kernel_dir¶
Directory containing generic/shared SPICE kernels.
- dynamic_kernels¶
Kernels regenerated from telemetry each run (SC-SPK, SC-CK, etc.) but not altered by parameter variations.
- instrument_name¶
SPICE instrument name (e.g.
"CPRS_HYSICS").
- time_field¶
Column name in the science DataFrame that holds uGPS timestamps.
- minimum_correlation¶
Optional image-matching quality filter threshold (0.0–1.0).
- meta_kernel_file: pathlib.Path¶
- generic_kernel_dir: pathlib.Path¶
- dynamic_kernels: list[pathlib.Path] = None¶
- instrument_name: str¶
- time_field: str¶
- minimum_correlation: float | None = None¶
- class curryer.correction.config.RequirementsConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelVerification requirements / thresholds.
Held as the required
requirementsfield onGeolocationSetupand consumed byverify()and the correction verdict.- performance_threshold_m¶
Per-measurement nadir-equivalent error limit in meters (must be > 0). A measurement passes when its error is below this value.
- Type:
float
- performance_spec_percent¶
Minimum fraction of measurements (0–100) that must pass for the overall verification to be considered successful.
- Type:
float
- performance_threshold_m: float = None¶
- performance_spec_percent: float = None¶
- class curryer.correction.config.PSFSamplingConfig¶
Configuration for PSF sampling during image matching.
Default values are calibrated for Landsat 30 m GCPs, which are the standard reference for GCP-based geolocation verification. Override all fields for instruments with different ground resolution or motion characteristics.
- Parameters:
gcp_step_m (float, optional) – Ground control point step size in meters. Default is 30.0.
motion_convolution_step_m (float or None, optional) – Step size for spacecraft motion convolution in meters. If
None(default), derived asgcp_step_m / 20.0in__post_init__.psf_lat_sample_dist_deg (float, optional) – PSF sample distance in the latitude direction in degrees. Default approximately 2.7 m at the equator (Landsat calibration).
psf_lon_sample_dist_deg (float, optional) – PSF sample distance in the longitude direction in degrees. Default approximately 2.7 m at the equator (Landsat calibration).
- gcp_step_m: float = 30.0¶
- motion_convolution_step_m: float | None = None¶
- psf_lat_sample_dist_deg: float = 2.4397105613972e-05¶
- psf_lon_sample_dist_deg: float = 2.8737038710207e-05¶
- class curryer.correction.config.SearchConfig¶
Configuration for the image-matching correlation search grid.
Default values are tuned for Landsat 30 m GCPs. Override all fields for instruments with different ground resolution.
- Parameters:
grid_size (int, optional) – Number of grid points per axis in the correlation search grid. Default 44 (Landsat-tuned).
grid_span_km (float, optional) – Half-width of the search grid in kilometers. Default 11.0.
reduction_factor (float, optional) – Multiplicative reduction applied to grid spacing each iteration. Default 0.8.
spacing_limit_m (float, optional) – Minimum grid spacing in meters; search stops when reached. Default 10.0 (Landsat-tuned).
- grid_size: int = 44¶
- grid_span_km: float = 11.0¶
- reduction_factor: float = 0.8¶
- spacing_limit_m: float = 10.0¶
- class curryer.correction.config.RegridConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelConfiguration for GCP chip regridding.
Specifies output grid parameters for transforming irregular geodetic grids to regular latitude/longitude grids. ECEF → geodetic conversion always uses the WGS84 ellipsoid, which is the only ellipsoid supported by
curryer.compute.spatial.ecef_to_geodetic.- Parameters:
output_grid_size (tuple[int, int], optional) – Desired output grid dimensions as (nrows, ncols). Mutually exclusive with
output_resolution_deg.output_resolution_deg (tuple[float, float], optional) – Desired output resolution as (dlat, dlon) in degrees. Mutually exclusive with
output_grid_size. Required whenoutput_boundsis set.output_bounds (tuple[float, float, float, float], optional) – Explicit output grid bounds as (minlon, maxlon, minlat, maxlat) in degrees. Requires
output_resolution_deg.conservative_bounds (bool, default=True) – If True, shrink bounds to ensure all output points lie within the input irregular grid (avoids edge extrapolation).
interpolation_method (str, default="bilinear") – Interpolation method; one of
"bilinear"or"nearest".fill_value (float, default=NaN) – Value assigned to output points that fall outside the input grid.
- output_grid_size: tuple[int, int] | None = None¶
- output_resolution_deg: tuple[float, float] | None = None¶
- output_bounds: tuple[float, float, float, float] | None = None¶
- conservative_bounds: bool = True¶
- interpolation_method: str = 'bilinear'¶
- fill_value: float¶
- classmethod validate_method(v: str) str¶
Validate interpolation method name.
- classmethod validate_grid_size(v: tuple[int, int] | None) tuple[int, int] | None¶
Validate that grid size has at least 2 rows and 2 columns.
- classmethod validate_resolution(v: tuple[float, float] | None) tuple[float, float] | None¶
Validate that resolution values are positive.
- classmethod validate_bounds(v: tuple[float, float, float, float] | None) tuple[float, float, float, float] | None¶
Validate that bounds are properly ordered.
- validate_grid_spec() RegridConfig¶
Validate that grid specification options are mutually consistent.
- class curryer.correction.config.CalibrationFiles(/, **data: Any)¶
Bases:
pydantic.BaseModelDirect paths to instrument calibration inputs.
Both fields are optional and interim: real line-of-sight vectors and spacecraft geometry will be SPICE-derived from telemetry rather than loaded from files, so nothing in the pipeline requires these.
- los_vectors_file¶
Per-detector line-of-sight unit vectors (instrument frame).
- psf_file¶
Optical point-spread-function calibration.
- los_vectors_file: pathlib.Path | None = None¶
- psf_file: pathlib.Path | None = None¶
- class curryer.correction.config.GeolocationSetup(/, **data: Any)¶
Bases:
pydantic.BaseModelDurable, mission-specific setup for geolocation correction/verification.
Built once per mission and reused across many
Sweepruns. Holds everything that does not change when you vary which parameters are swept: SPICE kernels and instrument identity (GeolocationConfig), the pass/failRequirementsConfig, how input data is read (DataConfig), static instrument calibration (CalibrationFiles), the science-Dataset variable names, and an optional custom image-matching implementation.- geo¶
SPICE kernels, instrument name, and science time field.
- requirements¶
Pass/fail thresholds used by verification and the correction verdict.
- data_config¶
How telemetry/science files are read.
Noneuses CSV defaults.
- calibration¶
Optional direct calibration file paths.
Nonewhen geometry is supplied another way (e.g. SPICE-derived).
- spacecraft_position_name, boresight_name, transformation_matrix_name
Variable names for the spacecraft-state fields in the image-matching
xr.Dataset(mission-configurable; generic defaults).
- image_matching_func¶
Optional custom image-matching callable.
Noneuses the built-inimage_matching(). Excluded from JSON serialisation because callables are not serialisable.
- model_config¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- geo: GeolocationConfig¶
- requirements: RequirementsConfig¶
- data_config: DataConfig | None = None¶
- calibration: CalibrationFiles | None = None¶
- spacecraft_position_name: str = 'sc_position'¶
- boresight_name: str = 'boresight'¶
- transformation_matrix_name: str = 't_inst2ref'¶
- image_matching_func: collections.abc.Callable | None = None¶
- class curryer.correction.config.Sweep(/, **data: Any)¶
Bases:
pydantic.BaseModelA parameter-variation experiment run against a
GeolocationSetup.Lightweight and cheap to copy, so a setup can be held fixed while rapidly trying parameter variations.
- parameters¶
The parameters to vary (at least one).
- search_strategy¶
How parameter sets are generated (RANDOM / GRID_SEARCH / SINGLE_OFFSET).
- n_iterations¶
Iterations for RANDOM and values-per-parameter for SINGLE_OFFSET; ignored by GRID_SEARCH.
- seed¶
Random seed for reproducible RANDOM sweeps.
- grid_points_per_param¶
Evenly-spaced points per parameter for GRID_SEARCH.
- max_grid_sets¶
Safety cap on total GRID_SEARCH parameter sets.
- parameters: list[ParameterConfig] = None¶
- search_strategy: SearchStrategy¶
- n_iterations: int = None¶
- seed: int | None = None¶
- grid_points_per_param: int = None¶
- max_grid_sets: int = None¶
- with_strategy(strategy: SearchStrategy | str, **sweep_changes: Any) Sweep¶
Return a copy of this sweep using a different search strategy.
Additional sweep-level fields (
n_iterations,seed,grid_points_per_param,max_grid_sets) may be overridden via keyword arguments. The result is re-validated, so typos and strategy-inconsistent settings fail eagerly.Examples
>>> grid = sweep.with_strategy("grid", grid_points_per_param=5) >>> repro = sweep.with_strategy(SearchStrategy.RANDOM, seed=7, n_iterations=200)
- update_param(selector: int | str, **spec_changes: Any) Sweep¶
Return a copy of this sweep with one parameter’s
ParameterSpecchanged.selector is either an integer index into
parameters, or a string matched against each parameter’sspec.fieldor itsconfig_filestem. The changed spec is re-validated againstParameterSpec(which isextra="forbid"), so out-of-spec values or unknown field names raise immediately rather than being silently swallowed.Examples
>>> wider = sweep.update_param("hps.az_ang_nonlin", bounds=[-100.0, 100.0]) >>> tighter = sweep.update_param(0, sigma=5.0)
- class curryer.correction.config.OutputConfig(/, **data: Any)¶
Bases:
pydantic.BaseModelOutput settings for a correction run.
- netcdf¶
NetCDF structure/metadata config.
Noneis auto-populated byrun_correction()from the setup’s performance threshold.
- output_filename¶
Output NetCDF filename.
Nonefalls back to the default inget_output_filename().
- netcdf: curryer.correction.io_config.NetCDFConfig | None = None¶
- output_filename: str | None = None¶
- get_output_filename(default: str = 'correction_results.nc') str¶
Return
output_filenameif set, otherwise default.
- class curryer.correction.config.CorrectionInput(/, **data: Any)¶
Bases:
pydantic.BaseModelA single input set for the correction loop.
Replaces the positional tuple
(telemetry_path, science_path, gcp_path)with named fields for clarity and IDE autocomplete.The reader for each file is chosen by
DataConfig.file_format, so the inputs are format-agnostic. The first-class real-data path is a NetCDF image observation (radiance as the science variable) carrying telemetry, metadata, and science times;.matfiles are interim test scaffolding.- Parameters:
telemetry_file (Path) – Telemetry observation file (NetCDF for real data; CSV/HDF5 also read).
science_file (Path) – Science/timing observation file (NetCDF for real data; CSV/HDF5 also read).
gcp_file (Path) – GCP reference-image file (NetCDF or
.mat).
Examples
>>> from curryer.correction import CorrectionInput >>> inputs = [ ... CorrectionInput( ... telemetry_file="data/obs_20240317.nc", ... science_file="data/obs_20240317.nc", ... gcp_file="gcps/landsat_chip_001.nc", ... ) ... ]
- telemetry_file: pathlib.Path¶
- science_file: pathlib.Path¶
- gcp_file: pathlib.Path¶
- curryer.correction.config.load_setup_from_json(config_path: pathlib.Path) GeolocationSetup¶
Load a
GeolocationSetupfrom the"setup"section of a JSON file.
- curryer.correction.config.load_sweep_from_json(config_path: pathlib.Path) Sweep¶
Load a
Sweepfrom the"sweep"section of a JSON file.
- curryer.correction.config.load_config_files(config_path: pathlib.Path) tuple[GeolocationSetup, Sweep, OutputConfig]¶
Load
(GeolocationSetup, Sweep, OutputConfig)from one JSON file.The file has three top-level sections —
"setup","sweep", and an optional"output"— each validated directly against its model. The"sweep".parametersentries mirrorParameterConfig(ptype/config_file/spec); rotation frames are authored as a singleCONSTANT_KERNELparameter withspec.current_value = [roll, pitch, yaw].