| Title: | Catch Advice for Fisheries Managed by Harvest Slot Limits |
| Version: | 0.0.2 |
| 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(). |
| License: | GPL-3 |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.2 |
| Imports: | ggplot2, grid, stats, utils, patchwork |
| Suggests: | testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | no |
| Packaged: | 2025-10-21 13:08:55 UTC; calumpritchard |
| Author: | C.J. Pritchard |
| Maintainer: | C.J. Pritchard <cj_pritchard@outlook.com> |
| Repository: | CRAN |
| Date/Publication: | 2025-10-25 12:30:02 UTC |
SAM
Description
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).
Usage
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
)
Arguments
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 |
Details
The unconstrained multiplier is (1 + lower\_adherence) \times (1 + upper\_adherence).
If any slot limit is violated, the multiplier is pmin(constraint, multiplier).
Value
A list with:
- lower_adherence
Relative deviation of
lowerfromminLS:(lower - minLS)/minLS.- upper_adherence
Relative deviation of
upperfrommaxLS:(maxLS - upper)/maxLS.- SAM
Size adherence multiplier.
SAM > 1increases the advised catch;SAM < 1decreases it.- plot
(only when
plot = TRUE) a ggplot2 object visualizing SAM over a grid. Illogical combinations of percentiles are shaded grey (e.g.,L_{2.5} > L_{97.5}).
See Also
percentile for computing percentiles from length–frequency data.
Examples
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$SAM
TBA
Description
Calculate the targeted biomass adjustment (TBA), which dampens the influence
of proportional rate of change rb 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 1 + (P_{\mathrm{targeted}} \times rb).
Usage
TBA(P_targeted = NULL, rb = NULL, digits = 2, plot = FALSE)
Arguments
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 |
Details
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 1 + P \times rb. A dashed horizontal line marks rb = 0.
Value
A list with:
- P_targeted
Input targeted proportion (numeric scalar).
- rb
Input proportional rate of change (numeric scalar).
- damped_change
P_{\mathrm{targeted}} \times rb(numeric scalar).- TBA
Targeted biomass adjustment multiplier
1 + P_{\mathrm{targeted}} \times rb(numeric scalar).TBA > 1increases advised catch;TBA < 1decreases it.- plot
(only when
plot=TRUE) a ggplot2 object visualizing TBA over a grid.
See Also
prop_target for targeted proportion; rb for proportional rate of change.
Examples
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$plot
catch_adjust
Description
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).
Usage
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
)
Arguments
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 |
Value
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 ifcatchprovided, -
plot— theggplot2object (orNULLif ggplot2 is unavailable).
Examples
# 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")
catch_advice
Description
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.
Usage
catch_advice(
Cy = NULL,
TBA = NULL,
SAM = NULL,
T1 = NULL,
T2 = NULL,
plot = FALSE
)
Arguments
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 |
Value
-
Ay: Catch advice (same units asCy). -
Ay_percent: Percent change of advice relative toCy. -
plot: (only whenplot = TRUE) a ggplot2 object visualizing percent change acrossTBA \times SAM.
See Also
Examples
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)
percentile
Description
Calculates specified percentiles from length-frequency data.
Usage
percentile(
LF = NULL,
probs = c(0.025, 0.975),
na.rm = TRUE,
sort_probs = TRUE,
unique_probs = TRUE
)
Arguments
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 |
Details
Uses stats::quantile(..., type = 7), the R default. Labels drop trailing
zeros (e.g., L_5 not L_5.0).
Value
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).
Examples
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 percentiles
prop_target
Description
Calculates the proportion of normalized survivorship S(L) falling inside
harvest slot limits [minLS, maxLS] relative to the exploitable population
(>L_c), where S(L) = \exp(-M \, t(L))
and t(L) is the inverse age-from-length for a chosen growth model.
Usage
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
)
Arguments
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 |
Details
Supported growth models (reparameterized to avoid negative length-at-age-0
and to give exact t(L_{start})=0):
-
von Bertalanffy (VB) with start length
l_0:t(l) = -\frac{1}{K}\ln\!\left(\frac{L_\infty - l}{L_\infty - l_0}\right), \quad l(t) = L_\infty\!\left(1 - (1-l_0/L_\infty)\,e^{-Kt}\right). -
Gompertz with start length
l_0(requires0 < l_0 < L_\infty):t(l) = -\frac{1}{K}\ln\!\left(\frac{\ln(l/L_\infty)}{\ln(l_0/L_\infty)}\right), \quad l(t) = L_\infty\,(l_0/L_\infty)^{e^{-Kt}}. -
Schnute with
l(0)=0andl(t_{max})=l_2:t(l) = -\frac{1}{g_1}\ln\!\left(1 - \frac{l^{g_2}}{l_2^{g_2}}\,(1-e^{-g_1 t_{max}})\right), \quad l(t) = \left(\frac{l_2^{g_2}}{1-e^{-g_1 t_{max}}}\,(1-e^{-g_1 t})\right)^{1/g_2}.
Survivorship is normalized at the model start so that S(L_{start})=1:
l0 for vB, Gom_l0 for Gompertz (requires 0 < Gom_l0 < Gom_Linf),
and 0 for Schnute.
Targeted proportion:
\frac{\int_{\max(minLS,L_c)}^{\min(maxLS,\,l(t_{max}))} S(L)\,dL}{
\int_{\max(L_c,\,L_{start})}^{l(t_{max})} S(L)\,dL}.
We clamp only near the upper limit to avoid log(0) and never shift the start,
preserving t(L_{start})=0.
Value
If plot = FALSE (default): numeric scalar (the targeted proportion).
If plot = TRUE: list with proportion and plot (a ggplot object).
Examples
# 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
rb
Description
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:
(x_1 - x_2)/x_2. Requires at least 2 values."1over2"Change between the most recent value and the mean of the two values prior:
(x_1 - \bar{x}_{2:3})/\bar{x}_{2:3}. Requires at least 3 values."2over3"Change between the mean of the two most recent values and the mean of the three values prior:
(\bar{x}_{1:2} - \bar{x}_{3:5})/\bar{x}_{3:5}. Requires at least 5 values.
Usage
rb(
b_index = NULL,
method = c("annual", "1over2", "2over3"),
na.rm = FALSE,
digits = NULL
)
Arguments
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
|
Details
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.
Value
A numeric scalar: the proportional rate of change rb. Positive values
indicate an increase; negative values indicate a decrease.
Note
b_index must be in descending time order (most recent first). Indices
should be non-negative (e.g., CPUE).
See Also
Examples
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)
slotlim_once
Description
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).
Usage
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
)
Arguments
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 |
Details
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.
Value
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.
Examples
# 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"
)