SCW17/Paper-07 Projection evaluations

Forward projection scenarios and selectivity sensitivity from jmMSE

Published

June 17, 2026

1 Purpose

This report documents the forward-projection outputs generated by run_projections.R and assembled by report_run_projections.R. It is a Quarto version of the cached HTML report: it loads the saved projection cache, summarizes the run settings, and displays the diagnostic plots that were produced during the projection workflow.

No projection calculations are rerun in this document. The report uses the cached objects in report/projections/cache.rda, which are produced by run_projections.R. This keeps the report rendering step separate from the computational projection step.

2 Workflow Summary

The projection workflow does the following:

  • loads the selected operating model (REF_OM) and subsets it to N_ITER iterations;
  • extends the model from the last historical year to the final projection year;
  • calculates reference points and current-state summaries;
  • evaluates simplified future fishing patterns;
  • compares terminal stock status across scenarios;
  • explores sensitivity to future selectivity assumptions using rolling terminal-year windows; and
  • compares named historical selectivity blocks as alternative frozen future selectivity patterns.

report_run_projections.R then reads the cache and writes report/projections/projections_report.html. This Quarto file reads the same cache and presents the same report content in a format that can be rendered, edited, and extended with standard Quarto tooling.

3 Run Summary

Show code
settings_tbl <- data.frame(
  setting = c(
    "Operating model",
    "Iterations",
    "MCMC worms shown",
    "Projection horizon",
    "Selectivity averaging windows",
    "Named selectivity blocks"
  ),
  value = c(
    REF_OM,
    fmt_num(N_ITER),
    if(exists("worm_iters")) fmt_num(length(worm_iters)) else "0",
    paste(INIT_YEAR + 1, FINAL_YEAR, sep="-"),
    paste(SELEX_WINDOWS, collapse=", "),
    paste(names(SELEX_BLOCKS), collapse=", ")
  ),
  stringsAsFactors = FALSE
)

kable(settings_tbl)
Table 1: Projection run settings stored in the cached projection report.
setting value
Operating model om11
Iterations 50
MCMC worms shown 30
Projection horizon 2026-2050
Selectivity averaging windows 3, 10
Named selectivity blocks Pre-2015, 2019-2025
Show code
kable(refpt_tbl, col.names=c("Stock", "SBMSY (t)", "FMSY"))
Table 2: Reference points used to interpret projected stock status.
Stock SBMSY (t) FMSY
CJM 7,298 0.206

The cached current-state values are:

Show code
kable(current_tbl[, c("stock", "ssb", "ssb_sbmsy", "f", "catch", "sbmsy", "fmsy")],
  col.names=c("Stock", "SSB (t)", "SSB / SBMSY", "Fbar", "Catch (t)", "SBMSY (t)", "FMSY"))
Table 3: Cached current-state values in 2025 by stock.
Stock SSB (t) SSB / SBMSY Fbar Catch (t) SBMSY (t) FMSY
CJM 8,228 1.13 0.829 1,386 7,298 0.206

4 Scenario Definitions

The fixed projection scenarios are defined in run_projections.R. The comparison uses future fishing patterns that include no fishing, constant future fishing mortality set to FMSY, constant future fishing mortality set to 0, 25%, 50%, 75%, 100%, and 200% of the 2025 value, constant fishing mortality set to the F35 SPR rate, and constant future catch set to 0, 25%, 50%, 75%, 100%, and 200% of the 2025 catch. The catch-based scenario is allocated among fleets using the 2025 fleet catch proportions. Special targets such as FMSY, the F2025_* multipliers, F35, and the C2025_* multipliers are resolved during the projection run before the cache is saved. F35 is read from the model yield-profile output as the SPR rate that gives 35% of spawning biomass per recruit. Projection result trajectories are excluded from the figures below when their Fbar exceeds 0.8.

