Skip to content

mostlyright.weather.forecast_nwp

Public NWP-forecast surface (Phase 3.2 — live HRRR/GFS/NBM).

End-to-end pipeline:

  1. Validate (model, mirror) against the closed enums in mostlyright.weather._fetchers._nwp_archive. Reserved ECMWF models raise NwpModelNotAvailableError.
  2. Resolve cycle (default: latest cycle whose lead time covers the requested fxx).
  3. For each mirror in the fallback chain: fetch the .idx text, do a HEAD for Content-Length, parse + filter to the model’s VARIABLE_MAP records, fetch each record via Range: bytes=.., write the concatenated bytes to a one-message-per-file GRIB2 in a temp directory, decode with cfgrib, extract per-station values with the cached BallTree, populate the canonical DataFrame.
  4. Run inline physics-bounds QC; tag each row with qc_status ∈ {clean, flagged, suspect}.
  5. Validate the assembled DataFrame against schema.forecast_nwp.v1.

If all wired mirrors fail, raise NoLiveForNwpError carrying the mirror chain. If any byte-range fetch returns bytes that fail GRIB2 structural checks, raise GribIntegrityError.

This module imports cfgrib / xarray / sklearn lazily inside forecast_nwp() so the module imports cleanly even without the [nwp] extra installed. The optional-extra hint is surfaced via SourceUnavailableError.

forecast_nwp(station, model, *[, cycle, …])Fetch NWP forecast values for one or more stations from NOAA BDP.

mostlyright.weather.forecast_nwp.forecast_nwp(station, model, , cycle=None, cycle_range_start=None, cycle_range_end=None, fxx=None, mirror=None, member=None, client=None, backend=‘pandas’, return_type=‘dataframe’)

Section titled “mostlyright.weather.forecast_nwp.forecast_nwp(station, model, , cycle=None, cycle_range_start=None, cycle_range_end=None, fxx=None, mirror=None, member=None, client=None, backend=‘pandas’, return_type=‘dataframe’)”

Fetch NWP forecast values for one or more stations from NOAA BDP.

  • Parameters:
    • station (str | list[str]) – Single ICAO/NWS code or a list of them. Unknown codes are skipped with a logged warning (not raised) so a partial list still returns a partial DataFrame.
    • model (str) – One of SUPPORTED_NWP_MODELS ("hrrr", "gfs", "nbm"). ECMWF Tier-2 values raise NwpModelNotAvailableError.
    • cycle (datetime | None) – Model run cycle (UTC, tz-aware). Default: the most recent cycle whose run + fxx clears a 90-minute upload backoff.
    • fxx (int | None) – Forecast hour ahead of cycle. Default 1 (next hour).
    • mirror (str | None) – Force a specific mirror ("aws_bdp" or "nomads"). Default: try AWS first then NOMADS.
    • member (str | None) – Ensemble member id — only valid for the member-capable models GEFS (e.g. "p05", default "c00") and CFS ("01"..“”04”, default ``"01"). None (the default) keeps the path-builder default and is byte-identical to pre-issue-#74 behavior. Threaded to the GEFS/CFS path builder only when non-None.
    • client (Client | None) – Reuse an httpx.Client for connection pooling. A fresh client is created (and closed) per call if omitted.
    • cycle_range_start (datetime | None)
    • cycle_range_end (datetime | None)
    • backend (str)
    • return_type (str)
  • Return type: DataFrame
  • Returns: pd.DataFrame matching schema.forecast_nwp.v1 — one row per (station, variable subset) for the given cycle/fxx. Empty DataFrame (with the canonical columns) if every requested station is unknown OR the model variable map matches no records in the upstream .idx (genuinely missing variables).
  • Raises:
    • NwpModelNotAvailableErrormodel is reserved (ECMWF Tier-2).
    • ValueErrormodel or mirror is not in the supported set; fxx is negative; cycle is naive; member is set for a non-member model, or is not a valid member of the requested model’s ensemble (GEFS/CFS).
    • SourceUnavailableError – the [nwp] optional extra (cfgrib + xarray + sklearn) is not installed.
    • NoLiveForNwpError – every wired mirror failed (typically while the upstream is still uploading a cycle).
    • GribIntegrityError – at least one fetched record decoded with structural failures (Pitfall 1 territory — cfgrib raises for a truncated final-record byte range).