Catch patterns
What drives the catch
Cross-year analysis of catches, migration, weather and flow. Every finding tested with Benjamini-Hochberg FDR correction — only patterns that survive across the whole dataset are flagged as significant.
Predictions — what matters and where the next 30 days look strongest
Per-river RandomForest fit on weather + flow + season features + recency-weighted 30-day rolling-mean forecast.
Two views per river: a horizontal bar of feature importance (what the model explains the variance with) and a line chart of the next 30 days (expected catch rate, with the top 5 dates highlighted in emerald). R² values are reported honestly — most are slightly negative, which means catch rate is mostly noise at the fishery-day grain. Treat the bars as a directional signal, the dates as a "where to look first" hint, not a tip.
Byskeälven
Model R² = -0.30 · RMSE = 0.273 · trained on 564 days, held out 142.Note: R² < 0 means the model is barely better than predicting the mean.
What matters
Next 30 days
Kalixälven
Model R² = -0.31 · RMSE = 0.386 · trained on 132 days, held out 33.Note: R² < 0 means the model is barely better than predicting the mean.
What matters
Next 30 days
Lögdeälven
Model R² = -0.49 · RMSE = 0.225 · trained on 288 days, held out 73.Note: R² < 0 means the model is barely better than predicting the mean.
What matters
Next 30 days
Mörrumsån
Model R² = -0.15 · RMSE = 0.146 · trained on 423 days, held out 106.Note: R² < 0 means the model is barely better than predicting the mean.
What matters
Next 30 days
Ätran
Model R² = -0.02 · RMSE = 0.363 · trained on 1,102 days, held out 276.Note: R² < 0 means the model is barely better than predicting the mean.
What matters
Next 30 days
Catch calendar (top 5 rivers)
Top 5 rivers by total catches: Ätran (4137), Mörrumsån (2110), Byskeälven (1270), Kalixälven (328), Lögdeälven (184)
- WhatWhen does each river peak across the season? Surfaces the seasonal timing pattern per river, year by year.
- DataTop 5 rivers by total catches (Ätran, Mörrumsån, Byskeälven, Kalixälven, Lögdeälven). One row per year, columns are ISO weeks 14–39 — the salmon season window.
- MethodPer (river × year × week), sum reported catches. Heatmap intensity scales against the per-river maximum so each river is comparable to itself across years.
Ätran
Mörrumsån
Byskeälven
Kalixälven
Lögdeälven
Show metric table (5 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Ätran | — | — | — | 4,137 | descriptive |
| Mörrumsån | — | — | — | 2,110 | descriptive |
| Byskeälven | — | — | — | 1,270 | descriptive |
| Kalixälven | — | — | — | 328 | descriptive |
| Lögdeälven | — | — | — | 184 | descriptive |
Catch rate by temperature bucket
Rows with temp + catch_rate present: 3,194 of 3,363
- WhatDoes air temperature affect catch rate? Tests the classic "13–16 °C is optimal" finding from Severn studies on Swedish rivers.
- Data3,175 fishery-days with both temperature and catch_rate. Buckets: cold / cool / optimal (13–16 °C) / warm / hot.
- MethodBucket each day by daily mean air temperature, then compare catch_rate distributions across buckets with Kruskal-Wallis (non-parametric — catch_rate is a heavily skewed 0–1 ratio).
Show metric table (1 test)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| global (temp bucket Kruskal) | 69.915 | 2.4e-14 | ✓ | 3,194 | small |
Catch rate by flow regime
Rows with flow_regime + catch_rate present: 1,110
- WhatDoes the amount of water moving through a river predict catches? Tests the "sweet spot" hypothesis around normal flow.
- Data1,092 fishery-days with paired flow regime + catch_rate. Each day classified by per-river flow percentiles (drought / low / normal / high / flood).
- MethodPer-river flow percentiles avoid one big river dominating the buckets. Kruskal-Wallis tests whether catch_rate distributions differ across regimes.
Show metric table (1 test)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| global (flow regime Kruskal) | 13.726 | 8.2e-3 | ✓ | 1,110 | negligible |
Pressure change (24 h) vs catch rate
Rows with Δp_24h + catch_rate: 3,130
- WhatThe folklore: pressure dropping = fish are biting. Test against real data per river.
- Data3,111 fishery-days with 24-hour pressure change and catch_rate. Top 3 rivers shown individually plus global summary.
- MethodPearson r between Δpressure_24h and catch_rate. 95% CI via Fisher z-transform. Each river tested independently — folklore could be local.
Show metric table (4 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| global | 0.002 | 9.2e-1 | ✗ | 3,130 | negligible |
| Ätran | 0.033 | 2.3e-1 | ✗ | 1,312 | negligible |
| Byskeälven | 0.012 | 7.4e-1 | ✗ | 686 | negligible |
| Mörrumsån | -0.003 | 9.5e-1 | ✗ | 459 | negligible |
Method (fly vs spin) × conditions
- WhatDo fly and spin anglers catch in different conditions? Tests whether method choice and weather are independent.
- Data4,998 reported catches with both method and temperature recorded (fly: 4,005 / spin: 993). Fly is the dominant method.
- MethodChi-square test of independence on the (method × temperature bucket) contingency table. Cramér's V scales the effect size.
Show metric table (1 test)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| method × temp bucket (chi-square) | 372.979 | 1.9e-79 | ✓ | 5,745 | medium |
Year-over-year catches (top 3 rivers)
- WhatWhere in the calendar does each river peak? Multi-year overlay shows whether peak timing is stable or drifts.
- DataAll catches 2021–2026 for top 3 rivers (Ätran, Mörrumsån, Byskeälven). Each year drawn as a separate line.
- MethodSum catches per day-of-year, smooth with a 7-day rolling mean to suppress noise. Display weeks 60–300 of the year (early March to late October) so off-season zeros don't flatten the curve.
Ätran YoY
Mörrumsån YoY
Byskeälven YoY
Show metric table (3 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Ätran YoY | — | — | — | 4,137 | descriptive |
| Mörrumsån YoY | — | — | — | 2,110 | descriptive |
| Byskeälven YoY | — | — | — | 1,270 | descriptive |
Migration vs catches (same day)
Aggregated (river, day) rows: 1,191
- WhatWhen a fish is counted at the migration camera, is it caught upstream the same day?
- Data1,187 (river, day) pairs across Ätran and Byskeälven — the two rivers where camera and fishery data overlap.
- MethodSpearman ρ (non-parametric, robust to outlier spike days) between same-day migration_count and caught_count totals per river.
Show metric table (2 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Byskeälven | -0.022 | 6.8e-1 | ✗ | 371 | negligible |
| Ätran | 0.255 | 1.2e-13 | ✓ | 820 | small |
Drivers of migration (Spearman)
Bars: green = positive ρ, red = negative. Annotation: *** p<0.001, ** p<0.01, * p<0.05, · n.s. Significance after BH-FDR correction is in findings.json.
- WhatWhich environmental signals correlate with migration count? Ranks candidate drivers per river.
- DataPer-river daily metrics × 12 candidate drivers (temperatures, flows, pressure, humidity, wind, clouds, precipitation, season position, moon phase). ~370–800 days per river.
- MethodSpearman ρ between each driver and migration_count, computed independently per river. Bars sorted by |ρ| so the strongest signal sits at the top.
Byskeälven
Ätran
Show metric table (23 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Byskeälven: pressure | -0.045 | 3.9e-1 | ✗ | 371 | negligible |
| Byskeälven: precipitation | 0.046 | 3.8e-1 | ✗ | 371 | negligible |
| Byskeälven: clouds | -0.046 | 3.7e-1 | ✗ | 371 | negligible |
| Byskeälven: flow (SMHI) | 0.068 | 3.4e-1 | ✗ | 198 | negligible |
| Byskeälven: Δpressure 24h | -0.078 | 1.3e-1 | ✗ | 371 | negligible |
| Byskeälven: flow (camera) | 0.090 | 8.3e-2 | ✗ | 371 | negligible |
| Byskeälven: humidity | -0.091 | 1.3e-1 | ✗ | 279 | negligible |
| Byskeälven: air temp (SMHI) | 0.102 | 4.9e-2 | ✗ | 371 | small |
| Byskeälven: moon phase | 0.158 | 2.3e-3 | ✓ | 371 | small |
| Byskeälven: wind speed | -0.167 | 1.3e-3 | ✓ | 371 | small |
| Byskeälven: water temp (camera) | 0.272 | 2.1e-7 | ✓ | 352 | small |
| Byskeälven: season position | -0.443 | 3.0e-19 | ✓ | 371 | medium |
| Ätran: moon phase | -0.008 | 8.1e-1 | ✗ | 820 | negligible |
| Ätran: Δpressure 24h | -0.039 | 2.7e-1 | ✗ | 791 | negligible |
| Ätran: wind speed | -0.067 | 6.8e-2 | ✗ | 742 | negligible |
| Ätran: flow (camera) | 0.092 | 8.8e-2 | ✗ | 342 | negligible |
| Ätran: clouds | 0.231 | 3.2e-11 | ✓ | 803 | small |
| Ätran: humidity | 0.253 | 3.8e-13 | ✓ | 803 | small |
| Ätran: pressure | -0.302 | 3.1e-18 | ✓ | 793 | medium |
| Ätran: precipitation | 0.303 | 2.3e-17 | ✓ | 749 | medium |
| Ätran: season position | 0.367 | 4.6e-27 | ✓ | 803 | medium |
| Ätran: water temp (camera) | 0.411 | 2.1e-26 | ✓ | 615 | medium |
| Ätran: air temp (SMHI) | 0.440 | 2.3e-39 | ✓ | 803 | medium |
Lag correlation: migration → catches
- WhatAfter a fish passes the camera, how many days before it reaches the fishery upstream? Cross-correlation by lag.
- DataPer-river paired daily totals (migration upstream + catches downstream), lag tested 0–14 days.
- MethodFor each lag N, compute Spearman ρ between today's catches and migration N days ago. Plot the curve.
Show metric table (30 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Byskeälven: lag 0d | -0.022 | 6.8e-1 | ✗ | 371 | |
| Byskeälven: lag 1d | -0.071 | 1.7e-1 | ✗ | 370 | |
| Byskeälven: lag 2d | -0.046 | 3.8e-1 | ✗ | 369 | |
| Byskeälven: lag 3d | -0.101 | 5.2e-2 | ✗ | 368 | |
| Byskeälven: lag 4d | -0.113 | 3.0e-2 | ✗ | 367 | |
| Byskeälven: lag 5d | -0.157 | 2.7e-3 | ✓ | 366 | |
| Byskeälven: lag 6d | -0.168 | 1.3e-3 | ✓ | 365 | |
| Byskeälven: lag 7d | -0.198 | 1.5e-4 | ✓ | 364 | |
| Byskeälven: lag 8d | -0.209 | 5.8e-5 | ✓ | 363 | |
| Byskeälven: lag 9d | -0.238 | 4.9e-6 | ✓ | 362 | |
| Byskeälven: lag 10d | -0.225 | 1.6e-5 | ✓ | 361 | |
| Byskeälven: lag 11d | -0.238 | 5.1e-6 | ✓ | 360 | |
| Byskeälven: lag 12d | -0.207 | 7.8e-5 | ✓ | 359 | |
| Byskeälven: lag 13d | -0.205 | 9.4e-5 | ✓ | 358 | |
| Byskeälven: lag 14d | -0.205 | 9.6e-5 | ✓ | 357 | |
| Ätran: lag 0d | 0.255 | 1.2e-13 | ✓ | 820 | |
| Ätran: lag 1d | 0.222 | 1.3e-10 | ✓ | 819 | |
| Ätran: lag 2d | 0.193 | 2.8e-8 | ✓ | 818 | |
| Ätran: lag 3d | 0.169 | 1.2e-6 | ✓ | 817 | |
| Ätran: lag 4d | 0.186 | 9.0e-8 | ✓ | 816 | |
| Ätran: lag 5d | 0.204 | 4.3e-9 | ✓ | 815 | |
| Ätran: lag 6d | 0.186 | 9.3e-8 | ✓ | 814 | |
| Ätran: lag 7d | 0.140 | 6.3e-5 | ✓ | 813 | |
| Ätran: lag 8d | 0.117 | 8.1e-4 | ✓ | 812 | |
| Ätran: lag 9d | 0.116 | 9.1e-4 | ✓ | 811 | |
| Ätran: lag 10d | 0.101 | 4.0e-3 | ✓ | 810 | |
| Ätran: lag 11d | 0.082 | 2.0e-2 | ✓ | 809 | |
| Ätran: lag 12d | 0.122 | 4.9e-4 | ✓ | 808 | |
| Ätran: lag 13d | 0.085 | 1.6e-2 | ✓ | 807 | |
| Ätran: lag 14d | 0.113 | 1.4e-3 | ✓ | 806 |
Seasonal totals YoY — migration vs catches
Camera counts cover the whole calendar year while catch reports are season-skewed — totals are comparable per river over time but the absolute migration/catch ratio is not a literal 'catch share'.
- WhatDo big-migration years coincide with big-catch years? Yearly totals comparison.
- DataCamera totals vs catch totals per (river, year). 5–6 years per river — small-n by design.
- MethodSpearman ρ on yearly totals. With ≤6 data points per river this is exploratory only — no robust statistical claim possible.
Byskeälven
Ätran
Show metric table (2 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Byskeälven | -0.500 | 3.9e-1 | ✗ | 5 | small-sample |
| Ätran | -0.200 | 7.0e-1 | ✗ | 6 | small-sample |
Wind direction × catches per river
Normalised by number of fishery-days per direction → corrects for wind prevalence bias. Proper head/tail/cross decomposition requires river flow orientation (geojson linestring) — deferred.
- WhatDo specific wind directions correlate with productive days per river?
- DataTop 3 rivers × 8 cardinal directions (N, NE, E, SE, S, SW, W, NW). Day-counts vary per direction per river.
- MethodNormalise catches by number of fishery-days in each direction (corrects for the prevalence bias — a common wind direction would otherwise dominate). Kruskal-Wallis tests whether the per-direction distribution differs.
Show metric table (3 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Ätran (wind dir Kruskal) | 5.673 | 5.8e-1 | ✗ | 1,224 | negligible |
| Mörrumsån (wind dir Kruskal) | 3.342 | 8.5e-1 | ✗ | 467 | negligible |
| Byskeälven (wind dir Kruskal) | 6.858 | 4.4e-1 | ✗ | 670 | negligible |
Moon phase distribution (catches + migration)
ephem.Moon.phase returns % illumination only — waxing and waning are not distinguished here. For tide-relevant analyses (Mörrum / Ätran estuaries) a full lunar-day model would be needed.
- WhatDo lunar phases line up with catch peaks? Especially relevant for sea trout and estuarial salmon.
- DataTop 4 rivers × moon phase buckets (new / waxing-waning / gibbous / full). ~150–1,400 fishery-days per river.
- MethodSpearman ρ between moon illumination (0–1) and catch_rate per river. Grouped bar chart for mean catches per (river × phase).
Show metric table (5 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Ätran | 0.003 | 9.2e-1 | ✗ | 1,378 | negligible |
| Mörrumsån | 0.054 | 2.1e-1 | ✗ | 529 | negligible |
| Byskeälven | 0.055 | 1.4e-1 | ✗ | 706 | negligible |
| Kalixälven | 0.002 | 9.8e-1 | ✗ | 165 | negligible |
| Moon phase × river (descriptive) | — | — | — | 8,067 | descriptive |
Precipitation as primary signal
Buckets: dry/light/medium/heavy. Lag-1 tests the 'fresh-water push' hypothesis: yesterday's rain triggers an upstream run today.
- WhatDoes rain trigger upstream runs? Test "fresh-water push" hypothesis — yesterday's rain → today's catch.
- Data~150–1,250 fishery-days per river with 24-hour precipitation totals. Buckets: dry / light / medium / heavy.
- MethodSpearman ρ on (precipitation vs catch_rate) at lag 0 (same day) and lag 1 (yesterday). Plus Kruskal-Wallis across rain buckets to check if heavy-rain days are systematically different.
Show metric table (12 tests)
| Test | r / H | p (raw) | BH-FDR | n | effect |
|---|---|---|---|---|---|
| Ätran (same-day) | 0.051 | 6.9e-2 | ✗ | 1,254 | negligible |
| Ätran (1-day lag) | 0.026 | 3.5e-1 | ✗ | 1,254 | negligible |
| Mörrumsån (same-day) | 0.058 | 2.1e-1 | ✗ | 464 | negligible |
| Mörrumsån (1-day lag) | -0.049 | 2.9e-1 | ✗ | 464 | negligible |
| Byskeälven (same-day) | -0.042 | 2.8e-1 | ✗ | 668 | negligible |
| Byskeälven (1-day lag) | -0.031 | 4.2e-1 | ✗ | 668 | negligible |
| Kalixälven (same-day) | 0.154 | 5.2e-2 | ✗ | 159 | small |
| Kalixälven (1-day lag) | 0.115 | 1.5e-1 | ✗ | 159 | small |
| Ätran (rain bucket Kruskal) | 8.173 | 4.3e-2 | ✗ | 1,257 | negligible |
| Mörrumsån (rain bucket Kruskal) | 2.207 | 5.3e-1 | ✗ | 466 | negligible |
| Byskeälven (rain bucket Kruskal) | 2.624 | 4.5e-1 | ✗ | 670 | negligible |
| Kalixälven (rain bucket Kruskal) | 5.910 | 1.2e-1 | ✗ | 160 | small |