Show code
kable(scenario_tbl, col.names=c("Scenario", "Control quantity", "Target", "Description"))
Table 4: Simplified future fishing-pattern scenarios.
Scenario Control quantity Target Description
F0 fbar 0 No fishing in projection years
FMSY fbar FMSY Constant future F set to FMSY
F2025_0 fbar F2025_0 Constant future F set to 0% of the 2025 value
F2025_25 fbar F2025_25 Constant future F set to 25% of the 2025 value
F2025 fbar F2025 Constant future F set to the 2025 value
F2025_75 fbar F2025_75 Constant future F set to 75% of the 2025 value
F2025_50 fbar F2025_50 Constant future F set to 50% of the 2025 value
F2025_200 fbar F2025_200 Constant future F set to 200% of the 2025 value
F35 fbar F35 SPR F giving 35% of spawning biomass per recruit
C2025_0 catch C2025_0 Constant future catch set to 0% of the 2025 catch
C2025_25 catch C2025_25 Constant future catch set to 25% of the 2025 catch
C2025_half catch C2025_HALF Constant future catch set to 50% of the 2025 catch
C2025_75 catch C2025_75 Constant future catch set to 75% of the 2025 catch
C2025 catch C2025 Constant future catch set to the 2025 catch
C2025_200 catch C2025_200 Constant future catch set to 200% of the 2025 catch
Show code
if(!is.null(fleet_split_tbl)) {
  kable(fleet_split_tbl, col.names=c("Fleet", "Share (%)"))
}
Table 5: Fleet shares used to allocate future catch, based on 2025 catch proportions.
Fleet Share (%)
N_Chile 6.8
SC_Chile_PS 77.2
FarNorth 15.0
Offshore_Trawl 1.0

5 Selectivity History

The first diagnostic summarizes historical catch selectivity at age by fishery and stock. This context is important because future projections freeze or average historical selectivity patterns, so changes in recent selectivity can affect projected spawning biomass and catch.

Show code
plot_qmd_selectivity(selex_ts_dt, ref_om=REF_OM)
Figure 1: Historical selectivity-at-age time series used to interpret the projection selectivity assumptions.

6 Historical Exploitation Metrics

The exploitation diagnostic compares alternative fishing mortality or harvest-rate summaries through the historical period. These metrics provide context for the current fishing mortality level used by the F2025 scenario.

Show code
plot_qmd_exploitation(mets_dt, mets_worms_dt, init_year=INIT_YEAR,
  n_iter=N_ITER, ref_om=REF_OM)
Figure 2: Historical exploitation metrics for the selected operating model.

7 Recruitment

The recruitment diagnostic shows the historical and future recruitment trajectories used in the projected operating model. The dashed vertical line marks the final historical year.

Show code
rec_worm_plot_iters <- sort(unique(rec_worms_dt$iter))[seq_len(min(15,
  length(unique(rec_worms_dt$iter))))]
rec_worms_plot_dt <- as.data.table(rec_worms_dt)[iter %in% rec_worm_plot_iters]
plot_qmd_recruitment(rec_dt, rec_worms_plot_dt, init_year=INIT_YEAR,
  final_year=FINAL_YEAR, ref_om=REF_OM)
Figure 3: Historical and future recruitment for the selected operating model. The future portion uses the F = 0 projection. Colored lines show 15 sampled MCMC draws.

8 SSB / Dynamic Bzero

This diagnostic shows SSB relative to the dynamic unfished spawning biomass trajectory used to scale the terminal stock-status comparison. The future portion uses the F0 projection for the selected operating model.

Show code
plot_qmd_ssb_dynamic_bzero(futs_worms_dt, REF_OM, N_ITER, INIT_YEAR,
  FINAL_YEAR, scenario_filter="F0", worm_n=15)
Figure 4: SSB / dynamic Bzero for om11 through 2050. The future portion uses the F = 0 projection. The ribbon shows the 90% interval across cached MCMC draw trajectories, the black line shows the median, and colored lines show 15 sampled MCMC draws.
Show code
plot_qmd_ssb_dynamic_bzero(futs_worms_dt, REF_OM, N_ITER, INIT_YEAR,
  FINAL_YEAR, scenario_filter="F2025", worm_n=15)
