SablefishMSE
SablefishMSE.Rmd
The SablefishMSE
package was developed to facilitate the evaluation of alternative harvest control rules, management policies (such as discarding), and TAC apportionment strategies for Alaska sablefish (Anoplopoma fimbria) under the jurisidiction of the United States North Pacific Fisheries Management Council (NPFMC).
The SablefishMSE
package can be downloaded and installed using:
::install_github("ovec8hkin/SablefishMSE")`
remoteslibrary(afscOM)
A Simple Example
A simple runnable example is available at dev/sablefish_mse_example.r
.
The primary R function that runs the MSE simulation loop is:
run_mse(
om=sable_om,
hcr=tier3,
nyears_input = nyears
)
Below, we break down the components that go into the om
and hcr
parameters.
Setting up the Operating Model
First, we start with defining the operating model.
This package relies on the afscOM
package to run the forward OM projection component of the MSE, as well as to generate observation data. afscOM
requires users to define two objects to control the behavior of the forward projection: a dem_params
list and a model_options
list.
The dem_params
list is a named list of multi-dimensional arrays that define demographic parameters within the OM. The model_options
list is a complex named list of various options that control, among other things, the details of the observation processes and how catches are apportioned between fleets. For more details on the proper construction of these objects, please see the afscOM
repository.
SablefishMSE
requires users to pass a named list that defines all of the components of the OM to the MSE wrapper function, which includes two additional components beyond what is required by afscOM
. The components are:
names(sable_om)
-
dem_params
is exactly thedem_params
list that is supplied toafscOM
. -
model_options
is the same list supplied toafscOM
but with some extra options appended. -
init_naa
is the the initial numbers-at-age (and sex) vector from which the OM should begin. -
recruitment
is a function and list of parameters that defines how annual recruitment should be generated (for more on how recruitment functions work within the package see: “Specifying Recruitment”).
Setting up a Harvest Control Rule
Second, users must define a harvest control rule (HCR) function that relates the current population state to a future fishing mortality rate. We provide several pre-built HCR functions, including the currently adopted Tier 3a rule (below) that is used to by the NPFMC to set ABCs for Alaska sablefish, but users can also define their own custom HCR functions (see “Constructing a New HCR Function” for more details on custom HCR functions).
tier3 <- function(ref_pts, naa, dem_params){
# Compute SSB from the current numbers-at-age matrix
ssb <- apply(naa[,,1,]*dem_params$waa[,,1,,drop=FALSE]*dem_params$mat[,,1,,drop=FALSE], 1, sum)
# Compute F based on the NPFMC Tier 3a rule
return(
npfmc_tier3_F(ssb, ref_pts$B40, ref_pts$F40)
)
}
The function object is provided directly to the run_mse
function, and is evaluated within the MSE function itself. For this reason, defining HCR functions must be done carefully with respect to the parameter inputs and function outputs (see “Constructing More Complex HCR Functions” for details).
Running the MSE
Once an OM object and HCR function have been correctly defined, running the MSE is as simple as:
mse <- run_mse(
om=sable_om,
hcr=tier3,
nyears_input = nyears
)
The nyears_input
parameter defined how many years for the MSE to project forward. There is also a parameter spinup_years
which can be used to define how many years to run the OM forward for, before the estimation model starts being used to set future TACs via the HCR. By default, spinup_years = 64
which is specific to Alaska sablefish.
Tests have not been performed to verify the behavior of the MSE when the spinup_years
parameter is different from 64.
There is a wrapper function for performing many MSE runs across different random seeds in parallel. For more information on parallel MSE simulations, see “Multiple MSE Simulations”.
Processing MSE outputs
The MSE function returns a large amount of data back to the user including numbers-at-age and sex for every year (both true and estimated), fishing-mortality-at-age (true and estimated), and the recommended F from the HCR in each year. To facilitate easier processing of these results, especially when MSEs with different OMs or different HCRs are being compared, a bind_mse_outputs
function has been provided.
model_runs <- list(
mse
)
extra_columns <- list(
hcr = c("tier3")
)
bind_mse_outputs(model_runs, var=c("naa", "naa_est"), extra_columns)
To use the bind_mse_outputs
function, place the finished MSE objects into an unnamed list (model_runs
in this case), create a named list of extra columns you want appended to the output data frame (extra_columns
in this case; often this is going to just be the HCR and/or the OM that was used, but see “How to Use the extra_columns Parameter” for more details on how this should be created), and determine the data you would like to pull from the MSE objects ("naa"
and "naa_est"
in this case). The resulting dataframe object with contain just the provided data the user asks for, in long format. From there, the user can manipulate the output data as necesarry for computing performance metrics or plotting results.
Three wrapper functions, get_ssb_biomass
, get_fishing_mortalities
, and get_recruits
, are provided to easily compute and return common quantities (spawning biomass and total biomass, fishing mortality, and recruitment respectively).
Below is an example of one way how users may plot SSB.
# Plot spawning biomass from OM and EM
d <- get_ssb_biomass(model_runs, extra_columns, sable_om$dem_params) %>%
# SSB is females only
filter(sex == "F") %>%
# summarise SSB across year and sim
group_by(time, hcr, sim, L1) %>%
summarise(spbio=sum(spbio)) %>%
# Compute quantiles of SSB distribution
group_by(time, hcr, L1) %>%
median_qi(spbio, .width=c(0.50, 0.80), .simple_names=FALSE) %>%
# Reformat ggdist tibble into long format
reformat_ggdist_long(n=3)
ggplot(d %>% filter(L1 == "naa")) +
geom_lineribbon(aes(x=time, y=median, ymin=lower, ymax=upper, group=hcr), size=0.4)+
geom_pointrange(data = d %>% filter(L1 == "naa_est"), aes(x=time, y=median, ymin=lower, ymax=upper), alpha=0.35, color="red")+
geom_vline(xintercept=64, linetype="dashed")+
geom_hline(yintercept=121.4611, linetype="dashed")+
scale_fill_brewer(palette="Blues")+
scale_y_continuous(limits=c(0, 300))+
coord_cartesian(expand=0)+
theme_bw()