Skip to content

Multi-class gradient barrier detection in single pass (match bcfishpass v0.5.0) #127

@NewGraphEnvironment

Description

@NewGraphEnvironment

Problem

fresh 0.12.5 runs frs_break_find separately for each gradient threshold (15%, 20%, 25%, 30%). Each run does its own vertex sampling and island detection with a boolean above/below grouping. This misses class transitions WITHIN a steep section — a section going 12%→18%→25% is one island at threshold=15%, so only one barrier is placed at the downstream entry. The 25% transition point is lost.

bcfishpass v0.5.0 gradient_barriers_load.sql does one pass, tags every vertex with its gradient class (5, 7, 10, 12, 15, 20, 25, 30), and creates separate islands per class. Class transitions within a steep section produce separate barriers. This is biologically correct — the point where gradient jumps from 15% to 25% matters because CH is blocked at 15% but BT passes through to 25%.

Result: bcfishpass generates 7,136 gradient_15 barriers for ADMS. fresh generates 5,571 (found) / 4,229 (in breaks). The missing barriers are at class transitions within steep sections.

Impact

Different barrier counts → different break points → different segments → different channel width coverage on accessible segments → -23% CH spawning gap vs bcfishpass v0.5.0 (link 0.0.0.9000 ADMS comparison).

Proposed Solution

Change frs_break_find to use bcfishpass's multi-class approach:

  1. One pass: sample gradient at every FWA vertex over 100m upstream window (same as now)
  2. Tag classes: assign each vertex to a gradient class (5, 7, 10, 12, 15, 20, 25, 30) instead of boolean above/below
  3. Island detection per class: group consecutive same-class vertices, place one barrier at the downstream entry of each class island
  4. Output: all barriers in one table with a gradient_class column

frs_habitat() then filters by species access threshold — BT uses 25+30, CH/CO/SK use 15+20+25+30.

The breaks_gradient parameter on frs_habitat() becomes the list of classes to generate (default all 8), not the list of thresholds to run separately.

Key SQL difference

Current fresh (boolean):

lag(above) OVER (...) IS DISTINCT FROM above AS step

bcfishpass (class-based):

lag(grade_class) OVER (...) <> grade_class AS step

Additional bcfishpass filter to match

bcfishpass line 22: AND blue_line_key = watershed_key — only samples main flow lines, excludes 382 of 11,520 ADMS segments (secondary/side channels). Minor impact but should be a parameter for exact matching.

Versions

  • fresh: 0.12.5
  • bcfishpass: v0.5.0
  • link: 0.0.0.9000
  • fwapg: Docker local (FWA 20240830)

Relates to NewGraphEnvironment/link#16
Relates to #124

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