Figure 5: SSB / dynamic Bzero for om11 through 2050. The future portion uses the projection with F set equal to the 2025 value. The ribbon shows the 90% interval across cached MCMC draw trajectories, the black line shows the median, and colored lines show 15 sampled MCMC draws.
Show code
plot_qmd_dynamic_bzero(REF_OM, N_ITER, INIT_YEAR, FINAL_YEAR, worm_n=15)
Figure 6: Dynamic Bzero for om11 through 2050 in kt. The ribbon shows the 90% interval across MCMC draws, the black line shows the median, and colored lines show 15 sampled MCMC draws.

9 Future Fishing Pattern Scenarios

The main projection comparison applies the fishing-pattern controls over the projection horizon. The plot shows median trajectories by scenario for the cached projection summaries, including spawning biomass, fishing mortality, and catch where available.

Show code
futs_excluded <- median_fbar_exclusions(
  as.data.table(futs_dt)[year > INIT_YEAR], "scenario")
futs_plot_dt <- drop_group_stock(futs_dt, futs_excluded, "scenario")

plot_qmd_scenarios(futs_plot_dt, INIT_YEAR, sbmsy_ref, fmsy_ref,
  final_year=FINAL_YEAR, ref_om=REF_OM)
Figure 7: Forward projections under the future fishing-pattern scenarios. CJM: SBMSY = 7,298 t, FMSY = 0.206 Projections: 2026-2050 Results with Fbar greater than 0.8 are excluded.

The terminal-status plot shows the distribution of projected spawning biomass relative to SBMSY in the final projection year. This gives a compact comparison of scenario risk at the end of the projection horizon.

Show code
status_plot_dt <- drop_fbar_iterations(status_dt, futs_fbar_max_dt, "scenario")
plot_qmd_status(status_plot_dt, FINAL_YEAR, n_iter=N_ITER, ref_om=REF_OM)
Figure 8: Distribution of SSB / SBMSY in 2050 under each projection scenario. 50 iterations. The dotted line marks SBMSY. Results with Fbar greater than 0.8 are excluded.
Show code
plot_qmd_tradeoff(status_plot_dt, FINAL_YEAR, ref_om=REF_OM)
Figure 9: Median catch and SSB / SBMSY in 2050 under each projection scenario. Points show scenario medians; bars show 90% intervals. The dotted line marks SBMSY. Results with Fbar greater than 0.8 are excluded.
Show code
plot_qmd_tradeoff(status_plot_dt, FINAL_YEAR, ref_om=REF_OM,
  x_metric="ssb")
Figure 10: Median catch and SSB in 2050 under each projection scenario. Points show scenario medians; bars show 90% intervals. The dotted line marks SBMSY. Results with Fbar greater than 0.8 are excluded.
Show code
scaled_tradeoff_om11_dt <- scaled_tradeoff_data(status_dt, futs_fbar_max_dt,
  REF_OM, N_ITER)
plot_qmd_scaled_tradeoff(scaled_tradeoff_om11_dt, FINAL_YEAR, ref_om=REF_OM)
Figure 11: Median catch and scaled stock status in 2050 under each projection scenario for om11. The x-axis is (SSB / dynamic Bzero) divided by the draw-specific Bmsy / Bzero value. Points show scenario medians; bars show 90% intervals. The dotted vertical line marks the draw-specific Bmsy / Bzero level. Results with Fbar greater than 0.8 are excluded.
Show code
om12_cache_file <- file.path(jmMSE_path, "report", "projections_om12",
  "cache.rda")
if(!file.exists(om12_cache_file)) {
  stop("OM12 projection cache not found at ", om12_cache_file,
    ". Run explore_projections.R with REF_OM set to 'om12' before rendering.")
}
om12_cache <- new.env(parent=emptyenv())
load(om12_cache_file, envir=om12_cache)
scaled_tradeoff_om12_dt <- scaled_tradeoff_data(om12_cache$status_dt,
  om12_cache$futs_fbar_max_dt, om12_cache$REF_OM, om12_cache$N_ITER)
