All five station networks in one call#

easysnowdata.stations reads five public snow-station networks: the USDA NRCS AWDB (SNOTEL and snow courses), California’s CDEC, British Columbia’s DataBC, Norway’s NVE HydAPI and the Yukon’s AquaCache. Each has its own catalog entry and client, but inventory() and load() take station codes from any of them and fan the request out to the right client.

inventory() defaults to source="archive", the published inventory from global_snow_networks: one request for all five networks, no credentials. source="clients" asks the five APIs instead. load() always goes to the live clients, so a list that includes a Norwegian station needs the NVE key in NVE_API_KEY; the other four need no account.

The figures show every daily station in the world coloured by network, and one water year of SWE at one station from each network on a common time axis.

import easysnowdata as esd

print(f"easysnowdata {esd.__version__}")
easysnowdata 0.3.3.dev40+g1bd7bbbf4

The five products and the routes behind them. Only NVE needs a credential.

for product_id in sorted(esd.stations.PRODUCT_IDS.values()):
    for src in esd.catalog.get(product_id).sources:
        print(
            f"{product_id:16} {src.id:8} {src.title:40} "
            f"{', '.join(src.requires) or 'no account'}"
        )
awdb-stations    awdb     USDA NRCS AWDB REST API v1               no account
cdec-stations    cdec     California Data Exchange Center          no account
databc-stations  databc   BC Data Catalogue / BC ENV snow data     no account
nve-stations     nve      NVE HydAPI v1                            nve
yukon-stations   yukon    Yukon Water Data (AquaCache) API v1      no account

Every station with a probe-verified daily record, across all five networks, in one request. AWDB is two thirds of the total.

inv_gdf = esd.stations.inventory(daily_only=True)
print(inv_gdf["network"].value_counts().to_string())
network
awdb      1214
cdec       346
databc     154
nve         32
yukon       17

The map spans from Alaska to Svalbard, and to the four stations NVE serves in Nepal. A degree of longitude is short at 70°N, so the axes are drawn with a latitude-corrected aspect, and the scale bar is right at the central latitude.

ax = esd.plotting.points(
    inv_gdf,
    column="network",
    markersize=6,
    figsize=(12, 5),
    title=f"{len(inv_gdf)} daily snow stations in five networks",
)
1763 daily snow stations in five networks
/home/runner/work/easysnowdata/easysnowdata/docs/gallery/stations/plot_all_networks.py:45: GeographicAxesWarning: The data are in a geographic CRS (EPSG:4326), so one axis unit is a degree, not a metre. The axes use a latitude-corrected aspect (1/cos(53.1°) = 1.67) so shapes are not stretched; for a true equal-area grid load the product with crs='utm'.
  ax = esd.plotting.points(

One station from each network, by code alone. AWDB triplets, NVE’s dotted numbers and Yukon’s hyphenated codes give their network away by shape; a CDEC or DataBC code is looked up in the inventory. The five requests go to five clients and come back on one (station, time) grid.

codes = ["679_WA_SNTL", "CSL", "1A01P", "12.142.0", "09AA-M1"]
obs_ds = esd.stations.load(codes, variables="swe", time="2023-10/2024-09")
print(obs_ds["network"].to_series().to_string())
station
679_WA_SNTL      awdb
12.142.0          nve
09AA-M1         yukon
CSL              cdec
1A01P          databc

One water year of SWE, in centimetres everywhere: the clients convert AWDB’s inches and DataBC’s millimetres before the values are merged.

ax = esd.plotting.timeseries(
    obs_ds["swe"], title="Water year 2024, one station per network"
)
Water year 2024, one station per network

With several networks in one Dataset, attrs["source"] joins the source ids, and the per-station truth is the network coordinate.

print(obs_ds.attrs["source"])
print(obs_ds.attrs["source_title"])
print(obs_ds["swe"].attrs)
awdb nve yukon cdec databc
USDA NRCS AWDB REST API v1; NVE HydAPI v1; Yukon Water Data (AquaCache) API v1; California Data Exchange Center; BC Data Catalogue / BC ENV snow data
{'units': 'cm', 'long_name': 'snow water equivalent', 'native_variables': 'SNO ADJ WTEQ swe_m swe_mm', 'interval': 'daily'}

For every daily station at once, easysnowdata.stations.archive.load() reads the pre-downloaded bundle instead of calling five APIs.

Total running time of the script: (0 minutes 20.693 seconds)