Skip to content

mostlyright.core.schemas.satellite

Satellite schema (schema.satellite.v1) — Phase 25 (25-01 surface).

Two surfaces live here:

validate_satellite_station : The ICAO station-identity validation HOOK the GOES ABI L2 extractor (mostlyright.weather._fetchers._goes_extract) calls at the _build_record write-site (Phase 25 D2). ColumnSpec supports only dtype/nullable/enum — NO regex (verified core/schema.py) — so the ICAO ^[A-Z]{4}$ contract cannot live as a column pattern; it is enforced via this hook plus validate_icao_for_path at the cache-path layer.

SatelliteSchema : The full schema.satellite.v1 shape contract — the 18 ported 2i fields plus the SDK overlay columns source / delivery / qc_status / as_of_time. Registered with the Validator (core/schemas/__init__.py) and wired into the codegen exporter (scripts/export_schemas.py _GROUP_A_SCHEMA_IDS) so schemas/json/schema.satellite.v1.json is emitted deterministically (TS type emission is signature-forward only this phase — the TS reader is a deferred parity ticket).

D1 source identity (Phase 25 USER-LOCKED 2026-06-18; Phase 26 W1 H1 generalization). _registered_sources is the SET of the four distinct NATIVE-ring source identities {noaa_goes, jma_himawari, noaa_viirs, eumetsat_meteosat} — one per instrument family (a model trained on one MUST NOT silently reconcile against another). Within a single frame the source is homogeneous: the validator reconciles df.attrs["source"] against the SET, and the per-row source overlay column must equal that single df.attrs["source"] (no cross-source mixing). noaa_goes is byte-unchanged from Phase 25 (live self-extraction AND the future paid adapter share it). delivery (enum {live, hosted}, default "live") is INFORMATIONAL LINEAGE ONLY and is NOT part of source identity. mirror is a transport choice and is deliberately NOT a schema column (D9).

SATELLITE_DELIVERY_VALUESD2 informational lineage enum.
SATELLITE_QC_STATUS_VALUESqc_status values (D5 annotate-never-drop, severity-inverted).
validate_satellite_station(station)Validate a satellite row’s station identity is a 4-letter ICAO code.
SatelliteSchema()schema.satellite.v1 — single-pixel satellite scan rows (NATIVE ring).

mostlyright.core.schemas.satellite.SATELLITE_DELIVERY_VALUES : tuple[str, …] = (‘live’, ‘hosted’)

Section titled “mostlyright.core.schemas.satellite.SATELLITE_DELIVERY_VALUES : tuple[str, …] = (‘live’, ‘hosted’)”

D2 informational lineage enum. delivery records the delivery channel (free local self-extraction vs the future paid adapter) WITHOUT being part of source identity — both channels share the SAME per-source identity (e.g. GOES live + the future GOES paid adapter both reconcile to noaa_goes).

mostlyright.core.schemas.satellite.SATELLITE_QC_STATUS_VALUES : tuple[str, …] = (‘clean’, ‘flagged’, ‘suspect’)

Section titled “mostlyright.core.schemas.satellite.SATELLITE_QC_STATUS_VALUES : tuple[str, …] = (‘clean’, ‘flagged’, ‘suspect’)”

qc_status values (D5 annotate-never-drop, severity-inverted). "clean" passed every rule; "flagged" tripped a warning-class rule; "suspect" tripped an error-class rule (physics/structure violation — almost always an extraction bug, so the row is KEPT rather than dropped).

class mostlyright.core.schemas.satellite.SatelliteSchema

Section titled “class mostlyright.core.schemas.satellite.SatelliteSchema”

Bases: Schema

schema.satellite.v1 — single-pixel satellite scan rows (NATIVE ring).

One row per (station, satellite, product, variable, pressure_level_hpa, scan_start_utc) — the dedup key (mirror-invariant, D9). Ports the 18 2i storage fields and adds the SDK overlay columns source / delivery / qc_status / as_of_time.

