Stations#

easysnowdata.stations#

Snow-station observations from five public networks (§9).

import easysnowdata as esd

aoi = (-121.94, 46.72, -121.54, 46.99)                 # Mount Rainier
stations_gdf = esd.stations.inventory(aoi, daily_only=True)  # GeoDataFrame
obs_ds = esd.stations.load(stations_gdf, variables=["swe", "snwd"],
                           time="2023-10/2024-06")  # (station, time)
everything_ds = esd.stations.archive.load()  # every daily station

Three layers, as global_snow_networks’ DESIGN.md §2 lays them out:

clients

Pure access, moved here verbatim with its history: one client per network (AWDB, CDEC, DataBC, NVE, Yukon), each answering get_all_stations / get_data / get_metadata with plain dict records in metric units. Use it directly when you want flags, a native variable name or an interval the adapter does not surface.

this module

inventory() and load(), which put those records into the package’s own return types and take aoi and time like every other loader.

archive

The daily archive that repo publishes — a normalized station inventory, a chunked Zarr store on its GitHub Pages site (the default), and per-station CSVs bundled in each snapshot release — for every station’s daily record without hitting five APIs. SWE and snow depth only.

The station × time grid comes back dense with NaN where a station has no observation. That is what xarray, Dask, and groupby want, and a station record is only sparse in the everyday sense — nothing here needs a sparse array backend. Station positions are latitude and longitude coordinates rather than an xvec geometry coordinate: the plan lists xvec as optional, it would be a new dependency, and float coordinates round-trip through Zarr and netCDF where a geometry object does not.

Station identity has two spellings, both accepted everywhere: the globally unique code ("679_WA_SNTL") and the network’s own station id ("679:WA:SNTL"). See easysnowdata.stations.networks.

inventory

Snow stations as a GeoDataFrame, indexed by their global station code.

load

Station observations as a (station, time) Dataset.

metadata

Full per-station metadata from the owning network's API.

easysnowdata.stations.archive#

The daily station archive: everything daily, without hitting five APIs.

global_snow_networks pre-downloads daily SWE and snow depth for every station its probe has verified as daily-or-better, and publishes three artefacts that this module reads (§9 step 3):

all_snow_stations.geojson

Every station from every archived network, periodic sites included, with the 26 normalized properties of that repo’s DESIGN.md §6.1 — including daily_or_better, which is the probe’s verdict rather than what a network advertises about itself.

archive/*.zarr on that repo’s GitHub Pages site

The same observations as the CSVs below, chunked (that repo’s DESIGN.md §6.5): by_time.zarr for “one water year, every station” and by_station.zarr for “this station’s whole record”. Pages serves range requests, so a query fetches the chunks it touches — well under a megabyte for either of those — instead of the whole bundle. The default route.

all_station_csvs.tar.xz on that repo’s latest GitHub Release

One date,wteq_cm,snwd_cm CSV per daily-or-better station, bundled: the periodic, DOI’d snapshot (a few times a year), about 28 MB and whole-file only. The fallback when Pages is down, since Releases are served from elsewhere — and the route to use when a result should be pinned to a citable snapshot rather than to today’s archive.

import easysnowdata as esd

stations_gdf = esd.stations.archive.inventory(daily_only=True)  # one request
archive_ds = esd.stations.archive.load(aoi=(-121.94, 46.72, -121.54, 46.99))

Both artefacts are refreshed daily by that repo’s CI, so the archive is at most a day behind and covers only SWE and snow depth. For anything else — a different variable, an interval other than daily, quality flags, or today’s observation — use easysnowdata.stations.load(), which goes to the networks themselves.

csv_url

URL of one station's archive CSV.

inventory

The published station inventory as a GeoDataFrame indexed by code.

latest_snapshot

The newest snapshot release of global_snow_networks.

load

Daily SWE and snow depth for many stations, from the published archive.

manifest

archive.json from the Pages store: when it was built, from which commit.

network_of

{code: network} from the inventory, for codes whose shape is ambiguous.

easysnowdata.stations.clients#

AWDBClient

Client for the USDA NRCS AWDB REST API v1.

AWDBError

Raised when the AWDB API returns an error or a request fails.

AlbertaClient

Client for snow data on the Alberta River Basins site (rivers.alberta.ca).

AlbertaError

Raised for Alberta River Basins source failures and bad requests.

CEAZAClient

Client for the CEAZA-Met web service (Coquimbo region, Chile).

CEAZAError

Raised for CEAZA-Met web-service failures and bad requests.

CDECClient

Client for CDEC (California Data Exchange Center).

CDECError

Raised when the CDEC API returns an error or a request fails.

CanSWEClient

Client for the CanSWE netCDF (latest Zenodo version, cached locally).

CanSWEError

Raised when CanSWE cannot be fetched, opened or queried.

DWDClient

Client for DWD CDC daily snow water equivalent and snow depth.

DWDError

Raised when a DWD CDC file cannot be fetched or parsed.

DataBCClient

Client for BC snow survey data via BC Data Catalogue.

DataBCError

Raised when a DataBC request fails.

FMIClient

Client for FMI's open-data WFS (daily snow depth and weather).

FMIError

Raised for FMI open-data failures and bad requests.

GHCNDClient

Client for NOAA NCEI GHCN-Daily station files.

GHCNDError

Raised when a GHCN-D file cannot be fetched or parsed.

HydroQuebecClient

Client for Hydro-Québec's open hydrometeorological feed (Opendatasoft).

HydroQuebecError

Raised when the Hydro-Québec portal fails or a request is invalid.

NVEClient

Client for the NVE HydAPI (Norwegian hydrological data service).

NVEError

Raised when the NVE HydAPI returns an error or a request fails.

NorSWEClient

Client for the NorSWE netCDF (latest Zenodo version, cached locally).

NorSWEError

Raised when NorSWE cannot be fetched, opened or queried.

RIHMIClient

Client for RIHMI-WDC route snow surveys and daily snow cover.

RIHMIError

Raised when RIHMI/NSIDC data cannot be fetched, parsed or resolved.

SLFClient

Client for open SLF snow-station datasets (GCOS SWE, new-snow SWE, manual study plots, IMIS).

SLFError

Raised for SLF / EnviDat source failures and bad requests.

SNIHClient

Client for the SNIH snow stations of Argentina.

SNIHError

Raised for SNIH portal failures and bad requests.

SYKEClient

Client for the Syke hydrology OData API (snow courses and areal SWE).

SYKEError

Raised for Syke hydrology API failures and bad requests.

SouthernAndesClient

Client for the Southern Andes Daily Snow Depth Dataset (Zenodo).

SouthernAndesError

Raised when the Southern Andes dataset cannot be fetched, read or queried.

YukonClient

Client for the Yukon Water Data (AquaCache) API.

YukonError

Raised when the Yukon AquaCache API returns an error or a request fails.

easysnowdata.stations.networks#

The snow-station networks, and how a station code maps to one of them.

Each Network ties a catalog source id to the vendored client that speaks to it (easysnowdata.stations.clients) and to the spelling of a station identifier in that network. Two spellings matter:

code

The globally unique code the inventory and the archive use, e.g. "679_WA_SNTL". Unique across all networks.

station_id

What the network’s own API calls the station, e.g. the AWDB triplet "679:WA:SNTL". AWDB swaps : for _; Alberta, SLF, SNIH, CEAZA and FMI codes add a prefix ("ARB-05BB803", "SLF-IMIS-WFJ2", "SNIH-12817", "CEAZA-HDC", "FMI-101932"), as global_snow_networks names them; for the rest the code is the station id.

split_by_network() turns a mix of codes, station ids and inventory rows into {network_id: [station_id, …]}, which is what easysnowdata.stations.load() fans out over.

Network

One snow-station network and the client that reads it.

canonical_units

The unit easysnowdata.stations.load() emits for type_name.

get

Return the Network called network.

slf_split

"IMIS-WFJ2" (or "SLF-IMIS-WFJ2") → ("imis", "WFJ2").

split_by_network

Group stations by network, as {network_id: [station_id, …]}.

to_code

The globally unique code of station_id in network.

to_station_id

The native station id of station in network.