| Title: | Catch Advice for Data-Limited Vertebrate and Invertebrate Fisheries Managed by Harvest Slot Limits |
|---|---|
| Description: | Catch advice for data-limited vertebrate and invertebrate fisheries managed by harvest slot limits using the 'SlotLim' harvest control rule. The package accompanies the manuscript 'SlotLim: catch advice for data-limited vertebrate and invertebrate fisheries managed by harvest slot limits' (Pritchard et al., in prep). Minimum data requirements: at least two consecutive years of catch data, length–frequency distributions, and biomass or abundance indices (all from fishery-dependent sources); species-specific growth rate parameters (either von Bertalanffy, Gompertz, or Schnute); and either the natural mortality rate ('M') or the maximum observed age ('tmax'), from which M is estimated. The following functions have optional plotting capabilities that require 'ggplot2' installed: 'prop_target', 'TBA', 'SAM', 'catch_advice', 'catch_adjust', and 'slotlim_once'. |
| Authors: | C.J. Pritchard [aut, cre] (ORCID: <https://orcid.org/0000-0001-7093-6785>) |
| Maintainer: | C.J. Pritchard <[email protected]> |
| License: | GPL-3 |
| Version: | 0.0.2 |
| Built: | 2026-05-21 06:22:05 UTC |
| Source: | https://github.com/slotlim/slotlim |
Calculates the targeted proportions under historical (old) and proposed (new)
harvest slot limits using the same survivorship-by-length framework as
prop_target. The ratio ("catch adjustment") is returned, and (optionally)
a historical catch value is scaled by the adjustment. The optional plot overlays old/new
in-slot proportions on the normalized survivorship curve with arrows
indicating the direction of change (old → new).
catch_adjust( old_minLS = NULL, old_maxLS = NULL, old_Lc = NULL, new_minLS = NULL, new_maxLS = NULL, new_Lc = NULL, catch = NULL, M = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, Lmin = NULL, plot = FALSE, length_units = NULL )catch_adjust( old_minLS = NULL, old_maxLS = NULL, old_Lc = NULL, new_minLS = NULL, new_maxLS = NULL, new_Lc = NULL, catch = NULL, M = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, Lmin = NULL, plot = FALSE, length_units = NULL )
old_minLS, old_maxLS, old_Lc
|
Numeric. Historical slot limits and length at first capture. |
new_minLS, new_maxLS, new_Lc
|
Numeric. New slot limits and length at first capture. If
|
catch |
Optional numeric. Historical catch to be adjusted. If provided,
|
M |
Numeric or |
growth_model |
One of |
Linf, K, l0
|
von Bertalanffy parameters; |
tmax |
Numeric. The maximum observed age used to bound the integrals via |
Gom_Linf, Gom_K, Gom_l0
|
Gompertz parameters; requires |
g1, g2, l2
|
Schnute parameters; |
Lmin |
Optional numeric. Lower bound for the curve grid. If |
plot |
Logical. If |
length_units |
Optional character scalar. Units to show in the x-axis
label when |
If plot = FALSE (default): a numeric scalar adjust_factor = prop_new/prop_old.
If plot = TRUE: a list with
prop_old, prop_new — targeted proportions under old/new slots,
adjust_factor — prop_new/prop_old,
adjusted_catch — only if catch provided,
plot — the ggplot2 object (or NULL if ggplot2 is unavailable).
# numeric only catch_adjust(old_minLS = 130, old_maxLS = 280, old_Lc = 80, new_minLS = 100, new_maxLS = 240, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34) # with plot (requires ggplot2) catch_adjust(old_minLS = 130, old_maxLS = 280, old_Lc = 80, new_minLS = 100, new_maxLS = 240, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, plot = TRUE, length_units = "mm") # note that overlapping portions stray from color in legend due to alpha value catch_adjust(old_minLS = 100, old_maxLS = 150, old_Lc = 80, new_minLS = 160, new_maxLS = 300, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, plot = TRUE, length_units = "mm")# numeric only catch_adjust(old_minLS = 130, old_maxLS = 280, old_Lc = 80, new_minLS = 100, new_maxLS = 240, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34) # with plot (requires ggplot2) catch_adjust(old_minLS = 130, old_maxLS = 280, old_Lc = 80, new_minLS = 100, new_maxLS = 240, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, plot = TRUE, length_units = "mm") # note that overlapping portions stray from color in legend due to alpha value catch_adjust(old_minLS = 100, old_maxLS = 150, old_Lc = 80, new_minLS = 160, new_maxLS = 300, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, plot = TRUE, length_units = "mm")
Calculates the advised catch using the SlotLim framework and (optionally) returns
a plot of the percentage change relative to Cy across a grid of
(TBA, SAM) values, with the output overlaid.
catch_advice( Cy = NULL, TBA = NULL, SAM = NULL, T1 = NULL, T2 = NULL, plot = FALSE )catch_advice( Cy = NULL, TBA = NULL, SAM = NULL, T1 = NULL, T2 = NULL, plot = FALSE )
Cy |
Numeric (length 1) > 0. Most recent annual catch, or multi-year average.
If landing size restrictions have changed, use |
TBA |
Numeric (length 1) > 0. Targeted Biomass Adjustment (see |
SAM |
Numeric (length 1) > 0. Size Adherence Multiplier (see |
T1 |
Optional numeric (length 1) in (0,1). Maximum allowed proportional
decrease. If |
T2 |
Optional numeric (length 1) in (0,1). Maximum allowed proportional
increase. If |
plot |
Logical. If |
Ay: Catch advice (same units as Cy).
Ay_percent: Percent change of advice relative to Cy.
plot: (only when plot = TRUE) a ggplot2 object
visualizing percent change across .
Cy <- 1000; TBA <- 1.1; SAM <- 0.9 catch_advice(Cy, TBA, SAM) # compute only catch_advice(Cy, TBA, SAM, plot = TRUE) catch_advice(Cy, TBA, SAM, T1 = 0.2, T2 = 0.2, plot = TRUE)Cy <- 1000; TBA <- 1.1; SAM <- 0.9 catch_advice(Cy, TBA, SAM) # compute only catch_advice(Cy, TBA, SAM, plot = TRUE) catch_advice(Cy, TBA, SAM, T1 = 0.2, T2 = 0.2, plot = TRUE)
Calculates specified percentiles from length-frequency data.
percentile( LF = NULL, probs = c(0.025, 0.975), na.rm = TRUE, sort_probs = TRUE, unique_probs = TRUE )percentile( LF = NULL, probs = c(0.025, 0.975), na.rm = TRUE, sort_probs = TRUE, unique_probs = TRUE )
LF |
Numeric vector of length-frequency data (e.g., |
probs |
Numeric vector of probabilities in |
na.rm |
Logical; if |
sort_probs |
Logical; if |
unique_probs |
Logical; if |
Uses stats::quantile(..., type = 7), the R default. Labels drop trailing
zeros (e.g., L_5 not L_5.0).
A named list (length = length of probs) where each element
corresponds to the requested percentile. Names are formatted as L_x,
where x is the percentile value in percent (e.g., L_2.5, L_97.5).
length_data <- c(10, 9, 7, 10, 11, 13, NA, 11, 6, 20) percentile(length_data) # default 2.5th and 97.5th percentile(length_data, probs = c(0.05, 0.95)) # 5th and 95th percentileslength_data <- c(10, 9, 7, 10, 11, 13, NA, 11, 6, 20) percentile(length_data) # default 2.5th and 97.5th percentile(length_data, probs = c(0.05, 0.95)) # 5th and 95th percentiles
Calculates the proportion of normalized survivorship falling inside
harvest slot limits [minLS, maxLS] relative to the exploitable population
(>L_c), where
and is the inverse age-from-length for a chosen growth model.
prop_target( minLS = NULL, maxLS = NULL, Lc = NULL, M = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, Lmin = NULL, plot = FALSE, length_units = NULL )prop_target( minLS = NULL, maxLS = NULL, Lc = NULL, M = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, Lmin = NULL, plot = FALSE, length_units = NULL )
minLS, maxLS
|
Numeric. Minimum and maximum harvest slot limits (same units as length). |
Lc |
Numeric. Lower cutoff; individuals below |
M |
Numeric or |
growth_model |
Character. One of |
Linf, K, l0
|
VB parameters; |
tmax |
Numeric. Maximum age used to determine |
Gom_Linf, Gom_K, Gom_l0
|
Gompertz parameters; requires |
g1, g2, l2
|
Schnute parameters; |
Lmin |
Optional numeric. Lower bound for the curve grid. If |
plot |
Logical. If |
length_units |
Optional character scalar. Units to display in the x-axis
label when |
Supported growth models (reparameterized to avoid negative length-at-age-0
and to give exact ):
von Bertalanffy (VB) with start length :
Gompertz with start length (requires ):
Schnute with and :
Survivorship is normalized at the model start so that :
l0 for vB, Gom_l0 for Gompertz (requires 0 < Gom_l0 < Gom_Linf),
and for Schnute.
Targeted proportion:
We clamp only near the upper limit to avoid log(0) and never shift the start,
preserving .
If plot = FALSE (default): numeric scalar (the targeted proportion).
If plot = TRUE: list with proportion and plot (a ggplot object).
# Numeric only prop_target(minLS=120, maxLS=240, Lc=80, growth_model="vb", Linf=405, K=0.118, l0=0, tmax=34, plot=FALSE) # With plot (requires ggplot2) out <- prop_target(minLS=120, maxLS=240, Lc=80, growth_model="schnute", g1=0.2, g2=0.2, l2=405, tmax=34, plot=TRUE, length_units = "mm") out$plot# Numeric only prop_target(minLS=120, maxLS=240, Lc=80, growth_model="vb", Linf=405, K=0.118, l0=0, tmax=34, plot=FALSE) # With plot (requires ggplot2) out <- prop_target(minLS=120, maxLS=240, Lc=80, growth_model="schnute", g1=0.2, g2=0.2, l2=405, tmax=34, plot=TRUE, length_units = "mm") out$plot
Calculates the proportional rate of change in an abundance or biomass index (rb)
between consecutive data points using one of three methods:
"annual"Change between the two most recent data points:
. Requires at least 2 values.
"1over2"Change between the most recent value and the mean of the
two values prior: . Requires at least 3 values.
"2over3"Change between the mean of the two most recent values and
the mean of the three values prior: .
Requires at least 5 values.
rb( b_index = NULL, method = c("annual", "1over2", "2over3"), na.rm = FALSE, digits = NULL )rb( b_index = NULL, method = c("annual", "1over2", "2over3"), na.rm = FALSE, digits = NULL )
b_index |
Numeric vector of abundance or biomass indices in descending time order (most recent first). |
method |
Character string; one of |
na.rm |
Logical; if |
digits |
Optional integer. If supplied, the result is rounded using
|
Validates that sufficient data are available for the chosen method and guards
against (near-)zero denominators. If a needed denominator is NA (after
na.rm) or numerically zero, an error is thrown.
A numeric scalar: the proportional rate of change rb. Positive values
indicate an increase; negative values indicate a decrease.
b_index must be in descending time order (most recent first). Indices
should be non-negative (e.g., CPUE).
cpue <- c(0.75, 0.70, 1.49, 1.20, 1.10) # most recent first rb(b_index = cpue) # annual method by default rb(b_index = cpue, method = "1over2") rb(b_index = cpue, method = "2over3") cpue2 <- c(0.75, NA, 1.49, 1.20, 1.10) rb(cpue2, method = "1over2", na.rm = TRUE, digits = 2)cpue <- c(0.75, 0.70, 1.49, 1.20, 1.10) # most recent first rb(b_index = cpue) # annual method by default rb(b_index = cpue, method = "1over2") rb(b_index = cpue, method = "2over3") cpue2 <- c(0.75, NA, 1.49, 1.20, 1.10) rb(cpue2, method = "1over2", na.rm = TRUE, digits = 2)
Calculate the size adherence multiplier (SAM), which evaluates adherence to
harvest slot limits by comparing (lower, upper) percentiles of length–frequency
data to minLS and maxLS. Optionally, produce a graph showing
how SAM varies across a grid of (lower, upper) values.
When lower >= minLS and upper <= maxLS, neither of the slot
limits are violated and the multiplier is calculated without constraint.
When lower < minLS or upper > maxLS, at least one slot limit is
violated and the multiplier is capped at constraint (default = 1).
SAM( lower = NULL, upper = NULL, minLS = NULL, maxLS = NULL, constraint = 1, digits = 2, plot = FALSE, res = 1, lower_percentile = 2.5, upper_percentile = 97.5, length_units = NULL )SAM( lower = NULL, upper = NULL, minLS = NULL, maxLS = NULL, constraint = 1, digits = 2, plot = FALSE, res = 1, lower_percentile = 2.5, upper_percentile = 97.5, length_units = NULL )
lower |
Numeric (length 1). Lower percentile of catch length (e.g., 2.5th). |
upper |
Numeric (length 1). Upper percentile of catch length (e.g., 97.5th). |
minLS |
Numeric (length 1). Minimum landing size (must be > 0). |
maxLS |
Numeric (length 1). Maximum landing size (must be > 0). |
constraint |
Numeric (length 1) in |
digits |
Integer. Number of decimal places used to round outputs
(default = 2). Set |
plot |
Logical. If |
res |
Numeric > 0. Grid step for plotting when |
lower_percentile, upper_percentile
|
Numbers used only for axis labels when
|
length_units |
Optional character scalar. Units to display in the x/y-axis
labels when |
The unconstrained multiplier is .
If any slot limit is violated, the multiplier is pmin(constraint, multiplier).
A list with:
Relative deviation of lower from minLS: .
Relative deviation of upper from maxLS: .
Size adherence multiplier. SAM > 1 increases the advised catch; SAM < 1 decreases it.
(only when plot = TRUE) a ggplot2 object visualizing SAM over a grid.
Illogical combinations of percentiles are shaded grey (e.g., ).
percentile for computing percentiles from length–frequency data.
SAM(lower = 13, upper = 24, minLS = 12, maxLS = 24) # no violation SAM(lower = 13, upper = 25, minLS = 12, maxLS = 24, constraint = 0.95) # violation with constraint out <- SAM( lower = 13, upper = 25, minLS = 12, maxLS = 24, res = 0.5, lower_percentile = 5, upper_percentile = 95, constraint = 1, plot = TRUE, length_units = "cm") out$SAMSAM(lower = 13, upper = 24, minLS = 12, maxLS = 24) # no violation SAM(lower = 13, upper = 25, minLS = 12, maxLS = 24, constraint = 0.95) # violation with constraint out <- SAM( lower = 13, upper = 25, minLS = 12, maxLS = 24, res = 0.5, lower_percentile = 5, upper_percentile = 95, constraint = 1, plot = TRUE, length_units = "cm") out$SAM
Run a single SlotLim pass: compute rb, P, TBA, SAM,
and catch advice Ay_percent; optionally show a composite plot (P, TBA, SAM, Ay_percent).
slotlim_once( Cy = NULL, b_index = NULL, method = c("annual", "1over2", "2over3"), minLS = NULL, maxLS = NULL, Lc = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, M = NULL, lower = NULL, upper = NULL, LF = NULL, probs = c(0.025, 0.975), constraint = 1, T1 = NULL, T2 = NULL, plots = FALSE, length_units = NULL )slotlim_once( Cy = NULL, b_index = NULL, method = c("annual", "1over2", "2over3"), minLS = NULL, maxLS = NULL, Lc = NULL, growth_model = c("vb", "gompertz", "schnute"), Linf = NULL, K = NULL, l0 = 0, tmax = NULL, Gom_Linf = NULL, Gom_K = NULL, Gom_l0 = NULL, g1 = NULL, g2 = NULL, l2 = NULL, M = NULL, lower = NULL, upper = NULL, LF = NULL, probs = c(0.025, 0.975), constraint = 1, T1 = NULL, T2 = NULL, plots = FALSE, length_units = NULL )
Cy |
Numeric. Historical catch. |
b_index |
Numeric vector of a biomass or abundance index in descending time order (most recent first). |
method |
Character. Method for calculating |
minLS, maxLS, Lc
|
Numeric. Slot limits and length at first capture. |
growth_model |
One of |
Linf, K, l0
|
von Bertalanffy (vB) parameters; |
tmax |
Numeric. Maximum observed age; used for integration bounds and (if |
Gom_Linf, Gom_K, Gom_l0
|
Gompertz parameters; requires |
g1, g2, l2
|
Schnute parameters; |
M |
Numeric or |
lower, upper
|
Optional values at specified percentiles. If provided, used directly by |
LF |
Optional numeric vector of length-frequency data. If |
probs |
Numeric vector of probabilities in |
constraint |
Numeric (default 1). Passed to |
T1, T2
|
Optional numerics passed to |
plots |
Logical; if |
length_units |
Optional character; x-axis units for the |
Precedence for size inputs: if both lower and upper are provided, they are used.
Otherwise, if LF is provided, they are derived via percentile(LF, probs). Else error.
A list with Ay, Ay_percent, TBA, SAM, rb, P,
and (if plots=TRUE) a composite plot. Also returns the resolved M and the
lower/upper bounds actually used; tmax is echoed back.
# Minimal, fast example (no plotting), passing lower/upper directly: slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), method = "2over3", minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, lower = 100, upper = 220 ) # Derive lower/upper from length-frequency percentiles: set.seed(1) LF <- rnorm(200, mean = 180, sd = 40) # toy example LF # Compute M from tmax: slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, LF = LF, probs = c(0.05, 0.95), method = "1over2" # rb method chosen ) # Use explicit M (still provide tmax for bounds): slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, M = 0.19, LF = LF, probs = c(0.025, 0.975), method = "1over2" # rb method chosen ) # Plotting example (needs ggplot2 and patchwork): slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, LF = LF, probs = c(0.025, 0.975), method = "1over2", # rb method chosen plots = TRUE, length_units = "mm" )# Minimal, fast example (no plotting), passing lower/upper directly: slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), method = "2over3", minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, lower = 100, upper = 220 ) # Derive lower/upper from length-frequency percentiles: set.seed(1) LF <- rnorm(200, mean = 180, sd = 40) # toy example LF # Compute M from tmax: slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, LF = LF, probs = c(0.05, 0.95), method = "1over2" # rb method chosen ) # Use explicit M (still provide tmax for bounds): slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, M = 0.19, LF = LF, probs = c(0.025, 0.975), method = "1over2" # rb method chosen ) # Plotting example (needs ggplot2 and patchwork): slotlim_once( Cy = 1000, b_index = c(0.5, 0.6, 0.7, 0.6, 0.5), minLS = 120, maxLS = 240, Lc = 80, growth_model = "vb", Linf = 405, K = 0.118, l0 = 0, tmax = 34, LF = LF, probs = c(0.025, 0.975), method = "1over2", # rb method chosen plots = TRUE, length_units = "mm" )
Calculate the targeted biomass adjustment (TBA), which dampens the influence
of proportional rate of change on catch advice when the proportion of abundance
targeted by harvest slot limits is small. Optionally, produce a graph showing how
TBA varies across a grid of (P_targeted, rb) values.
The TBA is calculated as .
TBA(P_targeted = NULL, rb = NULL, digits = 2, plot = FALSE)TBA(P_targeted = NULL, rb = NULL, digits = 2, plot = FALSE)
P_targeted |
Numeric (length 1) in [0, 1]. Proportion of abundance targeted
by harvest slot limits (e.g., from |
rb |
Numeric (length 1). Proportional rate of change in a biomass index
(e.g., from |
digits |
Integer. Number of decimal places used to round outputs
(default = 2). Set |
plot |
Logical. If |
The adjustment dampens large changes in biomass indices when the targeted
proportion is small by multiplying rb by P_targeted. The plot shades
the surface of . A dashed horizontal line marks rb = 0.
A list with:
Input targeted proportion (numeric scalar).
Input proportional rate of change (numeric scalar).
(numeric scalar).
Targeted biomass adjustment multiplier
(numeric scalar). TBA > 1 increases advised catch; TBA < 1 decreases it.
(only when plot=TRUE) a ggplot2 object visualizing TBA over a grid.
prop_target for targeted proportion; rb for proportional rate of change.
TBA(P_targeted = 0.5, rb = -0.5) # compute only # compute + plot (requires ggplot2) out <- TBA(P_targeted = 0.5, rb = -0.5, digits = 2, plot = TRUE) out$plotTBA(P_targeted = 0.5, rb = -0.5) # compute only # compute + plot (requires ggplot2) out <- TBA(P_targeted = 0.5, rb = -0.5, digits = 2, plot = TRUE) out$plot