Intended for conditioning operating models for MSEtool. For data-limited stocks, this function can generate a range of potential depletion scenarios inferred from sparse data. From a historical time series of total catch or effort, and potentially age/length compositions and multiple indices of abundance, the RCM returns a range of values for depletion, selectivity, unfished recruitment (R0), historical fishing effort, and recruitment deviations for the operating model. This is done by sampling life history parameters provided by the user and fitting a statistical catch-at-age model (with the predicted catch equal to the observed catch). Alternatively one can do a single model fit and sample the covariance matrix to generate an operating model with uncertainty based on the model fit. Either a full catch (conditioned on catch) or effort (conditioned on effort) time series is needed but missing data (as NAs) are allowed for all other data types. check_RCMdata evaluates whether the inputs in the S4 RCMdata object are correctly formatted.

check_RCMdata(RCMdata, OM, condition = c("catch", "catch2", "effort"))

RCM(OM, data, ...)

# S4 method for OM,RCMdata
RCM(
  OM,
  data,
  condition = c("catch", "catch2", "effort"),
  selectivity = "logistic",
  s_selectivity = NULL,
  LWT = list(),
  comp_like = c("multinomial", "lognormal"),
  prior = list(),
  max_F = 3,
  cores = 1L,
  integrate = FALSE,
  mean_fit = FALSE,
  drop_nonconv = FALSE,
  drop_highF = FALSE,
  control = list(iter.max = 2e+05, eval.max = 4e+05),
  ...
)

# S4 method for OM,list
RCM(
  OM,
  data,
  condition = c("catch", "catch2", "effort"),
  selectivity = "logistic",
  s_selectivity = NULL,
  LWT = list(),
  comp_like = c("multinomial", "lognormal"),
  ESS = c(30, 30),
  prior = list(),
  max_F = 3,
  cores = 1L,
  integrate = FALSE,
  mean_fit = FALSE,
  drop_nonconv = FALSE,
  drop_highF = FALSE,
  control = list(iter.max = 2e+05, eval.max = 4e+05),
  ...
)

# S4 method for OM,Data
RCM(
  OM,
  data,
  condition = c("catch", "catch2", "effort"),
  selectivity = "logistic",
  s_selectivity = NULL,
  LWT = list(),
  comp_like = c("multinomial", "lognormal"),
  ESS = c(30, 30),
  prior = list(),
  max_F = 3,
  cores = 1L,
  integrate = FALSE,
  mean_fit = FALSE,
  drop_nonconv = FALSE,
  drop_highF = FALSE,
  control = list(iter.max = 2e+05, eval.max = 4e+05),
  ...
)

Arguments

RCMdata

An RCMdata object.

OM

An object of class OM that specifies natural mortality (M), growth (Linf, K, t0, a, b), stock-recruitment relationship, steepness, maturity parameters (L50 and L50_95), standard deviation of recruitment variability (Perr), as well as index uncertainty (Iobs).

condition

