
Estimate Channel Width from a Bankfull Regression
Source:R/frs_channel_width.R
frs_channel_width.RdWrite a channel width predicted from upstream drainage area and mean
annual precipitation onto a working table, via SQL UPDATE. By default
it fills only rows where the target column is NULL. That gives every
segment with both inputs a width, including the first-order streams that
fwa_stream_networks_channel_width leaves NULL, while leaving measured
and mapped widths alone. FWA placeholder (999) and unmapped segments
have no upstream area, so they stay NULL unless value is given. Point to at a new column instead to get an
independent estimate to compare against existing widths.
Usage
frs_channel_width(
conn,
table,
model = "poisson2021",
to = "channel_width",
col_area = "upstream_area_ha",
col_precip = "map_upstream",
col_source = paste0(to, "_source"),
overwrite = FALSE,
value = NULL,
verbose = TRUE
)Arguments
- conn
A DBI::DBIConnection object (from
frs_db_conn()).- table
Character. Schema-qualified working table to update.
- model
Regression to apply.
"poisson2021"(default),"hall2007", or a named list of coefficients for a custom power law (see Details).- to
Character. Column to write. Added as
double precisionif missing. Default"channel_width".- col_area
Character. Upstream drainage area column, in hectares. Default
"upstream_area_ha".- col_precip
Character. Mean annual precipitation column, in millimetres. Default
"map_upstream".- col_source
Character or
NULL. Column labelling which rows this call wrote, added astextif missing. Default"<to>_source", so a comparison column (to = "channel_width_hall") never relabelschannel_width_source.NULLwrites no label.- overwrite
Logical.
FALSE(default) writes only rows wheretoisNULL.TRUErewrites every row: the regression where its inputs allow,NULLelsewhere.- value
Numeric or
NULL. A width (m) for rows stillNULLafter the regression, labelledASSIGNED: typically segments with no upstream area, such as FWA placeholder and unmapped lines. DefaultNULLleaves themNULL.- verbose
Logical. Report how many rows were modelled, assigned and left
NULL. DefaultTRUE.
Details
The function reads columns that must already be on table. It does no
network-specific joins. For FWA networks, add them with frs_col_join()
(see Examples).
Every model is one power law:
"poisson2021"Thorley and Irvine (2021b), Poisson Consulting. The model behind the
MODELLEDwidths infwa_stream_networks_channel_width(fwapgextras/channel_width/sql/channel_width_modelled.sql):k = exp(0.30713),a = b = 0.4577882,a_div = 100,p_div = 1000,a_off = p_off = 1, rounded to 2 decimals. LabelMODELLED_POISSON2021."hall2007"The bankfull width regression of the Valley Confinement Algorithm (Hall et al. 2007), as used by flooded:
(area_km2 ^ 0.280) * 0.196 * (precip_cm ^ 0.355). Herek = 0.196,a = 0.280,b = 0.355,a_div = 100(ha to km2),p_div = 10(mm to cm), no offsets, no rounding. It runs below poisson2021 except on small catchments, where the crossover depends on precipitation: about 65 ha at 100 mm, 16 ha at 1000 mm and 5 ha at 4000 mm. LabelMODELLED_HALL2007.- custom
A named list with numeric
k,a,b,a_div,p_div,a_off,p_off, and optionallydigits(rounding). LabelMODELLED_CUSTOM.
A row is written only where both area + a_off and precip + p_off
are positive, so rows with a NULL input stay NULL. With poisson2021's
offset of 1, an input of 0 is still written. Unlike fwapg, a NULL
precipitation is not treated as 0.
Matching fwapg. fwapg computes MODELLED once per
wscode_ltree / localcode_ltree pair, from the largest upstream area
among that pair's watershed polygons. So every segment on a reach gets the
width at its downstream end. To reproduce it, join that group maximum as
the area column (second example). On the Bulkley group, that join
puts 94% of MODELLED rows within 5%, against about 10% for each
segment's own area.
See also
Other habitat:
frs_aggregate(),
frs_break(),
frs_break_apply(),
frs_break_find(),
frs_break_validate(),
frs_categorize(),
frs_classify(),
frs_cluster(),
frs_col_generate(),
frs_col_join(),
frs_extract(),
frs_feature_find(),
frs_feature_index(),
frs_habitat(),
frs_habitat_access(),
frs_habitat_classify(),
frs_habitat_overlay(),
frs_habitat_partition(),
frs_habitat_predicates(),
frs_habitat_species(),
frs_near_river(),
frs_network_segment()
Examples
if (FALSE) { # \dontrun{
conn <- frs_db_conn()
# Inputs: upstream area (ha) and mean annual precipitation (mm)
conn |>
frs_col_join("working.streams",
from = "(SELECT l.linear_feature_id, ua.upstream_area_ha
FROM fwa_streams_watersheds_lut l
JOIN fwa_watersheds_upstream_area ua
ON l.watershed_feature_id = ua.watershed_feature_id)",
cols = "upstream_area_ha",
by = "linear_feature_id") |>
frs_col_join("working.streams",
from = "fwa_stream_networks_mean_annual_precip",
cols = "map_upstream",
by = c("wscode_ltree", "localcode_ltree"))
# Fill NULL widths (first-order streams), 0.5 m where inputs are missing
conn |>
frs_channel_width("working.streams", value = 0.5)
# Independent estimates alongside the existing widths
conn |>
frs_channel_width("working.streams", to = "channel_width_poisson") |>
frs_channel_width("working.streams", model = "hall2007",
to = "channel_width_hall")
# fwapg-matching area: the largest upstream area per watershed-code pair
conn |>
frs_col_join("working.streams",
from = "(SELECT s.wscode_ltree, s.localcode_ltree,
max(ua.upstream_area_ha) AS upstream_area_ha
FROM fwa_stream_networks_sp s
JOIN fwa_streams_watersheds_lut l
ON s.linear_feature_id = l.linear_feature_id
JOIN fwa_watersheds_upstream_area ua
ON l.watershed_feature_id = ua.watershed_feature_id
-- the watershed group(s) your table covers
WHERE s.watershed_group_code = 'BULK'
GROUP BY s.wscode_ltree, s.localcode_ltree)",
cols = "upstream_area_ha",
by = c("wscode_ltree", "localcode_ltree"))
DBI::dbDisconnect(conn)
} # }