Phase 26 W1 generalization (H1). Phase 25 was GOES-geostationary-shaped. The native ring (GOES E/W + Himawari + VIIRS + EUMETSAT) is covered by a SET of distinct source identities (_registered_sources) and a broadened satellite enum, and the row contract is generalized so a polar VIIRS SWATH row validates alongside a geostationary GOES/Himawari/SEVIRI row: sat_lon_used is now NULLABLE (geostationary-only) and pixel_row/ pixel_col mean “native grid index OR swath line/sample index”.

COLUMNS : ClassVar[list[ColumnSpec]] = [ColumnSpec(name=‘station’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘satellite’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘goes16’, ‘goes17’, ‘goes18’, ‘goes19’, ‘himawari8’, ‘himawari9’, ‘viirs-npp’, ‘viirs-n20’, ‘viirs-n21’, ‘meteosat-0deg’, ‘meteosat-iodc’), notes=”), ColumnSpec(name=‘product’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘variable’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘pressure_level_hpa’, dtype=‘float64’, units=‘hPa’, nullable=True, enum_values=None, notes=‘null for 2D products; populated (part of the dedup key) for 3D profiles’), ColumnSpec(name=‘scan_start_utc’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=“UTC scan/granule start time (event-time, D4); from the source’s filename start token (GOES/Himawari _s, VIIRS granule start, SEVIRI repeat-cycle start)”), ColumnSpec(name=‘scan_end_utc’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=“UTC scan/granule end time; >= scan_start_utc (the source’s filename end token; equal to start for a duration-less filename)”), ColumnSpec(name=‘pixel_value’, dtype=‘float64’, units=None, nullable=True, enum_values=None, notes=“raw-as-reported single grid cell; null ONLY on the file’s _FillValue”), ColumnSpec(name=‘pixel_dqf’, dtype=‘float64’, units=None, nullable=True, enum_values=None, notes=‘NOAA DQF integer at the cell; null for variables with no DQF’), ColumnSpec(name=‘pixel_row’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘native pixel row index at the station: geostationary fixed-grid row (y) for GOES/Himawari/SEVIRI, OR the SWATH line index for a VIIRS polar granule’), ColumnSpec(name=‘pixel_col’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘native pixel col index at the station: geostationary fixed-grid col (x) for GOES/Himawari/SEVIRI, OR the SWATH sample index for a VIIRS polar granule’), ColumnSpec(name=‘units’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘physical units from the NetCDF variable units attr’), ColumnSpec(name=‘station_lat’, dtype=‘float64’, units=‘degrees_north’, nullable=False, enum_values=None, notes=‘station latitude copied at ingest time (provenance)’), ColumnSpec(name=‘station_lon’, dtype=‘float64’, units=‘degrees_east’, nullable=False, enum_values=None, notes=‘station longitude copied at ingest time (provenance)’), ColumnSpec(name=‘sat_lon_used’, dtype=‘float64’, units=‘degrees_east’, nullable=True, enum_values=None, notes=‘sub-satellite longitude of the geostationary source (GOES goes_imager_projection / Himawari fixed-grid / SEVIRI sub-sat 0deg|45.5E); NULL for a VIIRS polar SWATH row, which has no single sub-satellite point’), ColumnSpec(name=‘source_object_key’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘full S3/GCS object key the row was extracted from (provenance)’), ColumnSpec(name=‘ingested_at’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘when the bytes were fetched; null for historical backfill’), ColumnSpec(name=‘source’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“per-row source-identity overlay == df.attrs[‘source’], one of {noaa_goes, jma_himawari, noaa_viirs, eumetsat_meteosat} (D1)”), ColumnSpec(name=‘delivery’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘live’, ‘hosted’), notes=‘delivery-channel lineage {live,hosted}; NOT source identity (D2)’), ColumnSpec(name=‘qc_status’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘clean’, ‘flagged’, ‘suspect’), notes=‘annotate-never-drop verdict (D5 severity-inverted)’), ColumnSpec(name=‘as_of_time’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘knowledge-time stamp; nullable (D4)’)]

Section titled “COLUMNS : ClassVar[list[ColumnSpec]] = [ColumnSpec(name=‘station’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘satellite’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘goes16’, ‘goes17’, ‘goes18’, ‘goes19’, ‘himawari8’, ‘himawari9’, ‘viirs-npp’, ‘viirs-n20’, ‘viirs-n21’, ‘meteosat-0deg’, ‘meteosat-iodc’), notes=”), ColumnSpec(name=‘product’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘variable’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=”), ColumnSpec(name=‘pressure_level_hpa’, dtype=‘float64’, units=‘hPa’, nullable=True, enum_values=None, notes=‘null for 2D products; populated (part of the dedup key) for 3D profiles’), ColumnSpec(name=‘scan_start_utc’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=“UTC scan/granule start time (event-time, D4); from the source’s filename start token (GOES/Himawari _s, VIIRS granule start, SEVIRI repeat-cycle start)”), ColumnSpec(name=‘scan_end_utc’, dtype=‘timestamp_utc’, units=None, nullable=False, enum_values=None, notes=“UTC scan/granule end time; >= scan_start_utc (the source’s filename end token; equal to start for a duration-less filename)”), ColumnSpec(name=‘pixel_value’, dtype=‘float64’, units=None, nullable=True, enum_values=None, notes=“raw-as-reported single grid cell; null ONLY on the file’s _FillValue”), ColumnSpec(name=‘pixel_dqf’, dtype=‘float64’, units=None, nullable=True, enum_values=None, notes=‘NOAA DQF integer at the cell; null for variables with no DQF’), ColumnSpec(name=‘pixel_row’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘native pixel row index at the station: geostationary fixed-grid row (y) for GOES/Himawari/SEVIRI, OR the SWATH line index for a VIIRS polar granule’), ColumnSpec(name=‘pixel_col’, dtype=‘int64’, units=None, nullable=False, enum_values=None, notes=‘native pixel col index at the station: geostationary fixed-grid col (x) for GOES/Himawari/SEVIRI, OR the SWATH sample index for a VIIRS polar granule’), ColumnSpec(name=‘units’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘physical units from the NetCDF variable units attr’), ColumnSpec(name=‘station_lat’, dtype=‘float64’, units=‘degrees_north’, nullable=False, enum_values=None, notes=‘station latitude copied at ingest time (provenance)’), ColumnSpec(name=‘station_lon’, dtype=‘float64’, units=‘degrees_east’, nullable=False, enum_values=None, notes=‘station longitude copied at ingest time (provenance)’), ColumnSpec(name=‘sat_lon_used’, dtype=‘float64’, units=‘degrees_east’, nullable=True, enum_values=None, notes=‘sub-satellite longitude of the geostationary source (GOES goes_imager_projection / Himawari fixed-grid / SEVIRI sub-sat 0deg|45.5E); NULL for a VIIRS polar SWATH row, which has no single sub-satellite point’), ColumnSpec(name=‘source_object_key’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=‘full S3/GCS object key the row was extracted from (provenance)’), ColumnSpec(name=‘ingested_at’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘when the bytes were fetched; null for historical backfill’), ColumnSpec(name=‘source’, dtype=‘string’, units=None, nullable=False, enum_values=None, notes=“per-row source-identity overlay == df.attrs[‘source’], one of {noaa_goes, jma_himawari, noaa_viirs, eumetsat_meteosat} (D1)”), ColumnSpec(name=‘delivery’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘live’, ‘hosted’), notes=‘delivery-channel lineage {live,hosted}; NOT source identity (D2)’), ColumnSpec(name=‘qc_status’, dtype=‘enum’, units=None, nullable=False, enum_values=(‘clean’, ‘flagged’, ‘suspect’), notes=‘annotate-never-drop verdict (D5 severity-inverted)’), ColumnSpec(name=‘as_of_time’, dtype=‘timestamp_utc’, units=None, nullable=True, enum_values=None, notes=‘knowledge-time stamp; nullable (D4)’)]”

mostlyright.core.schemas.satellite.validate_satellite_station(station)

Section titled “mostlyright.core.schemas.satellite.validate_satellite_station(station)”

Validate a satellite row’s station identity is a 4-letter ICAO code.

Returns the station string unchanged when valid (so call sites can use it inline). Raises SchemaValidationError for anything that is not exactly four uppercase ASCII letters — notably the 2i 3-letter NWS codes, which must fail loudly rather than silently produce un-joinable rows.

  • Return type: str
  • Parameters: station (str)