Skip to content

Research: calibrate CH and BT gradient and channel-width thresholds from observations #284

Description

@NewGraphEnvironment

If we do it: CH and BT habitat in the default_tuned bundle rests on measured fish distributions and cited literature, with a recorded verdict per threshold. If we never do: both species keep inherited bcfishpass cutoffs, and the size difference that separates them (big-river CH spawning vs small-stream BT) is represented only by spawn_channel_width_min 4 vs 2.

Status (2026-09-29): all six steps done, and BT 0.1349 is scored and held

The verdicts are in research/habitat_thresholds.md, including the Step 5 results.

  • Step 5 changed shape before it ran. A counts-only power check found the planned held-out set could decide one step of six (BT 10 / 1 / 0 and CH 0 / 1 / 2 locations in the bands). So:
    • BT was widened to eight held-out WSGs: ELKR, BULL, UARL, REVL, CLRH, LILL, BABL and BABR.
    • CH was dropped. Its verdicts stay "keep", unscored, because the data is too thin.
    • An underpowered step changes nothing (operator's calls, 2026-09-29).
  • Result. All three variants were built on one shared segmentation of the 23-WSG closure. The steps to 0.1349 add rearing that BT use at 0.60 and 0.71 of the core rate; at the same elevation that is 0.75 and 0.89. The step to 0.1449 falls to 0.32 (8 found where 25 were expected). default_tuned keeps 0.1349. Capture goes from 81.2 % to 84.2 % for 585 km more rearing (+5.7 %).
  • The floor question. The rule's n ≥ 10 counts locations found, and so cannot refuse a band fish avoid. A floor on locations expected at the core rate can. Both readings agree here, and the choice stays open.
  • Cutoffs vs weights. Use tapers with gradient and thins with elevation. So the discussion moved to weighting habitat instead of cutting it, biology first: NewGraphEnvironment/knowledge#28.

The earlier status and plan, kept for the record:

  • Step 5 plan (agreed 2026-09-26, run after Region-scoped DV→BT observation pooling, tracked in bundle CSVs #290):

    • Prepare each WSG once, then re-classify it per variant, so every variant shares its segmentation. default is re-run in the same harness: the existing fresh_default BULK is pre-BT/ST accessible_km over-credit: access segmentation drops the accessibility frontier #223, with 42,860 segments against 87,639.
    • Seven variants: default, default_tuned, BT rear 0.1249 and 0.1449, CH spawn 0.0549 and 0.0299, and CH rear 0.0649.
    • WSGs: BT is read on ELKR and BULL (held out), with PARS, KOTL, BULK and MORR in-sample. CH is read on UNTH and LNTH (held out), with BULK and MORR in-sample.
    • Rule, fixed before the runs: the marginal band is habitat when its observation density per km is ≥ 0.5× the incumbent's. It is read on held-out WSGs and needs n ≥ 10, else keep. The literature veto stands.
    • Everything is species-agnostic: variants, WSG roles and absence taxa are data.
  • One value moves: BT rear_gradient_max 0.1049 → 0.1349, in default_tuned (high confidence: BT and DV records pooled, n 4,764 accessible, P95 0.135; Isaak et al. 2015's 15 % natal envelope agrees). BT records alone give 0.1249, and both are recorded. Every other CH/BT gradient maximum and width minimum is kept, as are spawn_gradient_min (CH spawning selects the flattest bin, ratio 2.8) and the bridge (1.2 % of BT observations lost to clustering). So default_tuned still inherits parameters_fresh.csv.

  • Vetoed by the literature: CH spawning width 6.6 m (Cooney & Holzer, Busch and Woll all put the minimum at 3.6–4 m).

  • Changed after the numbers were seen: restricting use to accessible segments moved three verdicts (CH spawning 0.0549 → keep, CH rearing 0.0649 → keep, BT rearing 0.1349 → 0.1249, before pooling brought BT back to 0.1349). Scoring should test the retired CH values too.

  • Coverage is not interior-only: about a third of the CH locations are in the lower Fraser and coastal Skeena, where ocean-type runs occur. The CH rearing verdict is sensitive to the gradient measure: the 100 m window gradient would give 0.0649 rather than keep.

  • BT and DV are pooled. Inland, DV records are bull trout recorded under the other name; on the coast either occurs, and their habitat biology is treated as equivalent. BT has no life stage anywhere in bcfishobs, so the staged evidence is the DV records. With full confidence the rule would loosen BT spawning gradient (0.1949) and width (1.2 m); the literature vetoes both.

  • Step 2 route: the FISS data-submission parse in knowledge (per-site width, gradient, effort, no-fish-captured) covers COTR, LNTH, PINE, UNTH and UPCE. Modelled width is good to about −30 % / +55 % of measured.

Problem

Current values (fresh parameters_habitat_thresholds.csv; link default/parameters_fresh.csv):

spawn gradient max spawn cw min rear gradient max rear cw min MAD access gradient max
CH 0.0449 4 0.0549 1.5 spawn ≥ 0.46, rear 0.28–100 (unused: no WSG uses the mad method and streams carry no mad_m3s — fresh#114) 0.15
BT 0.0549 2 0.1049 1.5 — 0.25

Rearing-to-spawning connection is identical for both (cluster_rearing = TRUE, direction both, cluster_bridge_gradient 0.05, cluster_bridge_distance 10000). In fresh's .frs_cluster_both(), a rearing cluster is kept if spawning lies anywhere upstream of it, with no gradient test. Failing that, it is kept if a downstream trace reaches spawning within 10 km through reaches under the bridge gradient. So the 5 % bridge governs only rearing that sits above spawning. (Corrected 2026-09-26: this previously said steep BT rearing "only survives with spawning upstream of it", which leaves out the downstream route.)

Channel width is mostly modelled: on the local fresh.streams, 1.38 M segments modelled, 98.5 k field-measured, 90 k river polygons and 2.19 M NULL. NULL fails every width test, and order-1 streams are NULL (fresh#28), which likely removes BT headwater rearing wholesale. (Measured 2026-09-26: 49 % of accessible BT stream length in fresh_default has NULL width, while 4 % of BT observations on those streams sit there, a selection ratio of 0.08. That does not separate under-sampling of headwaters from absence.)

Proposed Solution

  1. Empirical distributions. For CH and BT, join bcfishobs.observations (after observation_exclusions; release records removed) to segments. Plot gradient and channel width at observation points by life stage where known, by region, against the current cutoffs. Use measured channel width where it exists, and report modelled vs measured separately.
  2. Site-level evidence. Add per-site measured width/gradient, effort, absences and fish size from FISS data submissions as an input table, to separate adult (spawning) from juvenile (rearing) evidence, especially for BT, where the provincial layer has no life stage. (Fish size is not parsed yet: the knowledge parse covers site, collection and habitat sheets, not individual fish.)
  3. Literature. One cited value or range per threshold, including CH stream-type vs ocean-type and BT life-history forms.
  4. Candidates. Set values in the default_tuned bundle (per-bundle thresholds, Per-bundle habitat thresholds CSV in config.yaml #282) for spawn/rear gradient max, channel width min, spawn_gradient_min (see the reverted 0.0025 floor in research/default_vs_bcfishpass.md), and BT cluster_bridge_gradient.
  5. Score. Run default and default_tuned on pilot WSGs with both species present and good sampling, then compare with the observation validation (Validate modelled habitat against fish observations per species and watershed group #283).
  6. Verdict in research/habitat_thresholds.md, revised in place per species.

Out of scope here: MAD (fresh#114), temperature/GSDD (#21), channel-class segmentation (#52).

Relates to #20, #282, #283

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions