Skip to content

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. None means best-available (== "iem"). "acis" raises ValueError — there is no ACIS leg in this code path.
    • backend ( {“pandas” , “polars”} , keyword-only , default “pandas”) – Output frame type. "polars" requires return_type="wrapper" (polars frames carry no df.attrs for provenance).
    • return_type ( {“dataframe” , “wrapper” , “list”} , keyword-only , default “dataframe”) –
      • "dataframe" (default): a pandas.DataFrame with provenance on df.attrs.
      • "list": a plain list[dict] of rows.
      • "wrapper": a MostlyRightResult.
  • Returns: One row per CLI settlement day with the public column contract: date, station, cli_high_f, cli_low_f, cli_report_type plus provenance source (per-row endpoint tag "iem") and issued_at. Frame identity df.attrs["source"] == "cli.archive".
  • Return type: pd.DataFrame | list[dict]
  • Raises: ValueError – If source is not in {None, "iem", "cli", "cli.archive"}, if start/end are not ISO dates, or if the backend/return_type pair 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.
>>> 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) – ISO YYYY-MM-DD inclusive lower bound on valid_at.
    • to_date (str) – ISO YYYY-MM-DD inclusive upper bound on valid_at.
    • model (str) – One of OPEN_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. When mode='training' and issued_at is provided, the fetcher uses Single Runs API for byte-exact cycle provenance.
    • allow_leakage (bool) – Required True when mode='seamless'; raises OpenMeteoSeamlessLeakageError otherwise.
    • variables (tuple[str, ...] | None) – Subset of _OM_VARIABLES_TO_FETCH to request. None (default) requests all 18. Unknown names raise ValueError before any HTTP request.
    • client (Client | None) – Optional httpx.Client (test-injection seam).
    • timeout (float) – Per-request timeout in seconds.
  • 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).
    • OpenMeteoSeamlessLeakageErrormode='seamless' without allow_leakage=True. Raised BEFORE any HTTP request.
    • NotImplementedErrormode='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 with observation_type and raw_metar preserved — NO bucketing/resampling. Each row’s source column 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 when source= is pinned. Fixed-cadence resampling (exact-hourly, 30-min, …) is a separate preprocessing transform, not a granularity value.

        Each observation-grain row also carries a settlement_date column (D-19) — the ISO YYYY-MM-DD of 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 key dataset(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-isolated exact_window path for any pinned source= 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_type instead (True"dataframe", False"list"). Passing it explicitly emits a DeprecationWarning; when both are supplied an explicit return_type wins. Left unset (default), return_type governs and a no-arg call still returns a pandas.DataFrame.

    • backend ( {“pandas” , “polars”} , keyword-only , default “pandas”) – Output frame backend. "polars" requires return_type="wrapper" (polars frames carry no df.attrs provenance). Validated via the shared validate_backend_kwargs gate.

    • return_type ( {“dataframe” , “list” , “wrapper”} , keyword-only , default “dataframe”) – Output shape: raw pandas.DataFrame (default), plain list[dict] of rows, or a MostlyRightResult wrapper 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 the settlement_date column at granularity="observation". Rarely needed for the US registry.

  • Returns: Daily obs_* aggregate rows (granularity="daily") or merged per-report rows (granularity="observation"). Shape follows return_type.
  • Return type: pd.DataFrame | list[dict]
  • Raises:
    • ValueError – If source, strategy, or granularity is not in its allowed Literal set, OR if strategy="warm_cache" is called with source != None (post-merge filtering would corrupt SOURCE_PRIORITY semantics; use strategy="exact_window" for single-source queries).
    • DataAvailabilityError – If strategy="hosted" (the precomputed-API seam deferred to v0.2.x).
  • obs() does NOT return CLI climate columns (cli_high_f, cli_low_f, fcst_*). If you need joined obs + CLI + forecast, use research() directly.
  • The "auto" router’s warm_cache tactic produces daily aggregates byte-equivalent to research() for obs_high_f, obs_low_f, obs_high_at, obs_low_at, source (verified against the 5 Phase 1 parity fixtures in tests/weather/test_obs_warm_cache_parity.py). The exact_window tactic matches those values at the row level but intentionally bypasses year-aligned caching, so its cache footprint and fetch URLs differ.
>>> 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, or None (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 (all noaa_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 explicit satellite= for mixed lists.
    • product (str | None) – Product id, or None (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; None keeps every registered variable of product.
    • start (datetime) – Event-time window start (UTC, tz-aware recommended).
    • end (datetime) – Event-time window end. end < start raises ValueError.
    • 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 via KnowledgeView; 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 loud ValueError BEFORE any I/O. Mirror is transport-only: the source identity stays "noaa_goes" and there is NO mirror row 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}/satellite with the MOSTLYRIGHT_API_KEY header and returns rows byte-identical to delivery="live" (D-28.2 — delivery is 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".
  • Return type: DataFrame
  • Returns: pd.DataFrame carrying the satellite rows plus the leakage overlay columns (source/event_time/knowledge_time/retrieved_at/ delivery) and qc_status, with df.attrs["source"] set to the resolved per-source identity (noaa_goes for GOES, and the other native-ring sources forward as their adapters land).
  • Raises:
    • ValueErrorsatellite/product/mirror/delivery not in their enums (or product not registered for satellite’s source), or end < start, or a naive as_of datetime.
    • SourceUnavailableError – the [satellite] optional extra is absent.
cacheLocal parquet cache for mostlyright weather observations and climate.
catalogWeather catalog: adapter registry + WeatherAdapter Protocol.
climate(station, start, end, *[, source, …])Return NWS CLI daily settlement labels for station over [start, end].
cwopmostlyright.weather.cwop — standalone CWOP (Citizen Weather Observer Program) live adapter.
earningsEarnings-audio Tier-2 ENGINE module (Phase 27, 27-03).
forecast_nwpPublic NWP-forecast surface (Phase 3.2 — live HRRR/GFS/NBM).
obs(station, start, end, *[, source, …])Return observation data for station over [start, end].
qcWeather QC rules + per-model NWP physics-bounds registry (Phase 17 PLAN-10).
qc_sidecarPhase 3.4 — observation QC sidecar writer.
satellite(station[, satellite, product, …])Fetch native-L2 satellite single-pixel values for one or more stations.