Source code for TeamOverbyeWeather.sources.noaa

"""NOAA/GFS forecast client — thin wrapper over :meth:`WeatherClient.download`."""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from .era5 import _spatial

if TYPE_CHECKING:
    from ..client import WeatherClient


[docs] class NOAAClient: """Access NOAA/GFS forecast datasets via :attr:`WeatherClient.noaa`. ``recent`` and ``archive`` are separate Drive folders, not a date split — a cycle in one will not appear in the other. """ def __init__(self, client: "WeatherClient") -> None: self._client = client
[docs] def list_forecast_cycles(self, type: str = "recent") -> list[str]: """List available cycles, newest first. Args: type: ``"recent"`` or ``"archive"``. """ return self._client.list("noaa", type)
[docs] def download_forecast( self, cycles: list[str], dest: str = ".", *, type: str = "recent", **kwargs, ) -> list[Path]: """Download NOAA/GFS forecast ``.pww`` files, one per cycle. Args: cycles: Cycle keys like ``["2026-07-22T12Z"]``. dest: Destination directory. type: ``"recent"`` or ``"archive"``. **kwargs: Passed to :meth:`WeatherClient.download`. """ return self._client.download("noaa", cycles, type, dest=dest, **kwargs)
[docs] def download_region( self, cycles: list[str], *, type: str = "recent", region_ids: list[str] | None = None, region_layer: str | None = None, bbox: tuple | None = None, dest: str = ".", **kwargs, ) -> list[Path]: """Download NOAA/GFS cycles cropped to a region or bbox. Args: cycles: Cycle keys. type: ``"recent"`` or ``"archive"``. region_ids: State postal codes or ISO zone ids. region_layer: ``"states"`` or ``"iso"``. bbox: ``(lat_max, lon_min, lat_min, lon_max)``. dest: Destination directory. **kwargs: Passed to :meth:`WeatherClient.download` (``time_start``, ...). """ spatial = _spatial(region_ids, region_layer, bbox) return self._client.download("noaa", cycles, type, dest=dest, **spatial, **kwargs)
[docs] def download_latest(self, dest: str = ".", **kwargs) -> Path: """Download the most recent NOAA/GFS forecast cycle. Raises: ValueError: If no forecast cycles are available. """ cycles = self.list_forecast_cycles() if not cycles: raise ValueError("No NOAA/GFS forecast cycles are currently available.") return self.download_forecast([cycles[0]], dest=dest, **kwargs)[0]