Hot Rivers — Which Runs Are Surging?
Daily Passage — Bonneville Dam Live
Daily Passage — Lower Granite Dam Live
Annual Run Size by Dam
Daily Passage by Destination River New
Cumulative Run Timing — Bonneville
Cumulative Run Timing — Lower Granite
Run Timing by River New
Basin Destination by Year New
Other/Unknown is not a river — it is the part of the dam count we could not attribute, typically 30–35% of the run. Years where the tags cannot support a breakdown at all (MY2011: 63 tags for 414,057 fish) are shown entirely as unresolved rather than split. Rivers entering the Columbia below Bonneville are excluded here: those fish never passed the dam being counted. Yakima uses the Prosser Dam census rather than the model, because a count beats an estimate.
* Method note: these totals now sum to the full dam count, matching how Idaho Fish and Game publish theirs. Fish we cannot attribute to a river are distributed across drainages rather than left in a separate bucket — previously about 35–45% of the run sat unassigned, which made every river read roughly 40% low. Hatchery and wild are allocated separately (they have different basin distributions) and recombined using the fin-clip census at the dam.
Sub-Basin Destinations New
Ocean Age × Origin (IDFG Style) New
How ocean age is known: only for fish PIT-tagged as juveniles, where we know the year they went to sea. Ocean age = (return migration year − smolt migration year) − 1. A fish tagged as an adult has no smolt year, so its ocean age is unknowable and it is excluded. How origin is known: a juvenile tagged at a hatchery is hatchery; one tagged at a screw trap or in-river is wild. The bar heights come from the DART dam census; only the split between age and origin classes is estimated from tags.
Read the labels before trusting a bar. Each shows the PIT tags behind it. Early years rest on very few — MY2013 has 118 tags for 232,795 fish (~1,970 fish per tag), where 2024–25 has 5,154 (~35 per tag). A bar built on a hundred tags can invert if a handful of fish are classified differently; the recent years are solid.
Returning Adults by Drainage Beta
Hatchery vs Wild — Bonneville
Steelhead = the total run and Wild Steelhead = the wild subset of that total, so hatchery = total − wild. (Adding the two columns double-counts every wild fish and inflates the run 28–40%; that error reached this site once before.) This is a census of every fish that passed, not an estimate.Hatchery vs Wild — Lower Granite
Ocean Age × Origin (IDFG Style)
Winters at sea × hatchery/wild. Identical to the Destinations-tab copy — one number, two homes. Current season: see the one-salt collapse note.
Adult Length Distribution
Adult Length vs Ocean Age New
Columbia Basin Migration Flows New
Per-River Migration Flows New
Entry-Gate Detections by River New
Migration Timing by Year — Dams New
PTAGIS Detection Sites — Map
Streamflow & Fish Detections Live
Select a river and click "Load Flow Data" to fetch live streamflow
Data from USGS National Water Information System (waterservices.usgs.gov)
How to Use This Dashboard
Every chart on this site is interactive. Here are the key things you can do:
Legend Controls:
- Single click a year or river in the legend to hide/show it
- Double-click a legend entry to isolate it — only that item will show. Double-click again to restore all.
Dropdowns & Buttons:
- Use dropdown menus (top-left of charts) to switch between views — dam totals, individual rivers, smoothing modes, etc.
- On the Run Timing chart, the dropdown lets you pick Bonneville (BON) or Lower Granite (LWG) scaling and filter to individual rivers. Single-river views color lines by year so you can compare across seasons.
Chart Interaction:
- Hover over any line or bar to see detailed data — fish counts, percentages, PIT tag info, expansion factors
- Click + drag to zoom into a region. Double-click to reset zoom.
- Use the camera icon in the top-right toolbar to download a chart as a PNG image
What Can You Learn?
- Dam Passage — Compare this year's daily fish counts to historical patterns. Is the run early, late, big, or small?
- Run Timing — Track cumulative progress: what % of the run has passed? How does each river compare?
- Destinations — Where are the fish going? Basin destination shows estimated returns per river system. The "expansion" number in the hover tells you how many real fish each PIT tag represents (e.g., 5x means each tagged fish represents ~5 total fish). This is calculated by dividing the DART dam count by the number of PIT tags detected.
- Fish Biology — Size distributions and ocean age help understand the population mix (1-ocean vs 2-ocean fish).
- Migration Flows — Sankey diagram traces fish from Bonneville through each dam to their final destination river. Width of each band = number of fish. Use the year dropdown to compare across years.
- Fish Biology — Click any fish dot on the growth scatter to open its full tag history on PTAGIS. Orange diamond markers are fish with a single adult measurement only (age is estimated from length).
Dam & Site Abbreviations:
About SteelheadTracker
SteelheadTracker is a passion project that tracks Columbia Basin steelhead migration using publicly available data from DART (Columbia Basin Research), PTAGIS (PIT Tag Information System), USGS (water data), and NOAA (weather forecasts).
Data Sources:
- DART — Dam passage counts (daily & annual)
- PTAGIS — PIT tag detection data (individual fish tracking)
- PTAGIS Detection Sites — PIT tag monitoring site locations and metadata
- USGS — Streamflow and water temperature
- NOAA — River flow forecasts
- Columbia Basin Dam Map — Overview of dam locations in the basin
How It Works:
A build script fetches the latest DART dam passage data and combines it with precomputed PIT tag analysis (basin destinations, growth, origin classification). Charts are rendered client-side using Plotly.js — no server computation needed.
Methodology Notes:
- Destination and returning adult charts use calendar year for consistency with dam passage data
- H/W classification from DART uses the "Wild Steelhead" column reported by dam operators
- PIT-based H/W uses release site information to infer hatchery vs wild origin
- Basin destinations are based on post-dam PIT detections at tributary sites
- Charts marked "Beta" are under active development and may have known limitations
A Note on the Numbers:
Estimating how many steelhead are heading to each river turns out to be a genuinely hard problem. We only have PIT tags in a fraction of the fish, and those tags have to be expanded out — multiplied by factors that can range from 10× to 50× or more — to estimate total basin destinations. I've done my best to cross-reference DART dam counts, PIT tag detections, and the v117p expansion model to produce something useful, but I'm not a fisheries biologist with access to better data, and I'm not a mathematical genius. There are real limitations here: expansion factors vary by year and river, some rivers have very few PIT tags to work with, and the entry gate detection efficiency isn't 100%. If you spot something that looks off, or you have expertise that could improve the methodology, I'd love to hear from you. This is the best I could do with what's publicly available — and I think it's still pretty useful.
Contact & Support:
Built by Paul Van Valkenburg — paul.vanvalkenburg@gmail.com
If you find this project useful and want to support its development — whether that means buying me a beer, helping me take my wife out to dinner to repair the damage this site has done to my marriage, or just keeping the servers running — any contribution is appreciated. Donate via PayPal
Want to receive updates? Email me to join the mailing list.
What's New
August 2026 — a big update, and an honest one.
This site ran without updates from late February to late August 2026. During that gap I found several real problems in my own numbers, and rather than patch quietly I rebuilt the validation from the ground up. Everything below is now checked against independent published sources — IDFG and ODFW's own figures, dam-by-dam censuses — before it ships, and a hard gate blocks the site from deploying if the numbers fail.
Fixed in this update:
- Eight charts restored — the live build had silently switched to an older script and dropped them (including the calendar/migration-year toggles).
- Ocean age corrected — 1-salt fish were dramatically undercounted by a day-counting bug; ages now derive from migration years and are validated against length distributions.
- One number per quantity — the cumulative run-timing chart and the destinations chart could disagree about the same river by 5x. Both now read from a single source; if you compare them, they match.
- Hatchery and wild estimated separately — the PIT-tag sample is 93–99% hatchery while the actual run is 52–72% hatchery. Pooling them made every destination estimate quietly a hatchery estimate. Wild allocation now uses wild sources and the dam fin-clip census.
- New: sub-basin destinations — Lochsa, Selway, Lemhi, Pahsimeroi and 18 more tributaries, from the separate hatchery/wild allocation.
- Confidence intervals repaired — some intervals didn't contain their own estimate after a late rescaling step; whiskers now wrap every bar.
- Impossible destinations removed — basins that enter the Columbia below Bonneville can't be destinations for fish counted at Bonneville.
- 2011 shown as unresolved — only 63 usable tags exist for that migration year, which cannot support per-river estimates. The bar now says so instead of pretending.
- Detection data current through August 23, 2026.
Known limitations, plainly:
- Snake River mainstem estimates lean on a model prior (very few tags resolve there) — treat them as indicative, not measured.
- The current migration year is always partial until the run completes in May.
- Tag-expansion methodology is under active validation against IDFG's published numbers; expect refinements, and expect me to say so here when they land.
Site build v134l · August 23, 2026