easysnowdata.stations.clients.AWDBClient#
- class easysnowdata.stations.clients.AWDBClient(base_url: str = 'https://wcc.sc.egov.usda.gov/awdbRestApi/services/v1', timeout: int = 180, max_retries: int = 3, backoff: int = 6, session: Session | None = None)[source]#
Bases:
objectClient for the USDA NRCS AWDB REST API v1.
- Parameters:
base_url (
str) – Base URL of the AWDB REST API. Override for staging / mirror endpoints.timeout (
int) – HTTP request timeout in seconds.max_retries (
int) – Number of retry attempts on transient server errors (5xx).backoff (
int) – Base backoff delay in seconds. Actual delay = backoff × attempt_number.session (
requests.SessionorNone) – Optional pre-configured session (useful for auth headers, proxies, etc.).
- get_reference_data(tables: list[str] | str = 'all') dict[str, Any][source]#
Fetch AWDB reference/lookup tables.
- Parameters:
tables (
list[str]orstr) – One or more reference table names, or"all"for everything. Common tables:"networks","elements","states","counties","durations","units".- Returns:
dict– Parsed JSON response. Keys are table names; values are lists of{code, name, description}dicts.
Example
>>> client = AWDBClient() >>> ref = client.get_reference_data(["networks", "elements"]) >>> ref["networks"][0] {'code': 'SNTL', 'name': 'SNOTEL', ...}
- get_stations(networks: list[str] | str | None = None, states: list[str] | str | None = None, huc: str | None = None, county_name: str | None = None, active_only: bool = False, station_triplets: list[str] | str | None = None) list[dict][source]#
List stations matching the given filters.
Returns only basic identification fields (no element inventory). Use
get_metadata()to retrieve full metadata including elements.- Parameters:
networks (
list[str]orstr, optional) – Network code(s) to filter by, e.g.["SNTL", "SNTLT"]. Defaults to all networks ("*").states (
list[str]orstr, optional) – Two-letter state code(s), e.g.["CO", "UT"].huc (
str, optional) – Hydrologic Unit Code prefix (2–12 digits). Stations whose HUC starts with this prefix are returned.county_name (
str, optional) – County name filter (case-insensitive prefix match).active_only (
bool) – If True, only return stations with noendDate.station_triplets (
list[str]orstr, optional) – Explicit list of station triplets to retrieve. Overrides network and state filters when provided.
- Returns:
list[dict]– List of station dicts with keys:stationTriplet,stationId,networkCode,name,stateCode,countyName,huc,latitude,longitude,elevation,beginDate,endDate.
Example
>>> stations = client.get_stations(networks=["SNTL"], states=["CO"]) >>> len(stations) 117
- get_metadata(triplets: list[str] | str, elements: list[str] | str = '*', durations: list[str] | str = '*', include_forecast_point: bool = False, include_reservoir: bool = False, active_only: bool = False) dict | list[dict][source]#
Retrieve full station metadata including the element inventory.
Given a single triplet this returns one dict, which is the
get_metadata(station_id) -> dictcontract of DESIGN.md §3.4 that the other four clients implement. Given a list it returns one dict per station, which the inventory pipeline needs: AWDB carries ~4 000 stations and fetching them one at a time is not viable, so this client keeps the batch form the API supports.- Parameters:
triplets (
list[str]orstr) – Station triplet(s), e.g."303:CO:SNTL"or a list.elements (
list[str]orstr) – Element code(s) to filter the station element list by, e.g.["WTEQ", "SNWD"]. Pass"*"for all elements.durations (
list[str]orstr) – Duration name(s) to filter by, e.g.["DAILY", "MONTHLY"]. Pass"*"for all durations.include_forecast_point (
bool) – Include forecast point metadata if available.include_reservoir (
bool) – Include reservoir metadata if available.active_only (
bool) – If True, only return active elements.
- Returns:
dictorlist[dict]– One dict when triplets is a single triplet, otherwise one dict per station. Each dict contains all AWDB metadata fields plus astationElementslist (one entry per matching element × duration combination). A single triplet that matches no station returns an empty dict.
Notes
Only stations that have at least one matching element are returned. Requests are automatically split into batches of at most 150 triplets and then split further on request-size errors to avoid URL-length and payload-size limits.
Example
>>> meta = client.get_metadata( ... ["303:CO:SNTL", "713:CO:SNTL"], ... elements=["WTEQ", "SNWD"], ... durations=["DAILY"], ... ) >>> meta[0]["stationElements"][0]["elementCode"] 'SNWD'
- get_data_by_water_year(triplets: list[str] | str, elements: list[str] | str, water_year: int, duration: str = 'DAILY', **kwargs) list[dict][source]#
Convenience wrapper: fetch data for a single water year.
A water year runs from October 1 of the previous calendar year to September 30 of
water_year. For example, WY2024 spans 2023-10-01 through 2024-09-30.- Parameters:
- Returns:
list[dict]– Same structure as_get_data_awdb()(nested AWDB payload, not the flat records ofget_data()).
- get_normals(triplets: list[str] | str, elements: list[str] | str, duration: str = 'DAILY', normal_period: str = '1991-2020', central_tendency_type: str = 'MEDIAN') list[dict][source]#
Retrieve climatological normals (medians or averages) for stations.
- Parameters:
- Returns:
list[dict]– Same structure as_get_data_awdb()(nested AWDB payload) withmedian/averagefields alongsidevaluein the values list.
Example
>>> norms = client.get_normals( ... "303:CO:SNTL", ["WTEQ"], normal_period="1991-2020" ... )
- get_all_stations(active_only: bool = False, bbox: tuple[float, float, float, float] | None = None) list[dict][source]#
Standardized station list.
- Parameters:
- Returns:
list[dict]– Station dicts (same schema asget_stations()).
- get_data(station_ids: list[str] | str | None = None, variables: list[str] | str | None = None, bbox: tuple[float, float, float, float] | None = None, begin_date: str | date | None = None, end_date: str | date | None = None, interval: str = 'daily', include_flags: bool = False) list[dict][source]#
Standardized data fetch — returns a flat list of observation records.
- Parameters:
station_ids (
list[str]orstrorNone) – AWDB station triplet(s), e.g."303:CO:SNTL". Required unlessbboxis provided.variables (
list[str]orstrorNone) – Element codes (e.g."WTEQ") or standardized types (e.g."swe").Nonereturns all elements inVARIABLES.bbox (
tuple, optional) –(min_lon, min_lat, max_lon, max_lat). Alternative tostation_ids; fetches data for all stations in the box.begin_date (
strordate, optional) – Start date ("YYYY-MM-DD"). Defaults to earliest available.end_date (
strordate, optional) – End date (inclusive). Defaults to today.interval (
str) – Temporal resolution:"daily","hourly","monthly", etc. Mapped to the AWDBdurationparameter.include_flags (
bool) – Reserved; the AWDB REST API does not return per-value QC flags.
- Returns:
list[dict]–Flat list of observation records:
{ "station_id": "303:CO:SNTL", "date": "2024-01-15", "variable": "WTEQ", "type": "swe", "value": 14.2, "units": "cm", "interval": "daily", # "flag": None (only present when include_flags=True) }
- Raises:
ValueError – If neither
station_idsnorbboxis provided.AWDBError – If a batch request fails after all retries.