plot_qmd_scaled_tradeoff(scaled_tradeoff_om12_dt, om12_cache$FINAL_YEAR,
  ref_om=om12_cache$REF_OM)
Figure 12: Median catch and scaled stock status in 2050 under each projection scenario for om12, the steepness = 0.8 operating model. The x-axis is (SSB / dynamic Bzero) divided by the draw-specific Bmsy / Bzero value. Points show scenario medians; bars show 90% intervals. The dotted vertical line marks the draw-specific Bmsy / Bzero level. Results with Fbar greater than 0.8 are excluded.
Show code
catch_2026_plot_dt <- drop_fbar_iterations(catch_2026_dt,
  futs_fbar_max_dt, "scenario")
plot_qmd_catch_distribution(catch_2026_plot_dt, 2026,
  n_iter=N_ITER, ref_om=REF_OM)
Figure 13: Distribution of catch in 2026 under each projection scenario. 50 iterations. Results with Fbar greater than 0.8 are excluded.

10 Selectivity Window Sensitivity

The selectivity-window sensitivity analysis projects at FMSY while replacing future selectivity with averages over alternative terminal-year windows. For example, a three-year window uses the mean selectivity pattern from the final three historical years.

Show code
window_tbl <- data.frame(
  window_years = SELEX_WINDOWS,
  description = paste("Mean selectivity over the final", SELEX_WINDOWS, "historical years")
)

kable(window_tbl, col.names=c("Window (years)", "Projection assumption"))
Table 6: Terminal-year selectivity averaging windows.
Window (years) Projection assumption
3 Mean selectivity over the final 3 historical years
10 Mean selectivity over the final 10 historical years
Show code
selex_excluded <- selex_fbar_max_dt[
  , .(max_median_fbar=median(max_fbar, na.rm=TRUE)),
  by=.(window, stock)][max_median_fbar > FBAR_MAX]
selex_plot_dt <- drop_group_stock(selex_dt, selex_excluded, "window")

plot_qmd_sensitivity(selex_plot_dt, group_col="window", group_lab="Avg. years",
  init_year=INIT_YEAR, sbmsy_ref=sbmsy_ref, fmsy_ref=fmsy_ref,
  ref_om=REF_OM,
  title_prefix="Selectivity averaging window sensitivity")
Figure 14: Sensitivity of projections to the terminal-year selectivity averaging window. CJM: SBMSY = 7,298 t, FMSY = 0.206 Results with Fbar greater than 0.8 are excluded.

11 Selectivity Block Sensitivity

The named-block sensitivity analysis is similar to the rolling-window analysis, but the averaged selectivity pattern comes from specified historical year blocks. This is useful when historical periods represent different fishery or stock-selectivity regimes.

Show code
kable(block_tbl, col.names=c("Block", "Years"))
Table 7: Named historical selectivity blocks used for projection sensitivity.
Block Years
Pre-2015 2005-2014
2019-2025 2019-2025
Show code
block_excluded <- block_fbar_max_dt[
  , .(max_median_fbar=median(max_fbar, na.rm=TRUE)),
  by=.(block, stock)][max_median_fbar > FBAR_MAX]
block_plot_dt <- drop_group_stock(block_dt, block_excluded, "block")

plot_qmd_sensitivity(block_plot_dt, group_col="block", group_lab="Selectivity block",
  init_year=INIT_YEAR, sbmsy_ref=sbmsy_ref, fmsy_ref=fmsy_ref,
  ref_om=REF_OM,
  title_prefix="Selectivity block sensitivity")
Figure 15: Sensitivity of projections to named historical selectivity blocks. CJM: SBMSY = 7,298 t, FMSY = 0.206 Results with Fbar greater than 0.8 are excluded.

12 Outputs

The cached projection workflow writes two main files:

  • report/projections/cache.rda, containing the settings, summary values, and plot objects used by this report; and
  • report/projections/projections_report.html, the original HTML report built by report_run_projections.R.

This Quarto document provides an editable report source for the same projection results.