library(learnr)
library(SimSurvey)
library(dplyr)
library(sdmTMB)
library(plotly)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, 
                      out.width = "100%", out.height = "450px")

Introduction

Fisheries-independent surveys

- Conducted by many RFMOs - Becoming increasingly important in stock assessment - Associated with difficult questions: - How many fish are in the sea? - Where are they located? - How should we sample the population? - How should we analyze these data?

  Canadian Coast Guard | Twitter


### How can [SimSurvey](https://github.com/PaulRegular/SimSurvey) help? - A sandbox for simulating of fisheries-independent trawl surveys - **Survey:** random or stratified-random - **Population:** age-structured and spatially-correlated - Facilitates tests of the design and analysis of survey data - How many sets, lengths, ages are enough? - Should the analysis be design or model based? - Can models be used to stitch surveys or fill gaps?

Simulation steps

  1. Simulate abundance - sim_abundance()

    • Common cohort model
  2. Simulate spatial aggregation - sim_distribution()

    • Includes depth associations and noise correlated across space, years and ages
  3. Simulate survey data - sim_survey()

    • Sample population using stratified random survey
    • These data can be analyzed using run_strat() (design-based analysis), or using a package like sdmTMB

Simulate abundance

sim_abundance()

Closure

R_fun <- sim_R(log_mean = log(500), log_sd = 0.5)
R_fun

Usage

pop <- sim_abundance(ages = 1:6, years = 1:4,
                     R = sim_R(log_mean = log(1000)),
                     Z = sim_Z(log_mean = log(0.8)))
round(pop$N)

Tinker and plot

set.seed(438)
long <- sim_abundance(ages = 1:20,
                      R = sim_R(log_mean = log(3e+07)),
                      Z = sim_Z(log_mean = log(0.2)))
short <- sim_abundance(ages = 1:6,
                       R = sim_R(log_mean = log(1e+10)),
                       Z = sim_Z(log_mean = log(0.8)))
plot_surface(short, mat = "N")

Simulate spatial aggregation

sim_distribution()

Make a grid

g <- make_grid(res = c(10, 19), n_div = 4, strat_splits = 1, 
               shelf_depth = 500, shelf_width = 0, depth_range = c(0, 1000))
plot_grid(g)

Populating the grid

pop <- sim_abundance(ages = 1:10, years = 1:10) %>%
           sim_distribution(grid = make_grid(res = c(10, 10)),
                            ays_covar = sim_ays_covar(range = 300,
                                                      phi_age = 0.8,
                                                      phi_year = 0.1),
                            depth_par = sim_parabola(mu = 200,
                                                     sigma = 50))
plot_distribution(pop, ages = 1:3, years = 1:3, type = "heatmap")

Simulate survey data

sim_survey()

Collect samples

set.seed(438)
pop <- sim_abundance(ages = 1:10, years = 1:5) %>%
  sim_distribution(grid = make_grid(res = c(10, 10)))

a <- pop %>%
  sim_survey(set_den = 1 / 1000)
b <- pop %>% 
  sim_survey(set_den = 5 / 1000)

plot_survey(a, which_year = 2, which_sim = 1)

Analyze

Design or model-based? That is the question

Design-based -- stratified analysis

sim <- sim_abundance(ages = 1:5, years = 1:5,
              R = sim_R(log_mean = log(1e+7)),
              growth = sim_vonB(length_group = 1)) %>%
  sim_distribution(grid = make_grid(res = c(10, 10)),
                   ays_covar = sim_ays_covar(sd = 1)) %>%
  sim_survey(n_sims = 1, q = sim_logistic(k = 2, x0 = 3)) %>%
  run_strat() %>%
  strat_error()

sim$total_strat_error_stats
sim$length_strat_error_stats
sim$age_strat_error_stats

Model-based -- sdmTMB

sdmTMB::sdmTMB()

## Simulate population
set.seed(17)
pop <- sim_abundance(ages = seq(1, 10), years = seq(1, 15)) %>%
  sim_distribution(grid = make_grid(res = c(10, 10), depth_range = c(10, 500)),
                   ays_covar = sim_ays_covar(phi_age = 0.8, phi_year = 0.2),
                   depth_par = sim_parabola(mu = 200, sigma = 30))

## Simulate survey data
survey <- sim_survey(pop, n_sims = 1) %>% run_strat()

## Add coordinates to set details
xy <- as_tibble(survey$grid_xy)
dat <- as_tibble(survey$setdet) %>%
  select(x, y, set, year, N = n, tow_area) %>%
  left_join(., xy, by = c("x", "y")) %>%
  mutate(offset = log(tow_area))

