
Classify rearing on direct children of large-order streams
Source:R/frs_order_child.R
frs_order_child.RdPost-classification update that adds a habitat label (default
rearing) to segments on direct tributaries of large-order rivers,
optionally distance-capped from the confluence. Runs after
frs_habitat_classify() (and any post-classify step like
frs_cluster()); is additive, idempotent, and never overrides
segments above an inaccessible barrier.
Usage
frs_order_child(
conn,
table,
habitat,
species,
label = "rearing",
parent_order_min = 5L,
child_order_min = NULL,
child_order_max = NULL,
distance_max = NULL,
channel_width_max = NULL,
gradient_max = NULL,
verbose = TRUE
)Arguments
- conn
DBI connection.
- table
Character. Schema-qualified streams table (e.g.
"fresh.streams").- habitat
Character. Schema-qualified habitat table (e.g.
"fresh.streams_habitat").- species
Character. Species code (e.g.
"BT").- label
Character. Habitat-table column to set TRUE. Default
"rearing". Generic on the column name — pass"lake_rearing","wetland_rearing", or any custom boolean column when biology supports it.- parent_order_min
Integer. Minimum parent stream order for a direct-child segment to qualify. Default
5L(matches bcfishpass's hard-coded value).- child_order_min
Integer or
NULL. If set, segment'sstream_ordermust be>= child_order_min. DefaultNULL. When bothchild_order_minandchild_order_maxareNULL, both default to1L(matches bcfishpass'sstream_order = 1predicate).- child_order_max
Integer or
NULL. If set, segment'sstream_ordermust be<= child_order_max. DefaultNULL. When bothchild_order_minandchild_order_maxareNULL, both default to1L(matches bcfishpass'sstream_order = 1predicate).- distance_max
Numeric or
NULL. If set, segment'sdownstream_route_measuremust be<= distance_max(metres from tributary mouth). DefaultNULL(whole tributary).- channel_width_max
Numeric or
NULL. If set, a segment'schannel_widthmust be known and at most this value (metres). Pass the species' rearing width minimum to admit the lines the width minimum turned away, as bcfishpass does. A segment with no width is never admitted. DefaultNULL(no width test).- gradient_max
Numeric or
NULL. If set, a segment'sgradientmust be at most this value (a proportion, as ingradient). Pass the species' rearing gradient maximum. DefaultNULL(no gradient test).- verbose
Logical. Print before/after counts. Default
TRUE.
Why this exists
Small streams flowing directly into mainstem rivers support juvenile rearing even when the FWA-measured channel width is below the species threshold. The parent river supplies flow, temperature, access; cool tributary water mixes at the confluence; backwater / off-channel habitat near the mouth is high-value. Channel-width measurement on the small tributary doesn't reflect this reality.
bcfishpass models this with a hard-coded predicate
cw.channel_width >= rear_channel_width_min OR (s.stream_order_parent >= 5 AND s.stream_order = 1) (per BT/CH/CO/
ST/WCT rear SQL in
model/02_habitat_linear/sql/load_habitat_linear_<sp>.sql). This
function exposes the same biology as a parametric post-classification
rule, so callers can tune parent_order_min, child_order_min/max,
and distance_max without touching the rule grammar.
In bcfishpass the exception sits inside the rest of the rearing test:
s.gradient <= rear_gradient_max AND cw.channel_width <= rear_channel_width_max AND (cw.channel_width >= rear_channel_width_min OR (s.stream_order_parent >= 5 AND s.stream_order = 1))
(smnorris/bcfishpass@7f444f1b,
model/02_habitat_linear/sql/load_habitat_linear_bt.sql:88-97). So a
line with no width never qualifies (NULL <= max is not true), and a
line steeper than the rearing maximum never rears. Pass
channel_width_max (the species' rearing width minimum) and
gradient_max (its rearing gradient maximum) to apply those two tests:
the first admits only lines with a known width at most the value.
bcfishpass tests below the minimum (<); a line at exactly the minimum
also passes the ordinary rule's width test, so the two differ only on a
line the ordinary rule does not cover. Pass a smaller value for a strict
test. Left
NULL, neither test applies and every direct child is admitted whatever
its width or gradient.
This function does not reproduce bcfishpass's exception on its own. What it leaves to the caller, or does differently:
Model. The exception sits in bcfishpass's channel-width branch only, so a group modelled on discharge (
mad) never takes it: call this only for groups oncw.Spawning and connectivity. bcfishpass's exception rows still pass the spawning and connectivity conditions of their rearing block; this function runs after classification and clustering and tests neither.
Waterbody and edge type. Every CH, CO, ST and WCT rearing block that carries the exception also filters by waterbody and edge type, in one of three forms; BT's blocks have none. Let
Ebe edge types 1000, 1100, 2000 and 2300.CH (all three blocks) and WCT's first: a river polygon, or no waterbody and an edge type in
E(load_habitat_linear_ch.sql:89-92).ST (all three) and WCT's second and third: a river polygon, or no waterbody, or an edge type in
E(load_habitat_linear_st.sql:88-90).CO (all three): as ST, with 1050 and 1150 added to
E(load_habitat_linear_co.sql:89-92); its first two blocks also rear every 1050 and 1150 line with no width test.
This function tests no edge or waterbody type, so for CH, CO, ST and WCT it also admits the direct children these filters turn away.
Direct child. bcfishpass has no
stream_order = stream_order_maxtest (itsstream_order_parentis perblue_line_key), so it also admits order-1 headwater reaches of higher-order lines that drain to a large river. This function leaves those out on purpose (fresh#158).
Direct-child semantics
A "direct child" of a large river is a segment that satisfies all of:
stream_order = stream_order_max(per blue_line_key). The segment is on the mouth-side reach of its BLK — the part where the BLK has reached its final, maximum order. Tributaries joining upstream may push the BLK to a higher order at lower DRM, but the headwater portions (where the BLK is still at a smaller order before any tribs join) are excluded. Without this filter, a multi-order BLK like a named creek that grows from order-1 headwaters to order-3 mouth would have its order-1 headwater reaches credited even though they are not the "direct trib" of a large parent — they are just upstream of one.stream_order_parent >= parent_order_min. The receiving stream at the BLK's first downstream confluence is at least the threshold order (default 5L = bcfp's hardcoded value).stream_orderbetweenchild_order_minandchild_order_max(defaults to 1L for both). Restricts the child trib's own order. Default 1L matches bcfishpass.
stream_order_max is computed on the fly via window function over
the table argument: MAX(stream_order) OVER (PARTITION BY blue_line_key).
fresh's streams table doesn't store this column; bcfp's
bcfishpass.streams does, but the value is the same.
Distance grain
distance_max filters on the segment's start measure
(downstream_route_measure). The grain of FWA segmentation
determines what gets captured at the boundary — segments straddling
the cap are kept (whole-segment-in, biology-conservative
overshoot). Documented as a tradeoff in fresh#158; alternate exact
break + filter approaches are out of scope here.
SQL emitted
WITH s AS (
SELECT *,
MAX(stream_order) OVER (PARTITION BY blue_line_key) AS stream_order_max
FROM <table>
)
UPDATE <habitat>
SET <label> = TRUE
FROM s
WHERE <habitat>.id_segment = s.id_segment
AND <habitat>.species_code = '<species>'
AND <habitat>.accessible = TRUE
AND <habitat>.<label> IS NOT TRUE
AND s.stream_order = s.stream_order_max
AND s.stream_order_parent >= <parent_order_min>
AND s.stream_order >= <child_order_min> -- default 1 if both NULL
AND s.stream_order <= <child_order_max> -- default 1 if both NULL
[AND s.downstream_route_measure <= <distance_max>]
[AND s.channel_width IS NOT NULL AND s.channel_width <= <channel_width_max>]
[AND s.gradient <= <gradient_max>]Bracketed clauses are emitted only when the corresponding parameter is non-NULL.
Examples
if (FALSE) { # \dontrun{
conn <- frs_db_conn()
# Direct children of order-5+ rivers, no distance cap, no width or
# gradient test, for BT/CH/CO/ST/WCT.
for (sp in c("BT", "CH", "CO", "ST", "WCT")) {
frs_order_child(conn, "fresh.streams", "fresh.streams_habitat",
species = sp)
}
# Distance-capped: only the lower 300 m of each direct-child trib.
frs_order_child(conn, "fresh.streams", "fresh.streams_habitat",
species = "BT", distance_max = 300)
# bcfishpass's width and gradient tests, in a channel-width group: only
# lines whose known width is at most BT's rearing minimum and whose
# gradient is within its rearing maximum.
frs_order_child(conn, "fresh.streams", "fresh.streams_habitat",
species = "BT", channel_width_max = 1.5, gradient_max = 0.1049)
# Restrict to 3rd-order-and-above direct children of major rivers.
frs_order_child(conn, "fresh.streams", "fresh.streams_habitat",
species = "BT", child_order_min = 3)
} # }