mostlyright.weather
mostlyright.weather
Section titled “mostlyright.weather”mostlyright.weather — direct public-API access for AWC, IEM, GHCNh, NWS CLI.
Local-first; no hosted backend; no API keys. Parsers are byte-faithful lifts
from monorepo-v0.14.1; HTTP fetchers and the parquet cache are net-new
Sprint 0 code so the SDK can run without the v0.14.1 ingest service.
Lift inventory (provenance for parity-critical code). Source SHA refers to
the v0.14.1 release tag of Tarabcak/monorepo (commit
514fcdab227e845145ca32b989355647466231d9).
Module | Source path | Source SHA | Lift date | Modifications |
|-------------------------|——————————————————–
|------------|————
|---------------------------------------------------------------------|| _awc.py | monorepo-v0.14.1/src/mostlyright/weather/_awc.py | 514fcda | 2026-05-21 | namespace rename only (imports point at mostlyright._internal) |
| _iem.py | monorepo-v0.14.1/src/mostlyright/weather/_iem.py | 514fcda | 2026-05-21 | namespace rename only |
| _climate.py | monorepo-v0.14.1/src/mostlyright/weather/climate.py | 514fcda | 2026-05-21 | namespace rename only |
| _ghcnh.py | monorepo-v0.14.1/src/mostlyright/weather/ghcnh.py | 514fcda | 2026-05-21 | namespace rename only |
| _fetchers/_init_.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — fetcher package marker |
| _fetchers/awc.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — historical AWC range fetcher |
| _fetchers/iem_asos.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — monthly-chunked IEM ASOS METAR fetcher |
| _fetchers/iem_cli.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — IEM CLI settlement-grade fetcher |
| _fetchers/ghcnh.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — per-year NCEI GHCNh PSV fetcher |
| cache.py | n/a (NEW) | n/a | 2026-05-21 | NEW (Sprint 0 Wave 1 Lane F) — local parquet cache, filelock-guarded |
_bounds is imported from mostlyright._internal (lifted there from
monorepo-v0.14.1/src/mostlyright/_bounds.py) — see the parallel lift
inventory in mostlyright._internal.__init__.
Public surface kept stable for Vojtech’s existing mostlyright==0.14.1
workflow: raw_metar is preserved on observation rows so MetPy re-parse
keeps working without preprocessing in v0.1.0.
mostlyright.weather.climate(station, start, end, , source=None, backend=‘pandas’, return_type=‘dataframe’)
Section titled “mostlyright.weather.climate(station, start, end, , source=None, backend=‘pandas’, return_type=‘dataframe’)”Return NWS CLI daily settlement labels for station over [start, end].
The settlement source for Kalshi NHIGH/NLOW markets: the official NWS CLI
daily high/low, merged via the frozen dedup policy (highest
report_type_priority with STRICT > — overnight final wins).
- Parameters:
- station (str) – ICAO code (e.g.
"KNYC") or 3-letter NWS code. - start (str) – ISO date strings (YYYY-MM-DD), inclusive bounds.
- end (str) – ISO date strings (YYYY-MM-DD), inclusive bounds.
- source ( {None , “iem” , “cli” , “cli.archive”} , keyword-only , default None) – Provenance selector. A degenerate single-authority axis (D-08): IEM
CLI is the sole live provider, so every accepted value resolves to the
same fetch.
Nonemeans best-available (=="iem")."acis"raisesValueError— there is no ACIS leg in this code path. - backend ( {“pandas” , “polars”} , keyword-only , default “pandas”) – Output frame type.
"polars"requiresreturn_type="wrapper"(polars frames carry nodf.attrsfor provenance). - return_type ( {“dataframe” , “wrapper” , “list”} , keyword-only , default “dataframe”) –
"dataframe"(default): apandas.DataFramewith provenance ondf.attrs."list": a plainlist[dict]of rows."wrapper": aMostlyRightResult.
- station (str) – ICAO code (e.g.
- Returns:
One row per CLI settlement day with the public column contract:
date, station, cli_high_f, cli_low_f, cli_report_typeplus provenancesource(per-row endpoint tag"iem") andissued_at. Frame identitydf.attrs["source"] == "cli.archive". - Return type: pd.DataFrame | list[dict]
- Raises:
ValueError – If
sourceis not in{None, "iem", "cli", "cli.archive"}, ifstart/endare not ISO dates, or if thebackend/return_typepair is incoherent (e.g.backend="polars", return_type="dataframe").
- CLI is a daily batch product —
climate()has NO grain axis and NO live surface (D-09/D-10 class 1: re-fetchable upstream). - This wraps the LOCAL CLI fetcher only; it makes NO hosted call.
Examples
Section titled “Examples”>>> from mostlyright.weather import climate>>> df = climate("KNYC", "2026-01-01", "2026-01-03")>>> df.attrs["source"]'cli.archive'mostlyright.weather.fetch_open_meteo(station, from_date, to_date, , model, mode=‘training’, issued_at=None, allow_leakage=False, variables=None, client=None, timeout=60.0)
Section titled “mostlyright.weather.fetch_open_meteo(station, from_date, to_date, , model, mode=‘training’, issued_at=None, allow_leakage=False, variables=None, client=None, timeout=60.0)”Fetch Open-Meteo forecasts for one station + one model.
- Parameters:
- station (
str) – ICAO code (e.g."KNYC") or 3-letter US NWS code. - from_date (
str) – ISOYYYY-MM-DDinclusive lower bound onvalid_at. - to_date (
str) – ISOYYYY-MM-DDinclusive upper bound onvalid_at. - model (
str) – One ofOPEN_METEO_MODELS(36 keys). - mode (
Literal['training','seamless','live']) –"training"(default) |"seamless"|"live". - issued_at (
str|None) – ISO datetime (e.g."2024-06-01T12:00") for Single Runs API. Whenmode='training'andissued_atis provided, the fetcher uses Single Runs API for byte-exact cycle provenance. - allow_leakage (
bool) – RequiredTruewhenmode='seamless'; raisesOpenMeteoSeamlessLeakageErrorotherwise. - variables (
tuple[str,...] |None) – Subset of_OM_VARIABLES_TO_FETCHto request.None(default) requests all 18. Unknown names raiseValueErrorbefore any HTTP request. - client (
Client|None) – Optionalhttpx.Client(test-injection seam). - timeout (
float) – Per-request timeout in seconds.
- station (
- Return type:
DataFrame - Returns:
DataFrame matching
schema.forecast.station.v1. Empty DataFrame (with canonical columns + dtypes) on 404 or empty response. - Raises:
- ValueError – unknown model, unknown mode, unknown station, or unknown variable name (checked before any HTTP request).
- OpenMeteoSeamlessLeakageError –
mode='seamless'withoutallow_leakage=True. Raised BEFORE any HTTP request. - NotImplementedError –
mode='live'(deferred to PLAN-05).
mostlyright.weather.obs(station, start, end, , source=None, strategy=‘auto’, granularity=‘daily’, as_dataframe=None, backend=‘pandas’, return_type=‘dataframe’, tz_override=None)
Section titled “mostlyright.weather.obs(station, start, end, , source=None, strategy=‘auto’, granularity=‘daily’, as_dataframe=None, backend=‘pandas’, return_type=‘dataframe’, tz_override=None)”Return observation data for station over [start, end].
Returns default fused-source aggregates merged via SOURCE_PRIORITY
(AWC > IEM > GHCNh). granularity chooses the row level.
- Parameters:
-
station (str) – ICAO code (e.g.
"KNYC") or 3-letter NWS code. -
start (str) – ISO date strings (YYYY-MM-DD), inclusive bounds.
-
end (str) – ISO date strings (YYYY-MM-DD), inclusive bounds.
-
source ( {“iem” , “ghcnh” , “awc”} | None , keyword-only) – If set, only that source is queried; the other two fetchers are skipped. If None, all three are queried and merged with the standard priority (AWC > IEM > GHCNh).
-
granularity ( {“daily” , “observation”} , keyword-only , default “daily”) –
Row level of the result.
-
"daily"(default): one row per LST settlement day — the obs_* aggregate subset (obs_high_f, obs_low_f, obs_mean_f, …). Behaviour is byte-unchanged from prior releases. -
"observation": the merged per-report rows (native METAR/SPECI + sub-hourly cadence), trimmed to the queried UTC window, pass-through withobservation_typeandraw_metarpreserved — NO bucketing/resampling. Each row’ssourcecolumn is the truthful bare parser tag (awc/iem/ghcnh); the FRAME identity (df.attrs["source"]) is"merged.live_v1"when unpinned, or the bare source whensource=is pinned. Fixed-cadence resampling (exact-hourly, 30-min, …) is a separate preprocessing transform, not agranularityvalue.Each observation-grain row also carries a
settlement_datecolumn (D-19) — the ISOYYYY-MM-DDof the LST settlement day the report belongs to (via the snapshot settlement machinery, never a raw UTC-day slice). This is the ergonomic key for grouping/joining reports by their settlement day (and the internal join keydataset(granularity="observation")uses).
-
-
strategy ( {“auto” , “exact_window” , “warm_cache” , “hosted”} , keyword-only) – Advanced/documented escape hatch — ordinary users never type it.
"auto"(the default) self-selects the right tactic, including the source-isolatedexact_windowpath for any pinnedsource=query. The default ships as"auto"and never churns between releases. -
as_dataframe (bool | None , keyword-only , default None) – DEPRECATED (Phase 30 D-06) — use
return_typeinstead (True→"dataframe",False→"list"). Passing it explicitly emits aDeprecationWarning; when both are supplied an explicitreturn_typewins. Left unset (default),return_typegoverns and a no-arg call still returns apandas.DataFrame. -
backend ( {“pandas” , “polars”} , keyword-only , default “pandas”) – Output frame backend.
"polars"requiresreturn_type="wrapper"(polars frames carry nodf.attrsprovenance). Validated via the sharedvalidate_backend_kwargsgate. -
return_type ( {“dataframe” , “list” , “wrapper”} , keyword-only , default “dataframe”) – Output shape: raw
pandas.DataFrame(default), plainlist[dict]of rows, or aMostlyRightResultwrapper carrying provenance. -
tz_override (str | None , keyword-only , default None) – IANA timezone name override for stations outside the built-in registry. Threaded to the settlement-date machinery (
mostlyright.snapshot.settlement_date_for()) used for daily bucketing and for thesettlement_datecolumn atgranularity="observation". Rarely needed for the US registry.
-
- Returns:
Daily obs_* aggregate rows (
granularity="daily") or merged per-report rows (granularity="observation"). Shape followsreturn_type. - Return type: pd.DataFrame | list[dict]
- Raises:
- ValueError – If
source,strategy, orgranularityis not in its allowed Literal set, OR ifstrategy="warm_cache"is called withsource != None(post-merge filtering would corrupt SOURCE_PRIORITY semantics; usestrategy="exact_window"for single-source queries). - DataAvailabilityError – If
strategy="hosted"(the precomputed-API seam deferred to v0.2.x).
- ValueError – If
obs()does NOT return CLI climate columns (cli_high_f, cli_low_f, fcst_*). If you need joined obs + CLI + forecast, useresearch()directly.- The
"auto"router’swarm_cachetactic produces daily aggregates byte-equivalent toresearch()for obs_high_f, obs_low_f, obs_high_at, obs_low_at, source (verified against the 5 Phase 1 parity fixtures intests/weather/test_obs_warm_cache_parity.py). Theexact_windowtactic matches those values at the row level but intentionally bypasses year-aligned caching, so its cache footprint and fetch URLs differ.
Examples
Section titled “Examples”>>> from mostlyright.weather import obs>>> df = obs("KNYC", "2024-03-01", "2024-03-31", source="iem")>>> hourly = obs("KNYC", "2024-03-01", "2024-03-31",... granularity="observation")mostlyright.weather.satellite(station, satellite=None, product=None, , variable=None, start, end, qc=‘clean’, as_of=None, mirror=‘aws’, delivery=‘live’, cache=True, max_workers=8, backend=‘pandas’, return_type=‘dataframe’)
Section titled “mostlyright.weather.satellite(station, satellite=None, product=None, , variable=None, start, end, qc=‘clean’, as_of=None, mirror=‘aws’, delivery=‘live’, cache=True, max_workers=8, backend=‘pandas’, return_type=‘dataframe’)”Fetch native-L2 satellite single-pixel values for one or more stations.
- Parameters:
- station (
str|list[str]) – Single ICAO/NWS code or a list. Unknown codes are skipped with a logged warning (partial list -> partial DataFrame). - satellite (
str|None) – A native-ring satellite id, orNone(the default) to auto-route by the station’s coverage region (Wave 5) — GOES for the Americas/Pacific, Himawari for Asia-Pacific, Meteosat for Europe/Africa/Indian-Ocean (landed Wave 6; needs a Data-Store key only for the live fetch), and VIIRS for the poles and any band no landed geostationary source covers. Explicit values: GOES (allnoaa_goes):"goes16"/"goes19"(GOES-East, CONUS) and"goes18"(operational GOES-West) /"goes17"(GOES-West archive) — West “C” covers PACUS (Pacific incl. Hawaii). Himawari (jma_himawari):"himawari8"/"himawari9". VIIRS (noaa_viirs):"viirs-npp"/"viirs-n20"/"viirs-n21". Meteosat (eumetsat_meteosat, KEYED):"meteosat-0deg"/"meteosat-iodc". When auto-routing, a single(source, satellite, product)triple is picked from the FIRST resolved station and applied to the whole call (MODEST routing). Cross-region caveat: auto-routing a station list that SPANS regions (e.g.["KNYC", "RJTT"]) fetches every station on the first station’s source, so stations outside that footprint silently return no rows (off-disk -> dropped; leakage-safe but a partial frame). A WARNING is logged naming the divergent stations; prefer per-region calls or an explicitsatellite=for mixed lists. - product (
str|None) – Product id, orNone(the default) to use the resolved source’s cheap default product (GOES"ABI-L2-ACMC", Himawari"AHI-L2-FLDK-Clouds", VIIRS"VIIRS-JRR-CloudMask", Meteosat"MSG-CLM")."ABI-L2-DSRF"emits a one-time gating warning (D6) on the live path. - variable (
str|None) – Optional single-variable filter;Nonekeeps every registered variable ofproduct. - start (
datetime) – Event-time window start (UTC, tz-aware recommended). - end (
datetime) – Event-time window end.end < startraisesValueError. - qc (
str) – Reserved qc-filter knob (annotate-never-drop — no row is dropped). - as_of (
Any) – Knowledge-time cutoff.TimePoint | datetime | None. Filters in-process on typed datetimes viaKnowledgeView; a naive datetime is rejected loudly (NOT a lexical string snapshot, D4). - mirror (
str) –"aws"(default) or"gcp"— the D9 TRANSPORT selector. Validated with a loudValueErrorBEFORE any I/O. Mirror is transport-only: the source identity stays"noaa_goes"and there is NOmirrorrow column. - delivery (
str) –"live"(default) self-parses public data directly and makes NO hosted call;"hosted"(28-31) fetches the deployed weather serving endpoint${WEATHER_HOSTED_URL}/satellitewith theMOSTLYRIGHT_API_KEYheader and returns rows byte-identical todelivery="live"(D-28.2 —deliveryis informational lineage, not source identity). Hosted is OPT-IN via the two env seams; the default live path never touches it. - cache (
bool) – Reserved cache toggle (per-partition parquet tier, 25-03). - max_workers (
int) – Reserved thread fan-out width (documented UNTUNED, D10). - backend (
str) –"pandas"(default) or"polars". - return_type (
str) –"dataframe"(default) or"result".
- station (
- Return type:
DataFrame - Returns:
pd.DataFramecarrying the satellite rows plus the leakage overlay columns (source/event_time/knowledge_time/retrieved_at/delivery) andqc_status, withdf.attrs["source"]set to the resolved per-source identity (noaa_goesfor GOES, and the other native-ring sources forward as their adapters land). - Raises:
- ValueError –
satellite/product/mirror/deliverynot in their enums (orproductnot registered forsatellite’s source), orend < start, or a naiveas_ofdatetime. - SourceUnavailableError – the
[satellite]optional extra is absent.
- ValueError –
Modules
Section titled “Modules”cache | Local parquet cache for mostlyright weather observations and climate. |
|---|---|
catalog | Weather catalog: adapter registry + WeatherAdapter Protocol. |
climate(station, start, end, *[, source, …]) | Return NWS CLI daily settlement labels for station over [start, end]. |
cwop | mostlyright.weather.cwop — standalone CWOP (Citizen Weather Observer Program) live adapter. |
earnings | Earnings-audio Tier-2 ENGINE module (Phase 27, 27-03). |
forecast_nwp | Public NWP-forecast surface (Phase 3.2 — live HRRR/GFS/NBM). |
obs(station, start, end, *[, source, …]) | Return observation data for station over [start, end]. |
qc | Weather QC rules + per-model NWP physics-bounds registry (Phase 17 PLAN-10). |
qc_sidecar | Phase 3.4 — observation QC sidecar writer. |
satellite(station[, satellite, product, …]) | Fetch native-L2 satellite single-pixel values for one or more stations. |