String to indicate whether the RCM is conditioned on "catch" (where F are estimated parameters), "catch2" (where F is solved internally using Newton's method), or "effort".

data

Data inputs formatted in a RCMdata (preferred) or Data object. Use of a list is deprecated. See Data section below.

...

Other arguments to pass in for starting values of parameters and fixing parameters. See details.

selectivity

A character vector of length nfleet to indicate "logistic", "dome", or "free" selectivity for each fleet in Chist. If there is time-varying selectivity, this is a character vector of length nsel_block (see Data section below). "free" indicates independent selectivity parameters for each age, and additional modifications for fixing selectivity parameters will likely be needed. See Additional arguments section.

s_selectivity

A vector of length nsurvey to indicate the selectivity of the corresponding columns in data$Index. Use "B" for total biomass, or "SSB" for spawning biomass (by default, "B" is used). Use numbers if the survey selectivity follows a fleet (corresponding to the columns in data$Chist, e.g., 1 = first fleet/column and so on). If the survey selectivity is otherwise independent of anything else in the model, use "logistic", "dome", or "free" to specify the functional form of selectivity, and see Additional arguments section for setup of survey selectivity parameters and Articles section for more information.

LWT

A named list of likelihood weights for the RCM. See below.

comp_like

A string indicating either "multinomial" (default) or "lognormal" distributions for the composition data.

prior

A named list (R0, h, M, and q) to provide the mean and standard deviations of prior distributions for those parameters. R0, index q, and M priors are lognormal (provide the mean in normal space, SD in lognormal space). Beverton-Holt steepness uses a beta prior, while Ricker steepness uses a normal prior. For index q, provide a matrix for nsurvey rows and 2 columns (for mean and SD), with NA in rows corresponding to indices without priors. For all others, provide a length-2 vector for the mean and SD. See Articles section for full description.

max_F

The maximum F for any fleet in the scoping model (higher F's in the model are penalized in the objective function). See also drop_highF.

cores

Integer for the number of CPU cores for the stock reduction analysis.

integrate

Logical, whether to treat recruitment deviations as penalized parameters in the likelihood (FALSE) or random effects to be marginalized out of the likelihood (TRUE).

mean_fit

Logical, whether to run an additional with mean values of life history parameters from the OM.

drop_nonconv

Logical, whether to drop non-converged fits of the RCM, including fits where F = NA.

drop_highF

Logical, whether to drop fits of the RCM where F = max_F.

control

A named list of arguments (e.g, max. iterations, etc.) for optimization, to be passed to the control argument of nlminb.

ESS

A vector of length two. A shortcut method to setting the maximum multinomial sample size of the age and length compositions. Not used when data are provided in a RCMdata object.

Value

An object of class RCModel (see link for description of output).

check_RCMdata returns a list of updated RCMdata object, OM, and StockPars, ObsPars, and FleetPars from the Hist object generated from the OM.

Details

Fleet selectivity is fixed to values sampled from OM if no age or length compositions are provided.

Survey selectivity is estimable only if IAA or IAL is provided. Otherwise, the selectivity should be mirrored to a fleet (vulnerable biomass selectivity) or indexed to total or spawning biomass (see s_selectivity).

Parameters that were used in the fitting model are placed in the RCM@OM@cpars list.

If the operating model OM uses time-varying growth or M, then those trends will be used in the RCM as well. Non-stationary productivity creates ambiguity in the calculation and interpretation of depletion and MSY reference points.

The easiest way to turn off time-varying growth/M is by setting: OM@Msd <- OM@Linfsd <- OM@Ksd <- c(0, 0).

To play with alternative fits by excluding indices, for example, or other optional data, set the corresponding likelihood weight to zero. The model will still generate the inferred index but the data won't enter the likelihood. See section on likelihood weights.

Online Documentation

Several articles are available for the RCM:

Data

One of indices, age compositions, or length compositions should be provided in addition to the historical catch or effort. Not all arguments are needed to run the model (some have defaults, while others are ignored if not applicable depending on the data provided).

The data variable can be an object of class RCMdata. See help file for description of inputs.

Alternatively, the data input can be a Data S4 object which will retrieve data from the following slots:

  • Data@Cat - catch series (single fleet with the Data S4 object)

  • Data@Effort - effort series

  • Data@CAA - fishery age composition

  • Data@CAL, Data@CAL_mids - fishery length composition and corresponding length bins

  • Data@Ind, Data@SpInd, Data@VInd, Data@AddInd - indices of abundance

  • Data@CV_Ind, Data@CV_SpInd, Data@CV_VInd, Data@CV_AddInd - annual coefficients of variation for the corresponding indices of abundance. CVs will be converted to lognormal standard deviations.

  • Data@ML - fishery mean lengths

  • Data@AddIndV, Data@AddIndType, Data@AddIunits - Additional information for indices in Data@AddInd: selectivity and units (i.e., biomass or abundance).

There is no slot in the Data S4 object for the equilibrium catch/effort. These can be passed directly in the function call, i.e., RCM(OM, Data, C_eq = C_eq, ...).

Use of a list is deprecated. For backwards compatibility, here is the list of supported entries:

  • Chist - A vector of historical catch, should be of length OM@nyears. If there are multiple fleets: a matrix of OM@nyears rows and nfleet columns. Ideally, the first year of the catch series represents unfished conditions (see also C_eq).

  • C_sd - A vector or matrix of standard deviations (lognormal distribution) for the catches in Chist. If not provided, the default is 0.01. Only used if condition = "catch".

  • Ehist - A vector of historical effort, should be of length OM@nyears (see also E_eq).

  • Index - A vector of values of an index (of length OM@nyears). If there are multiple indices: a matrix of historical indices of abundances, with rows indexing years and columns indexing the index.

  • I_sd - A vector or matrix of standard deviations (lognormal distribution) for the indices corresponding to the entries in Index. If not provided, this function will use values from OM@Iobs.

  • I_type - Obsolete as of version 2.0. See s_selectivity argument.

  • CAA - Fishery age composition matrix with nyears rows and OM@maxage+1 columns. If multiple fleets: an array with dimension: nyears, OM@maxage, and nfleets.

  • CAL - Fishery length composition matrix with nyears rows and columns indexing the length bin. If multiple fleets: an array with dimension: nyears, length bins, and nfleets.

  • MS - A vector of fishery mean size (MS, either mean length or mean weight) observations (length OM@nyears), or if multiple fleets: matrix of dimension: nyears and nfleets. Generally, mean lengths should not be used if CAL is also provided, unless mean length and length comps are independently sampled.

  • MS_type - A character (either "length" (default) or "weight") to denote the type of mean size data.

  • MS_cv - The coefficient of variation of the observed mean size. If there are multiple fleets, a vector of length nfleet. Default is 0.2.

  • s_CAA - Survey age composition data, an array of dimension nyears, maxage+1, nsurvey.

  • s_CAL - Survey length composition data, an array of dimension nyears, length(length_bin), nsurvey.

  • length_bin - A vector for the midpoints of the length bins for CAL and s_CAL. All bin widths should be equal in size.

  • C_eq - A numeric vector of length nfleet for the equilibrium catch for each fleet in Chist prior to the first year of the operating model. Zero (default) implies unfished conditions in year one. Otherwise, this is used to estimate depletion in the first year of the data. Alternatively, if one has a full CAA matrix, one could instead estimate "artificial" rec devs to generate the initial numbers-at-age (and hence initial depletion) in the first year of the model (see additional arguments).

  • C_eq_sd - A vector of standard deviations (lognormal distribution) for the equilibrium catches in C_eq. If not provided, the default is 0.01. Only used if condition = "catch".

  • E_eq - The equilibrium effort for each fleet in Ehist prior to the first year of the operating model. Zero (default) implies unfished conditions in year one. Otherwise, this is used to estimate depletion in the first year of the data.

  • abs_I - Optional, an integer vector to indicate which indices are in absolute magnitude. Use 1 to set q = 1, otherwise use 0 to estimate q.

  • I_units - Optional, an integer vector to indicate whether indices are biomass based (1) or abundance-based (0). By default, all are biomass-based.

  • age_error - Optional, a square matrix of maxage + 1 rows and columns to specify ageing error. The aa-th column assigns a proportion of the true age in the a-th row to observed age. Thus, all rows should sum to 1. Default is an identity matrix (no ageing error).

  • sel_block - Optional, for time-varying fleet selectivity (in time blocks), a integer matrix of nyears rows and nfleet columns to assigns a selectivity function to a fleet for certain years.

Additional arguments

For RCM, additional arguments can be passed to the model via ...:

  • vul_par: A matrix of 3 rows and nfleet columns for starting values for fleet selectivity. The three rows correspond to LFS (length of full selectivity), L5 (length of 5 percent selectivity), and Vmaxlen (selectivity at length Linf). By default, the starting values are values from the OM object. If any selectivity = "free", then this matrix needs to be of maxage+1 rows where the row specifies the selectivity at age. See Articles section.

  • ivul_par: A matrix of 3 rows and nsurvey columns for starting values for fleet selectivity. Same setup as vul_par. Values in the column are ignored if s_selectivity is mapped to a fishing fleet (add NA placeholders in that case). If any s_selectivity = "free", then this matrix needs to be of maxage+1 rows where the row specifies the selectivity at age.

  • log_rec_dev: A numeric vector of length nyears for the starting values of the log-recruitment deviations.

  • log_early_rec_dev: A numeric vector of length OM@maxage for the starting values of the recruitment deviations controlling the abundance-at-age in the first year of the model.

  • map_vul_par: An integer matrix of the same dimension as vul_par. This is the 'map' argument for vul_par in TMB, see MakeADFun, which indicates whether selectivity parameters are fixed or estimated. If an entry is NA, the corresponding parameter is fixed in the model to the starting value. Otherwise, an integer for each independent parameter. By default, selectivity is fixed if there are no age or length composition for that fleet or survey, otherwise estimated. Unused cells in the vul_par matrix should be given NA in the map matrix.

  • map_ivul_par: The map argument for the survey selectivity parameters (same dimension as ivul_par). Placeholder parameters should have a map value of NA.

  • map_log_early_rec_dev: A vector of length OM@maxage that indexes which recruitment deviates for the cohorts in the first year of the model are fixed (using NA) or estimated (a separate integer). By default, no deviates are estimated (all are NA).

  • map_log_rec_dev: A vector of length OM@nyears that indexes which recruitment deviates are fixed (using NA) or estimated (a separate integer). By default, all deviates are estimated.

  • plusgroup: Logical for whether the maximum age is a plusgroup or not. By default, TRUE.

  • fix_dome: Logical for whether the dome selectivity parameter for fleets is fixed. Used primarily for backwards compatibility, this is overridden by map_vul_par.

  • resample: Logical, whether the OM conditioning parameters (recruitment, fishing mortality, SSB, selectivity, etc.) are obtained by sampling the Hessian matrix from a single model fit. By default FALSE. This feature requires identical biological parameters among simulations.

Likelihood weights

LWT is an optional named list containing the likelihood weights (values >= 0) with the possible options:

  • Chist, CAA, CAL, MS, C_eq: A vector of length nfleet for each.

  • Index, IAA, IAL: A vector of length nsurvey for each.

By default, all likelihood weights are equal to one if not specified by the user.

Annual multinomial sample sizes for the age and length comps can now be provided directly in the RCMdata object. For a list or Data object, use the ESS argument.

See also

Author

Q. Huynh

Examples

# \donttest{ 
# An example that conditions a Pacific cod operating model. There are 48 simulations, 
# where values of natural mortality and steepness are sampled from distributions. 
# The model is fitted with priors on the index catchability. Maturity and selectivity 
# are knife-edge at the age of 2 years. See online tutorial for more information.

data(pcod) 
mat_ogive <- pcod$OM@cpars$Mat_age[1, , 1]
out <- RCM(OM = pcod$OM, data = pcod$data, 
           condition = "catch", mean_fit = TRUE,
           selectivity = "free", s_selectivity = rep("SSB", ncol(pcod$data@Index)),
           vul_par = matrix(mat_ogive, length(mat_ogive), 1),
           map_vul_par = matrix(NA, length(mat_ogive), 1),
           map_log_early_rec_dev = rep(1, pcod$OM@maxage),
           prior = pcod$prior)
#> 
#> Checking OM and data...
#> RCM model is conditioned on: catch
#> 1 fleet(s) detected.
#> 65 years of data detected.
#> 5 survey(s) detected.
#> Getting biological parameters from OM...
#> Mean weight data found.
#> OM@maxF updated to 3.
#> No fishery length or age compositions were provided. Selectivity is fixed to values from OM.
#> Beverton-Holt stock-recruitment relationship used.
#> Prior for q found.
#> 
#> Fitting model (48 simulations) ...
#> Generating additional model fit from mean values of parameters in the operating model...
#> Range of unfished age-0 recruitment (OM@cpars$R0): 5655.85 - 14678.21
#> Range of initial spawning depletion: 0.54 - 1.2
#> Range of spawning depletion (OM@cpars$D): 0.17 - 0.42
#> Historical F and selectivity trends set in OM@cpars$Find and OM@cpars$V, respectively.
#> Selectivity during projection period is set to that in most recent historical year.
#> Historical effort trends set in OM@EffLower and OM@EffUpper.
#> Recruitment standard deviation set in OM@cpars$Perr.
#> Historical recruitment set in OM@cpars$Perr_y.
#> Range of recruitment autocorrelation OM@AC: 0.22 - 0.32
#> Future recruitment deviations sampled with autocorrelation (in OM@cpars$Perr_y).
#> Growth, maturity, natural mortality, and steepness values from RCM are set in OM@cpars.
#> Historical catch data added to OM@cpars$Data@Cat.
#> Historical indices added to OM@cpars$Data@AddInd.
#> Complete.
plot(out, s_name = colnames(pcod$data@Index))
#> Registered S3 method overwritten by 'prodlim':
#>   method    from   
#>   plot.Hist MSEtool
#> Generated markdown file: /var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T//Rtmpi8ulNm/RCM.Rmd
#> Rendering markdown file...
#> Rendered file: /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/Rtmpi8ulNm/RCM.html

# Alternative OM with age-3 maturity and selectivity instead.
out_age3 <- local({
  pcod$OM@cpars$Mat_age[, 2, ] <- 0
  mat_ogive_age3 <- pcod$OM@cpars$Mat_age[1, , 1]
  RCM(OM = pcod$OM, data = pcod$data, 
      condition = "catch", mean_fit = TRUE,
      selectivity = "free", s_selectivity = rep("SSB", ncol(pcod$data@Index)),
      vul_par = matrix(mat_ogive_age3, length(mat_ogive_age3), 1),
      map_vul_par = matrix(NA, length(mat_ogive_age3), 1),
      map_log_early_rec_dev = rep(1, pcod$OM@maxage),
      prior = pcod$prior)
})
#> 
#> Checking OM and data...
#> RCM model is conditioned on: catch
#> 1 fleet(s) detected.
#> 65 years of data detected.
#> 5 survey(s) detected.
#> Getting biological parameters from OM...
#> Mean weight data found.
#> OM@maxF updated to 3.
#> No fishery length or age compositions were provided. Selectivity is fixed to values from OM.
#> Beverton-Holt stock-recruitment relationship used.
#> Prior for q found.
#> 
#> Fitting model (48 simulations) ...
#> Generating additional model fit from mean values of parameters in the operating model...
#> Range of unfished age-0 recruitment (OM@cpars$R0): 5655.85 - 14678.21
#> Range of initial spawning depletion: 0.54 - 1.2
#> Range of spawning depletion (OM@cpars$D): 0.17 - 0.42
#> Historical F and selectivity trends set in OM@cpars$Find and OM@cpars$V, respectively.
#> Selectivity during projection period is set to that in most recent historical year.
#> Historical effort trends set in OM@EffLower and OM@EffUpper.
#> Recruitment standard deviation set in OM@cpars$Perr.
#> Historical recruitment set in OM@cpars$Perr_y.
#> Range of recruitment autocorrelation OM@AC: 0.22 - 0.32
#> Future recruitment deviations sampled with autocorrelation (in OM@cpars$Perr_y).
#> Growth, maturity, natural mortality, and steepness values from RCM are set in OM@cpars.
#> Historical catch data added to OM@cpars$Data@Cat.
#> Historical indices added to OM@cpars$Data@AddInd.
#> Complete.
  
compare_RCM(out, out_age3, scenario = list(names = c("Age-2 maturity", "Age-3 maturity")),
            s_name = colnames(pcod$data@Index))
#> Generated markdown file: /var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T//Rtmpi8ulNm/compare_RCM.Rmd
#> Rendering markdown file...
#> Rendered file: /private/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/Rtmpi8ulNm/compare_RCM.html
# }