Skip to content

frs_trace_downstream: FWA-averaged gradient hides localized barriers #187

@NewGraphEnvironment

Description

@NewGraphEnvironment

Problem

.frs_trace_downstream (fresh/R/frs_habitat.R:1364) traces downstream from origin points using whse_basemapping.fwa_downstreamtrace(), which returns FWA-original linear_feature_id rows with their feature-averaged gradients. Localized gradient barriers on a sub-piece of a long FWA feature (e.g. lake-outlet drops) are invisible to this trace, so the bridge_gradient check never fires on them.

.frs_connected_waterbody (used for SK lake-spawn proximity, fresh#147) calls .frs_trace_downstream for Phase 1. When a rearing lake's outlet is a steep drop within a longer flat FWA feature, the trace traverses past the drop without detecting a barrier, then Phase 3 promotes accessible spawn-eligible segments downstream up to distance_max.

Concrete case

Surfaced during link parity work, KISP SK spawning, 2026-04-30. Stream blue_line_key 360869584 (Kitwanga River) drains Kitwancool Lake (waterbody_key 329229702, area 780.6 ha, well above SK rear_lake_ha_min 200).

In fresh.streams (post-break):

DRM length_m gradient role
37,223+ 296+ 0 inside Kitwancool Lake (rearing)
37,216 7.4 0.8492 lake-outlet drop
36,578 ↓ 33,764 8 segments, 3,452 m total 0–0.02 downstream of lake outlet

In FWA-original (whse_basemapping.fwa_stream_networks_sp):

linear_feature_id DRM start length_m gradient
82056035 37,223 765.6 0
82058212 33,764 3,459.2 0.0084 (averaged)

fwa_downstreamtrace() returns FWA feature 82058212 with averaged gradient 0.0084 — the 7 m × 84.92% lake-outlet drop is hidden inside the longer feature's averaging. Bridge_gradient check passes, trace reaches all 8 fresh-broken segments at DRM 33,764–37,216.

bcfishpass's equivalent model/02_habitat_linear/sql/load_habitat_linear_sk.sql traces against bcfishpass.streams (post-break) — sees the localized 0.8492 segment as a barrier and stops. No spawning credited downstream of the lake outlet on this stream.

Verified on db_newgraph tunnel: bcfishpass.habitat_linear_sk shows spawning = NULL on segments DRM 33,764–37,216. Verified on local fwapg: whse_basemapping.fwa_downstreamtrace(360869584, 37223) returns linear_feature_id 82058212 with gradient = 0.0084.

Fix

Switch .frs_trace_downstream from the FWA-original iterator to a predicate join against the broken-streams table, following the same pattern already used by .frs_cluster_both phase 3 (fresh/R/frs_cluster.R:505–509):

# Current
FROM origins o
CROSS JOIN LATERAL whse_basemapping.fwa_downstreamtrace(
  o.blue_line_key, o.downstream_route_measure) t
WHERE t.blue_line_key = t.watershed_key
# Proposed (predicate against broken streams)
FROM origins o
INNER JOIN <table> t ON FWA_Downstream(
  o.blue_line_key, o.downstream_route_measure,
  o.wscode_ltree, o.localcode_ltree,
  t.blue_line_key, t.downstream_route_measure,
  t.wscode_ltree, t.localcode_ltree)
WHERE t.blue_line_key = t.watershed_key

Requires origins_sql to also yield wscode_ltree and localcode_ltree (currently only yields blue_line_key, downstream_route_measure). .frs_connected_waterbody's origins_sql (line 1469–1478) already pulls these from the streams table — small SELECT extension.

Related

  • fresh#186 (open) — .frs_cluster_both phase-1 + confluence-boost interaction. Different code path, different mechanism, same theme: bcfishpass parity on cluster connectivity.
  • fresh#147 (closed) — original .frs_connected_waterbody for SK/KO lake-proximity.
  • fresh#133 (closed) — connected_distance_max predicate.

Reproduction

Tunnel DB: bcfishpass on host localhost:63333 (db_newgraph, rebuilt Mondays). Local fwapg: localhost:5432. WSG: KISP. Species: SK. Stream: blue_line_key 360869584 (Kitwanga River). Lake: Kitwancool Lake waterbody_key 329229702. Affected fresh.streams DRM range: 33,764–37,216 (8 segments, 3.45 km of link_only SK spawning).

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