Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Stage in-situ precipitation timeseries for a given AOI and time range and compare to rasters

Stage data on S3 via CLI

Note: I’m writing this under a ‘scratch’ prefix that automatically deletes after 2 weeks

11:43:38 [   1.3s] stagefile: Wrote s3://gaia/scratch/public/skagit/stage.yaml
11:43:38 [   1.3s] runner: synoptic: loading (2025-12-01T00:00:00/2025-12-16T23:59:59, read as 2025-11-30T00:00:00/2025-12-17T23:59:59)
11:43:38 [   1.3s] datasets.synoptic: querying station metadata from https://api.synopticdata.com/v2
11:43:38 [   1.4s] datasets.synoptic: found 23 stations with precip_accum in the AOI
11:43:38 [   1.4s] datasets.synoptic: fetching timeseries for 23 station(s)
11:43:39 [   2.2s] io: Writing Zarr to s3://gaia/scratch/public/skagit/skagit.zarr
11:43:43 [   6.2s] io: Saved s3://gaia/scratch/public/skagit/skagit.zarr
11:43:43 [   6.3s] io: Wrote STAC item s3://gaia/scratch/public/skagit/skagit.json
11:43:43 [   6.3s] runner: prism: loading (2025-12-01T00:00:00/2025-12-16T23:59:59, read as 2025-11-30T00:00:00/2025-12-17T23:59:59)
11:43:43 [   6.5s] prism_cache.cache: PRISM ppt: 18 of 18 grid(s) in cache https://s3.kopah.uw.edu/gaia/public/prism (0 provisional, 0 missing)
11:43:44 [   6.6s] datasets.prism: PRISM ppt: reading 18 day(s) x 164 x 208 cells from cached COGs
11:43:49 [  12.6s] io: Writing Zarr to s3://gaia/scratch/public/skagit/skagit.zarr
11:43:54 [  17.5s] io: Saved s3://gaia/scratch/public/skagit/skagit.zarr
11:43:55 [  17.8s] io: Wrote STAC item s3://gaia/scratch/public/skagit/skagit.json
11:43:55 [  17.8s] runner: hrrr: loading (2025-12-01T00:00:00/2025-12-16T23:59:59, read as 2025-11-30T00:00:00/2025-12-17T23:59:59)
11:43:55 [  17.8s] datasets.hrrr: opening dynamical.org Icechunk repo s3://dynamical-noaa-hrrr/noaa-hrrr-analysis/v0.2.0.icechunk/
11:43:56 [  19.2s] datasets.hrrr: HRRR precipitation_surface: reading 432 hour(s) x 50 x 47 cells (2025-11-30T00:00 to 2025-12-17T23:00)
11:43:58 [  20.6s] io: Writing Zarr to s3://gaia/scratch/public/skagit/skagit.zarr
11:44:04 [  27.1s] io: Saved s3://gaia/scratch/public/skagit/skagit.zarr
11:44:04 [  27.3s] io: Wrote STAC item s3://gaia/scratch/public/skagit/skagit.json
11:44:04 [  27.3s] runner: Done
                           PRE skagit.zarr/
2026-10-21 11:44:04       3560 skagit.json
2026-10-21 11:43:38        656 stage.yaml

Work with staged data

Our bucket has anonymous read access, so anyone can access it

('/', '/stations', '/rasters', '/stations/synoptic', '/rasters/hrrr', '/rasters/prism')

Weather station timeseries

Loading...
Loading...
Loading...
<Figure size 640x480 with 1 Axes>
<Figure size 300x310.53 with 2 Axes>

Raster data: PRISM and HRRR

Loading...

1. Native (unaligned) grids

gaia stage keeps each raster on the grid and time step of its source (see dev/prism.md, dev/hrrr.md):

PRISMHRRR
CRSEPSG:4269 (lat/lon), ~800 mLambert Conformal, 3 km
Time stepdaily; date D covers (D−1 12:00, D 12:00] UTChourly; time T covers (T−1 h, T]

time_bounds records the interval each value covers. Working on native grids means doing any alignment yourself, but it is the most faithful way to compare against stations, because no regridding happens.

PRISM: CRS 4269, resolution (0.0083, 0.0083), 18 time steps, first covers ['2025-11-29T12:00', '2025-11-30T12:00']
HRRR: CRS custom (Lambert Conformal), resolution (3000.0, 3000.0), 432 time steps, first covers ['2025-11-29T23:00', '2025-11-30T00:00']
US share of the AOI: 87%

A common accumulation window. Station values are running accumulations, PRISM days end at 12 UTC, and HRRR hours end on the hour. The store holds a day more on each side than requested, so align.common_window picks the longest interval inside [start, end] made of whole PRISM days and HRRR hours. align.select_window keeps each raster’s time steps inside it, and the station accumulations are differenced over exactly the same interval.

Window 2025-12-01 12:00 to 2025-12-16 12:00 UTC: 15 PRISM days, 360 HRRR hours
<Figure size 1200x500 with 3 Axes>

☝️ Note that PRISM does not extend into Canada unfortunately.

Stations vs. native rasters

Sample each raster at the station locations (nearest cell, no regridding). The station points are reprojected into each raster’s CRS first.

19 stations with complete records over 2025-12-01 12:00 to 2025-12-16 12:00 UTC
Loading...
<Figure size 550x550 with 1 Axes>

Basin-mean accumulation at native time steps

The exact area-weighted mean over the US part of the AOI polygon (xvec + exactextract) of each native grid, accumulated over time. Each PRISM value is plotted at the end of its day (12 UTC), where it lines up with HRRR’s hour-ending values. Both curves cover the window above.

<Figure size 1000x400 with 1 Axes>

2. Aligned grids

gaia align puts the rasters on one grid and one time step. By default it sums HRRR’s hours into PRISM days (the coarsest time step), then regrids PRISM once, area-weighted (conservative), onto HRRR’s 3 km grid (the coarsest grid). It writes a new store and leaves the native one untouched (see dev/reprojecting.md). These aligned datacubes are much easier to work with, but opinionated choices have been made about how to align the rasters, so you may want to do your own alignment if you have a different idea!

11:44:18 [   2.2s] align: time target rasters/prism (18 step(s))
11:44:22 [   5.9s] align: grid target rasters/hrrr (50 x 47 cells)
11:44:22 [   6.3s] align: regridding rasters/prism/precipitation (conservative)
11:44:29 [  13.2s] io: Writing Zarr to s3://gaia/scratch/public/skagit-aligned/skagit-aligned.zarr
11:44:38 [  22.4s] io: Saved s3://gaia/scratch/public/skagit-aligned/skagit-aligned.zarr
11:44:38 [  22.6s] io: Wrote STAC item s3://gaia/scratch/public/skagit-aligned/skagit-aligned.json
11:44:38 [  22.6s] align: Done
Loading...
{'time': 15, 'y': 50, 'x': 47}; PRISM regridded with 'conservative'; HRRR 24 values of 60 minutes per day
<Figure size 1600x500 with 5 Axes>
Event totals: PRISM 464 mm, HRRR 370 mm (-20 %)
<Figure size 1000x600 with 2 Axes>

Interpretation

For this event (US part of the Skagit basin, December 1–16, 2025; precisely 2025-12-01 12:00 to 2025-12-16 12:00 UTC, the part of the request that whole PRISM days cover, since PRISM days run 12–12 UTC), HRRR is about 20 % drier than PRISM (~370 vs. ~464 mm basin mean). That ~94 mm gap is a difference between the two products. Regridding barely affects it: each product’s total from section 1 (native grids) and from this section (aligned grid) differ by only ~2 % (PRISM ~468 vs. ~464 mm, HRRR ~377 vs. ~370 mm). That small change comes from averaging over the exact basin outline on the native grids, but over whole 3 km cells on the aligned grid.

  • When: about two-thirds of the deficit falls on the three heaviest atmospheric-river days (12-09, 12-11 and 12-16, with the largest gap on 12-11). HRRR is wetter on a few moderate days (12-06, 12-10, 12-15).

  • Where: the difference map shows HRRR drier mainly in the west and north of the basin, where PRISM is wettest, with scattered patches where HRRR is wetter.

  • Against the gauges: PRISM is ~9 % above and HRRR ~11 % below the station totals. Across stations PRISM correlates better (0.86 vs. 0.76), but one gauge dominates that: at THBW1 HRRR is ~195 mm above the gauge, while it is below the gauge almost everywhere else. Without THBW1 the correlations are equal (0.89 vs. 0.88) and HRRR is ~15 % low. There are 19 gauges, but three pairs share a location (DARW1/COOPDARW1, MARW1/COOPMARW1, UBKW1/UBDW1), so only 16 sites. Neither product can be called right; the basin truth plausibly lies between the two.

  • PRISM has no data in British Columbia (~13 % of the basin), so every comparison here covers the US part only.