## Make mesh and fit geostatistical model to survey data
mesh <- sdmTMB::make_mesh(dat, xy_cols = c("x", "y"), cutoff = 20)
fit <- sdmTMB(N ~ 0 + as.factor(year) + offset,
              data = dat,
              family = nbinom2(link = "log"), spde = mesh,
              include_spatial = TRUE, time = "year")

## Expand grid data for predictions
grid_dat <- as_tibble(select(survey$grid_xy, x, y, depth)) %>% distinct()
grid_dat <- purrr::map_dfr(sort(unique(dat$year)), ~ bind_cols(grid_dat, year = .))
grid_dat$offset <- 0

## Predict across full grid and get index
cell_area <- survey$setdet$cell_area[1]
pred <- predict(fit, newdata = grid_dat, sims = 1000)
index <- get_index_sims(pred, area = rep(cell_area, nrow(pred)))

## Combine indices
true_abund <- tibble(year = unique(dat$year), N = as.numeric(colSums(survey$I))) %>% mutate(type = "True")
strat_abund <- tibble::as_tibble(survey$total_strat) %>%
  mutate(N = total, type = "Design-based") %>%
  select(year, N, type)
index <- index %>%
  mutate(type = "Model-based", N = est) %>%
  bind_rows(strat_abund) %>%
  bind_rows(true_abund)

## Visualize result
index %>% 
  plot_ly(x = ~year, color = ~type, legendgroup = ~type) %>% 
  add_ribbons(ymin = ~lwr, ymax = ~upr, line = list(width = 0), showlegend = FALSE) %>% 
  add_lines(y = ~N, line = list(dash = ~ifelse(type == "True", "solid", "dot")))

What if?

## Simulate population
set.seed(17)
pop <- sim_abundance(ages = seq(1, 10), years = seq(1, 15)) %>%
  sim_distribution(grid = make_grid(res = c(10, 10), depth_range = c(10, 500)),
                   ays_covar = sim_ays_covar(phi_age = 0.8, phi_year = 0.2),
                   depth_par = sim_parabola(mu = 200, sigma = 30))

## Simulate survey data
survey <- sim_survey(pop, n_sims = 1)

## DROP DATA FROM STRATA 5, 6 FOLLOWING YEAR 10
survey$setdet <- filter(survey$setdet, !(year > 10 & strat %in% 5:6))

## Run stratified analysis with missing areas
survey <- survey %>% run_strat()

## Add coordinates to set details
xy <- as_tibble(survey$grid_xy)
dat <- as_tibble(survey$setdet) %>%
  select(x, y, set, year, N = n, tow_area) %>%
  left_join(., xy, by = c("x", "y")) %>%
  mutate(offset = log(tow_area))

## Make mesh and fit geostatistical model to survey data
mesh <- sdmTMB::make_mesh(dat, xy_cols = c("x", "y"), cutoff = 20)
fit <- sdmTMB(N ~ 0 + as.factor(year) + offset,
              data = dat,
              family = nbinom2(link = "log"), spde = mesh,
              include_spatial = TRUE, time = "year")

## Expand grid data for predictions
grid_dat <- as_tibble(select(survey$grid_xy, x, y, depth)) %>% distinct()
grid_dat <- purrr::map_dfr(sort(unique(dat$year)), ~ bind_cols(grid_dat, year = .))
grid_dat$offset <- 0

## Predict across full grid and get index
cell_area <- survey$setdet$cell_area[1]
pred <- predict(fit, newdata = grid_dat, sims = 1000)
index <- get_index_sims(pred, area = rep(cell_area, nrow(pred)))

## Combine indices
true_abund <- tibble(year = unique(dat$year), N = as.numeric(colSums(survey$I))) %>% mutate(type = "True")
strat_abund <- tibble::as_tibble(survey$total_strat) %>%
  mutate(N = total, type = "Design-based") %>%
  select(year, N, type)
index <- index %>%
  mutate(type = "Model-based", N = est) %>%
  bind_rows(strat_abund) %>%
  bind_rows(true_abund)

## Visualize result
index %>% 
  plot_ly(x = ~year, color = ~type, legendgroup = ~type) %>% 
  add_ribbons(ymin = ~lwr, ymax = ~upr, line = list(width = 0), showlegend = FALSE) %>% 
  add_lines(y = ~N, line = list(dash = ~ifelse(type == "True", "solid", "dot"))) %>% 
  add_segments(x = 10, xend = 10, y = 0, yend = max(index$upr, na.rm = TRUE) * 1.05, 
               inherit = FALSE, showlegend = FALSE, hoverinfo = "none", color = I("black"),
               size = I(0.5), linetype = I(2))

Conclusion



PaulRegular/SimSurvey documentation built on Sept. 21, 2023, 7:42 p.m.