You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If done: a mad watershed group keeps stream habitat for every modelled species, on
discharge windows set from evidence. If never: any group moved to mad loses all
stream spawning and rearing for BT, GR, KO and RB by construction. That is not a finding
about the fish. Only waterbody rules (wetlands, lakes, the 1050/1150 edges) keep them.
Problem
parameters_habitat_thresholds.csv carries spawn_mad_* for CH, CM, CO, PK, SK, ST and
WCT, and rear_mad_* for CH, CO, ST and WCT only (default, default_tuned and bcfishpass alike). The gap was inherited from bcfishpass example_newgraph. Under
the mad model, fresh writes FALSE in place of the size test for a species with no
range, as bcfishpass does. Since #299, lnk_habitat_validate() names a miss the missing
range alone explains no_mad_threshold. Misses from the same cause also read width_null (no discharge on the line) or fails_gradient_and_width (gradient fails
too), so that label is a floor on the loss, not a count of it. On ADMS on mad, 27 BT
locations read it against spawning and 8 more read fails_gradient_and_width
(data-raw/logs/habitat_validate_299/). The operator's direction (2026-10-02, #299 plan gate): tune and add the thresholds, rather than leave them missing in the long
run.
Literature and FISS for each species' discharge range, recorded in research/habitat_thresholds.md as one verdict per threshold.
Land the values in default_tuned (a thin bundle) first, scored out-of-sample with lnk_habitat_validate_band(). default stays untouched until a score supports a move.
Score before/after with capture and cost (share_*, *_km) and lnk_habitat_validate_band(), not with no_mad_threshold. Once a range exists, the
label cannot fire, so its "after" is 0 whatever the value.
Depends on #299. Relates to #284, #286, #300. As built: the mad scoring harness #300 needed was built here (operator's call at the plan gate), so #300 can reuse it.
Landed in default_tuned (m³/s, maxima open): BT 0.078 spawn and rear, GR 0.96
spawn / 0.97 rear, RB 0.011 spawn / 0.019 rear, and KO 0.57 spawn, unscored (no
held-out group). They are inert while every group is on cw; default is untouched.
Scoring: a rule fixed before the build (expected-count floor). Every P10 → P05
loosening was refused on the held-out groups except RB spawning, so the landed values
are the P10 rungs, not the P05 candidates.
Cost before moving any group to mad: at least −33 % BT and −82 % GR stream
rearing against cw on the held-out groups. Stream size and sampling effort are not
separated; a size-stratified core is the next tuning.
If done: a
madwatershed group keeps stream habitat for every modelled species, ondischarge windows set from evidence. If never: any group moved to
madloses allstream spawning and rearing for BT, GR, KO and RB by construction. That is not a finding
about the fish. Only waterbody rules (wetlands, lakes, the 1050/1150 edges) keep them.
Problem
parameters_habitat_thresholds.csvcarriesspawn_mad_*for CH, CM, CO, PK, SK, ST andWCT, and
rear_mad_*for CH, CO, ST and WCT only (default,default_tunedandbcfishpassalike). The gap was inherited from bcfishpassexample_newgraph. Underthe
madmodel, fresh writesFALSEin place of the size test for a species with norange, as bcfishpass does. Since #299,
lnk_habitat_validate()names a miss the missingrange alone explains
no_mad_threshold. Misses from the same cause also readwidth_null(no discharge on the line) orfails_gradient_and_width(gradient failstoo), so that label is a floor on the loss, not a count of it. On ADMS on
mad, 27 BTlocations read it against spawning and 8 more read
fails_gradient_and_width(
data-raw/logs/habitat_validate_299/). The operator's direction (2026-10-02,#299 plan gate): tune and add the thresholds, rather than leave them missing in the long
run.
Proposed Solution
mad_m3sat BT / GR / KO / RB observationlocations by stage (pooled DV per
species_pooling.csv), alongside accessibleavailability. This is the Research: calibrate CH and BT gradient and channel-width thresholds from observations #284 method with discharge in place of width. As built:
measured on the 46 discharge-covered
fresh_defaultgroups (calibration), not onScore the discharge (mad) habitat model against observations, as #284 did for gradient #300's held-out groups, so that the score could stay out-of-sample.
research/habitat_thresholds.mdas one verdict per threshold.default_tuned(a thin bundle) first, scored out-of-sample withlnk_habitat_validate_band().defaultstays untouched until a score supports a move.share_*,*_km) andlnk_habitat_validate_band(), not withno_mad_threshold. Once a range exists, thelabel cannot fire, so its "after" is 0 whatever the value.
Depends on #299. Relates to #284, #286, #300. As built: the
madscoring harness#300 needed was built here (operator's call at the plan gate), so #300 can reuse it.
Outcome (2026-10-02, PR #303)
default_tuned(m³/s, maxima open): BT 0.078 spawn and rear, GR 0.96spawn / 0.97 rear, RB 0.011 spawn / 0.019 rear, and KO 0.57 spawn, unscored (no
held-out group). They are inert while every group is on
cw;defaultis untouched.loosening was refused on the held-out groups except RB spawning, so the landed values
are the P10 rungs, not the P05 candidates.
mad: at least −33 % BT and −82 % GR streamrearing against
cwon the held-out groups. Stream size and sampling effort are notseparated; a size-stratified core is the next tuning.
research/habitat_thresholds.md, "MAD (discharge) ranges for BT,GR, KO and RB (Tune MAD (discharge) thresholds for BT, GR, KO and RB rather than leave them missing #302)"; archive
planning/archive/2026-10-issue-302-mad-thresholds/.