Skip to content

Commit 50a0463

Browse files
committed
Final MSE runs and analyses for upcoming manuscript
1 parent da69ea3 commit 50a0463

1 file changed

Lines changed: 295 additions & 0 deletions

File tree

dev/zahneretal-2025-mseruns.r

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
rm(list=ls())
2+
3+
library(tidyverse)
4+
library(ggdist)
5+
library(ggh4x)
6+
library(reshape2)
7+
library(SpatialSablefishAssessment)
8+
library(tictoc)
9+
library(doParallel)
10+
11+
# Change to wherever your local copy of afscOM is
12+
library(devtools)
13+
afscOM_dir <- "~/Desktop/Projects/afscOM"
14+
sablefishMSE_dir <- here::here()
15+
16+
devtools::load_all(afscOM_dir)
17+
18+
lapply(list.files("R", full.names = TRUE), source)
19+
20+
#' 1. Set up the OM by defining demographic parameters
21+
#' model options (such as options governing the observation
22+
#' processes), and OM initial conditons
23+
nyears <- 110
24+
25+
sable_om <- readRDS("data/sablefish_om_big.RDS") # Read this saved OM from a file
26+
sable_om$model_options$fleet_apportionment <- matrix(c(0.80, 0.20), nrow=nrow(sable_om$model_options$fleet_apportionment), ncol=2, byrow=TRUE)
27+
sable_om$model_options$obs_pars$catch_cv <- c(1e-5, 1e-5, 1e-5, 1e-5)
28+
29+
# Source all available OM and HCR objects
30+
source("dev/oms.R")
31+
source("dev/hcrs.R")
32+
33+
#' 3. Run the closed-loop MSE simulation
34+
#' A single MSE simulation can be run using the `run_mse(...)`
35+
#' function, while multiple MSE simulations can be run (serially)
36+
#' using the `run_mse_multiple(...)` function.
37+
#'
38+
#' It is recommended to always use `run_mse_multiple(...)` even
39+
#' when only a single MSE simulation is required.
40+
#'
41+
42+
set.seed(895)
43+
nsims <- 200
44+
seed_list <- sample(1:(100*nsims), nsims) # Draw 10 random seeds
45+
46+
mse_options_base <- setup_mse_options()
47+
mse_options <- mse_options_base
48+
mse_options$n_spinup_years <- 54
49+
mse_options$recruitment_start_year <- 54
50+
mse_options$n_proj_years <- 75
51+
52+
mse_options_list <- listN(mse_options)
53+
54+
55+
om_list <- listN(om_rand_recruit, om_bh_recruit, om_bhcyclic_recruit, om_immcrash_recruit)
56+
hcr_list <- listN(
57+
mp_f40, mp_f50,
58+
mp_5perc, mp_10perc,
59+
mp_15cap, mp_25cap,
60+
mp_f50chr,
61+
mp_pfmc4010, mp_bcsable,
62+
mp_f00chr
63+
)
64+
65+
66+
tic()
67+
model_runs <- run_mse_multiple(
68+
om_list,
69+
hcr_list,
70+
seed_list,
71+
nyears=100,
72+
mse_options_list=mse_options_list,
73+
diagnostics = FALSE,
74+
save=TRUE
75+
)
76+
toc()
77+
78+
79+
# Data Processinf
80+
filetype <- ".jpeg"
81+
figures_dir <- file.path(here::here(), "figures")
82+
width_small <- 12
83+
height_small <- 8
84+
85+
publication_hcrs <- c("F40", "F50", "F40 +/- 5%", "F40 +/- 10%", "15k Harvest Cap", "25k Harvest Cap", "Constant F50", "PFMC 40-10", "British Columbia", "No Fishing")
86+
publication_oms <- c("Random Recruitment", "Beverton-Holt Cyclic Recruitment", "Immediate Crash Recruitment")
87+
publication_metrics = c("Annual Catch", "Catch AAV", "SSB", "Average Age", "Proportion of Years with Low SSB")
88+
89+
mse_runs <- get_saved_model_runs2(om_order=publication_oms, hcr_order=publication_hcrs)
90+
model_runs <- mse_runs$model_runs
91+
extra_columns <- mse_runs$extra_columns2
92+
93+
interval_widths <- c(0.50, 0.80)
94+
common_trajectory <- 54
95+
time_horizon <- c(55, 130)
96+
97+
hcr_colors <- set_hcr_colors2(publication_hcrs)
98+
99+
100+
### Spawning Biomass and Catch Plots
101+
ssb_data <- get_ssb_biomass(model_runs, extra_columns, sable_om$dem_params, hcr_filter=publication_hcrs, om_filter=publication_oms)
102+
plot_ssb(ssb_data, v1="hcr", v2="om", v3=NA, common_trajectory=common_trajectory, show_est = FALSE)
103+
ggsave(filename=file.path(figures_dir, paste0("ssb", filetype)), width=width_small, height=height_small, units=c("in"))
104+
105+
plot_relative_ssb(ssb_data, v1="hcr", v2="om", common_trajectory = common_trajectory, base_hcr = "No Fishing")
106+
ggsave(filename=file.path(figures_dir, paste0("rel_ssb", filetype)), width=width_small, height=height_small, units=c("in"))
107+
108+
catch_data <- get_landed_catch(model_runs, extra_columns, hcr_filter=publication_hcrs, om_filter=publication_oms)
109+
plot_landed_catch(catch_data, v1="hcr", v2="om", common_trajectory = common_trajectory)
110+
ggsave(filename=file.path(figures_dir, paste0("catch", filetype)), width=width_small, height=height_small, units=c("in"))
111+
112+
plot_ssb_catch(
113+
ssb_data,
114+
catch_data,
115+
v1="hcr",
116+
v2="om",
117+
common_trajectory = common_trajectory
118+
)
119+
ggsave(filename=file.path(here::here(), "figures", "ssb_catch.jpeg"), width=16, height=10, units="in")
120+
121+
122+
### Performance Metrics
123+
performance_metrics <- performance_metric_summary(
124+
model_runs,
125+
extra_columns,
126+
sable_om$dem_params,
127+
ref_naa,
128+
hcr_filter=publication_hcrs,
129+
om_filter=publication_oms,
130+
interval_widths=interval_widths,
131+
time_horizon = time_horizon,
132+
extra_filter = NULL,
133+
relative=NULL,
134+
summarise_by=c("om", "hcr"),
135+
summary_out = TRUE,
136+
metric_list = c("avg_catch", "avg_variation", "avg_ssb", "avg_age", "prop_years_lowssb")
137+
)
138+
perf_data <- performance_metrics$perf_data %>%
139+
mutate(
140+
name = factor(name, levels=publication_metrics)
141+
) %>%
142+
group_by(.width, om, name) %>%
143+
scale_and_rank("median")
144+
145+
plot_performance_metric_summary(perf_data, v1="hcr", v2="om")+
146+
theme(
147+
panel.spacing.x = unit(0.75, "cm"),
148+
)
149+
ggsave(filename=file.path(here::here(), "figures", paste0("performance2", filetype)), width=18, height=12, units="in")
150+
151+
### Resilience Metrics
152+
resilience_metrics <- performance_metric_summary(
153+
model_runs,
154+
extra_columns,
155+
sable_om$dem_params,
156+
ref_naa,
157+
hcr_filter=publication_hcrs,
158+
om_filter=c("Immediate Crash Recruitment"),
159+
interval_widths=interval_widths,
160+
time_horizon = time_horizon,
161+
extra_filter = NULL,
162+
relative=NULL,
163+
summarise_by=c("om", "hcr"),
164+
summary_out = TRUE,
165+
metric_list = c("crash_time", "recovery_time")
166+
)
167+
168+
resilience_data <- resilience_metrics$perf_data %>%
169+
add_row(
170+
om = "Immediate Crash Recruitment",
171+
hcr = "No Fishing",
172+
.width = c(0.5, 0.8),
173+
.point = "median",
174+
.interval = "qi",
175+
name = "Crash Time",
176+
median = Inf, lower = Inf, upper = Inf
177+
) %>%
178+
mutate(
179+
om = factor(om),
180+
hcr = factor(hcr, levels=publication_hcrs),
181+
name = factor(name, levels=c("Crash Time", "Recovery Time"))
182+
) %>%
183+
group_by(.width, om, name) %>%
184+
scale_and_rank("median")
185+
186+
plot_performance_metric_summary(resilience_data)+
187+
ggh4x::facetted_pos_scales(
188+
x = list(
189+
scale_x_continuous("Year", limits=c(0, 20)),
190+
scale_x_continuous("Year", limits=c(0, 50))
191+
)
192+
)+
193+
theme(
194+
strip.text.y = element_blank(),
195+
plot.margin = margin(10, 30, 10, 10),
196+
panel.spacing.x = unit(30, "pt")
197+
)
198+
ggsave(filename=file.path(here::here(), "figures", paste0("resilience2", filetype)), width=width_small, height=height_small, units="in")
199+
200+
201+
### Aggregate Performance
202+
full_performance_metrics <- performance_metric_summary(
203+
model_runs,
204+
extra_columns,
205+
sable_om$dem_params,
206+
ref_naa,
207+
hcr_filter=publication_hcrs,
208+
om_filter=publication_oms,
209+
interval_widths=interval_widths,
210+
time_horizon = time_horizon,
211+
extra_filter = NULL,
212+
relative=NULL,
213+
summarise_by=c("om", "hcr"),
214+
summary_out = FALSE,
215+
metric_list = c("avg_catch", "avg_variation", "avg_ssb", "avg_age", "prop_years_lowssb")
216+
)
217+
218+
om_aggregated_performance <- full_performance_metrics$perf_data %>%
219+
group_by(sim, hcr) %>%
220+
summarise(
221+
across(2:6, \(x) mean(x, na.rm=TRUE))
222+
) %>%
223+
pivot_longer(3:7, names_to="name", values_to="value") %>%
224+
mutate(
225+
name = factor(
226+
name,
227+
levels=c("annual_catch", "aav", "spbio", "avg_age", "prop_years"),
228+
labels=publication_metrics
229+
)
230+
)
231+
232+
om_means <- om_aggregated_performance %>% group_by(name) %>% summarise(v = mean(value))
233+
234+
ggplot(om_aggregated_performance)+
235+
ggridges::stat_binline(aes(x=value, y=hcr, fill=hcr))+
236+
geom_vline(data=om_means, aes(xintercept=v), linetype="dashed")+
237+
scale_fill_manual(values=hcr_colors)+
238+
facet_wrap(~name, scales="free_x")+
239+
labs(y="")+
240+
custom_theme+
241+
ggh4x::facetted_pos_scales(
242+
x = list(
243+
scale_x_continuous("", limits=c(0, 35)),
244+
scale_x_continuous("", limits=c(0, 0.06)),
245+
scale_x_continuous("", limits=c(0, 300)),
246+
scale_x_continuous("", limits=c(5, 10)),
247+
scale_x_continuous("", limits=c(0, 1), breaks=c(0, 0.25, 0.50, 0.75, 1.0), labels=seq(0, 1, 0.25), expand=c(0, NA))
248+
)
249+
)+
250+
guides(fill=guide_legend("Management \n Strategy", nrow=2))+
251+
theme(
252+
# axis.text.y = element_blank(),
253+
axis.ticks.y = element_blank(),
254+
panel.spacing.x = unit(1, "cm")
255+
)
256+
ggsave(file.path(figures_dir, paste0("performance_metrics_agg_hist2", filetype)))
257+
258+
259+
### Extra Analyses
260+
261+
# Get average performance metric value by HCR across the OM scenarios
262+
om_aggregated_performance %>% group_by(hcr, name) %>%
263+
summarise(
264+
value = mean(value)
265+
) %>%
266+
pivot_wider(names_from="name", values_from="value")
267+
268+
# Get number of simulations in which the population went extinct prematurely
269+
ssb_data %>% filter(biomass < 1e-2) %>% pull(sim) %>% unique
270+
271+
# Get number of years in which stability and max harvest constraints were
272+
# applied to their respective HCRs
273+
catch_data %>%
274+
filter_times(time_horizon) %>%
275+
filter(fleet == "Fixed") %>%
276+
filter_hcr_om(hcrs = c("F40 +/- 5%", "F40 +/- 10%", "15k Harvest Cap", "25k Harvest Cap"), oms=publication_oms) %>%
277+
group_by(sim, om, hcr) %>%
278+
mutate(
279+
rel_perc_change = abs(total_catch/lag(total_catch)-1),
280+
constrained = case_when(
281+
hcr == "F40 +/- 5%" ~ ifelse(rel_perc_change >= 0.0499, 1, 0),
282+
hcr == "F40 +/- 10%" ~ ifelse(rel_perc_change >= 0.0999, 1, 0),
283+
hcr == "15k Harvest Cap" ~ ifelse(total_catch >= 14.99, 1, 0),
284+
hcr == "25k Harvest Cap" ~ ifelse(total_catch >= 24.99, 1, 0)
285+
)
286+
) %>%
287+
# arrange(sim, om, time) %>%
288+
group_by(sim, om, hcr) %>%
289+
summarise(
290+
years_constrained = sum(constrained, na.rm=TRUE)/n()
291+
) %>%
292+
group_by(om, hcr) %>%
293+
median_qi(years_constrained, .width = interval_widths) %>%
294+
print(n=100)
295+

0 commit comments

Comments
 (0)