Skip to content

Latest commit

 

History

History
1090 lines (944 loc) · 38.3 KB

File metadata and controls

1090 lines (944 loc) · 38.3 KB
### create FLStock for cod ####
### base on SAM assessment

### check versions of required R packages
if (packageVersion("FLCore") < "2.6.11.9001") 
  stop("please update FLCore")
if (packageVersion("FLfse") < "0.0.0.9003") 
  stop("please update FLfse")
if (packageVersion("stockassessment") < "0.8.1") 
  stop("please update stockassessment")
if (packageVersion("mse") < "0.9.1") 
  stop("please update stockassessment")

### load packages
library(FLfse)
library(stockassessment)
library(ggplotFL)
library(FLAssess)
library(mse)
### load files from package mse for easier debugging
# devtools::load_all("../mse/")
library(FLash)
library(tidyr)
library(dplyr)

source("a4a_mse_WKNSMSE_funs.R")

dir.create(path = "input/cod4", recursive = TRUE)
## Warning in dir.create(path = "input/cod4", recursive = TRUE): 'input\cod4'
## already exists
dir.create(path = "output/runs/cod4", recursive = TRUE)
## Warning in dir.create(path = "output/runs/cod4", recursive = TRUE):
## 'output\runs\cod4' already exists
### create plots and print to screen?
verbose <- TRUE

### simulation specifications ####

### number of iterations/replicates
n <- 1000
### number of years
n_years <- 20
### last data year
yr_data <- 2018

### fit SAM ####
### use input data provided in FLfse
### recreates the WGNSSK2018 cod assessment
fit <- FLR_SAM(stk = cod4_stk, idx = cod4_idx, conf = cod4_conf_sam)

if (isTRUE(verbose)) {
  is(fit)
  fit
  plot(fit)
}

plot of chunk unnamed-chunk-1

### remove catch multiplier for cod ####
### For the cod SAM assessment a catch multiplier is estimated for the years
### 1993-2005.
### For the simulation, we correct the catch with this multiplier and remove
### estimation of the catch multiplier 
### -> saves time in simulation (less parameters to estimate)

### get catch multiplier
ages <- fit$conf$minAge:fit$conf$maxAge
yrs <- fit$conf$keyScaledYears
catch_mult <- FLQuant(
  matrix(data = fit$pl$logScale[(fit$conf$keyParScaledYA + 1)], 
         ncol = fit$conf$noScaledYears,
         nrow = length(fit$conf$minAge:fit$conf$maxAge),
         byrow = TRUE), 
  dimnames = list(year = fit$conf$keyScaledYears, 
                  age = fit$conf$minAge:fit$conf$maxAge))
catch_mult <- exp(catch_mult)

cod4_stk2 <- cod4_stk
### correct catch.n
catch.n(cod4_stk2)[ac(ages), ac(yrs)] <- catch.n(cod4_stk2)[ac(ages), ac(yrs)] *
  catch_mult
### split into landings and discards, based on landing fraction
landings.n(cod4_stk2)[ac(ages), ac(yrs)] <- catch.n(cod4_stk2)[ac(ages), ac(yrs)] *
  (landings.n(cod4_stk)[ac(ages), ac(yrs)] / catch.n(cod4_stk)[ac(ages), ac(yrs)])
discards.n(cod4_stk2)[ac(ages), ac(yrs)] <- catch.n(cod4_stk2)[ac(ages), ac(yrs)] *
  (1 - landings.n(cod4_stk)[ac(ages), ac(yrs)] / 
     catch.n(cod4_stk)[ac(ages), ac(yrs)])
### update stock
catch(cod4_stk2)[, ac(yrs)] <- computeCatch(cod4_stk2)[, ac(yrs)]
landings(cod4_stk2)[, ac(yrs)] <- computeLandings(cod4_stk2)[, ac(yrs)]
discards(cod4_stk2)[, ac(yrs)] <- computeDiscards(cod4_stk2)[, ac(yrs)]

### fit SAM to "corrected" catches
cod4_conf_sam_no_mult <- cod4_conf_sam[!names(cod4_conf_sam) %in% 
                                         c("noScaledYears", "keyScaledYears",
                                           "keyParScaledYA")]
fit2 <- FLR_SAM(stk = cod4_stk2, idx = cod4_idx, 
                conf = cod4_conf_sam_no_mult)
### compare results
if (isTRUE(verbose)) summary(fit2) / summary(fit)
##      R(age 1)      Low      High SSB      Low      High Fbar(2-4)      Low
## 1963        1 1.000041 0.9999581   1 1.002028 0.9979721         1 1.000000
## 1964        1 1.000108 0.9998917   1 1.001807 0.9981933         1 1.000000
## 1965        1 1.000049 0.9999516   1 1.001456 0.9985430         1 1.000000
## 1966        1 1.000015 0.9999849   1 1.001530 0.9984758         1 1.000000
## 1967        1 1.000028 0.9999713   1 1.001420 0.9985851         1 1.000000
## 1968        1 1.000061 0.9999367   1 1.001036 0.9989625         1 1.000000
## 1969        1 1.000141 0.9998617   1 1.001384 0.9986216         1 1.000000
## 1970        1 1.000014 0.9999862   1 1.001566 0.9984326         1 1.000000
## 1971        1 1.000070 0.9999297   1 1.001469 0.9985311         1 1.000000
## 1972        1 1.000052 0.9999493   1 1.001394 0.9986070         1 1.000000
## 1973        1 1.000026 0.9999749   1 1.001167 0.9988327         1 1.000000
## 1974        1 1.000020 0.9999805   1 1.001364 0.9986452         1 1.000000
## 1975        1 1.000212 0.9997879   1 1.001475 0.9985304         1 1.000000
## 1976        1 1.000209 0.9997920   1 1.002040 0.9979638         1 1.000000
## 1977        1 1.000136 0.9998636   1 1.002267 0.9977457         1 1.000000
## 1978        1 1.000215 0.9997857   1 1.001469 0.9985296         1 1.000000
## 1979        1 1.000028 0.9999724   1 1.001758 0.9982386         1 1.000000
## 1980        1 1.000042 0.9999575   1 1.001711 0.9982955         1 1.000000
## 1981        1 1.000043 0.9999560   1 1.001658 0.9983419         1 1.000000
## 1982        1 1.000449 0.9995509   1 1.001768 0.9982378         1 1.000000
## 1983        1 1.000371 0.9996287   1 1.002801 0.9972036         1 1.000000
## 1984        1 1.000688 0.9993120   1 1.003625 0.9963900         1 1.000000
## 1985        1 1.000384 0.9996175   1 1.004309 0.9957120         1 1.000000
## 1986        1 1.000539 0.9994619   1 1.003957 0.9960524         1 1.000000
## 1987        1 1.000296 0.9997041   1 1.004097 0.9959203         1 1.001115
## 1988        1 1.000410 0.9995892   1 1.003571 0.9964454         1 1.000000
## 1989        1 1.000899 0.9991024   1 1.004807 0.9952163         1 1.001078
## 1990        1 1.000553 0.9994504   1 1.006985 0.9930695         1 1.002307
## 1991        1 1.004441 0.9955779   1 1.010287 0.9898151         1 1.007034
## 1992        1 1.012672 0.9874876   1 1.021008 0.9794174         1 1.015458
## 1993        1 1.016080 0.9841747   1 1.079715 0.9261619         1 1.023753
## 1994        1 1.022641 0.9778607   1 1.095669 0.9126876         1 1.026964
## 1995        1 1.021278 0.9791636   1 1.098055 0.9106904         1 1.027180
## 1996        1 1.018857 0.9814916   1 1.100446 0.9087187         1 1.028377
## 1997        1 1.021910 0.9785600   1 1.092877 0.9150301         1 1.027618
## 1998        1 1.014944 0.9852754   1 1.084269 0.9222834         1 1.027996
## 1999        1 1.018876 0.9814746   1 1.102453 0.9070636         1 1.027957
## 2000        1 1.018058 0.9822651   1 1.089798 0.9175960         1 1.028078
## 2001        1 1.017677 0.9826381   1 1.081180 0.9249072         1 1.025316
## 2002        1 1.017866 0.9824446   1 1.084628 0.9219635         1 1.028049
## 2003        1 1.013918 0.9862789   1 1.085143 0.9215380         1 1.024969
## 2004        1 1.007256 0.9927906   1 1.075847 0.9295090         1 1.025033
## 2005        1 1.002685 0.9973224   1 1.037514 0.9638445         1 1.028490
## 2006        1 1.001966 0.9980383   1 1.014655 0.9855375         1 1.007622
## 2007        1 1.001551 0.9984461   1 1.011129 0.9890052         1 1.008170
## 2008        1 1.002366 0.9976376   1 1.014731 0.9854741         1 1.010345
## 2009        1 1.002410 0.9975922   1 1.018176 0.9821608         1 1.012302
## 2010        1 1.003957 0.9960580   1 1.023688 0.9768674         1 1.018072
## 2011        1 1.002936 0.9970807   1 1.029487 0.9713616         1 1.019417
## 2012        1 1.002770 0.9972361   1 1.033641 0.9674517         1 1.021053
## 2013        1 1.003055 0.9969503   1 1.034805 0.9663578         1 1.021333
## 2014        1 1.003318 0.9966952   1 1.034054 0.9670748         1 1.021053
## 2015        1 1.002912 0.9970944   1 1.035833 0.9654151         1 1.018868
## 2016        1 1.003628 0.9963830   1 1.036246 0.9650297         1 1.022284
## 2017        1 1.003942 0.9960730   1 1.040159 0.9613924         1 1.016086
## 2018        1 1.000942 0.9990640   1 1.038314 0.9631076         1 1.011331
##           High
## 1963 1.0000000
## 1964 0.9983361
## 1965 0.9984779
## 1966 1.0000000
## 1967 1.0000000
## 1968 1.0000000
## 1969 1.0000000
## 1970 1.0000000
## 1971 1.0000000
## 1972 1.0000000
## 1973 1.0000000
## 1974 1.0000000
## 1975 1.0000000
## 1976 0.9989616
## 1977 1.0000000
## 1978 1.0000000
## 1979 1.0000000
## 1980 1.0000000
## 1981 0.9990412
## 1982 1.0000000
## 1983 1.0000000
## 1984 1.0000000
## 1985 1.0000000
## 1986 0.9990893
## 1987 1.0000000
## 1988 1.0000000
## 1989 0.9991055
## 1990 0.9971483
## 1991 0.9932757
## 1992 0.9855908
## 1993 0.9773371
## 1994 0.9739777
## 1995 0.9731183
## 1996 0.9721724
## 1997 0.9734675
## 1998 0.9732620
## 1999 0.9726962
## 2000 0.9717466
## 2001 0.9753425
## 2002 0.9721689
## 2003 0.9764936
## 2004 0.9753086
## 2005 0.9713971
## 2006 0.9939247
## 2007 0.9909677
## 2008 0.9892761
## 2009 0.9865410
## 2010 0.9835821
## 2011 0.9807356
## 2012 0.9775281
## 2013 0.9788868
## 2014 0.9807692
## 2015 0.9822134
## 2016 0.9799197
## 2017 0.9848485
## 2018 0.9893428
### estimates and log likelihood identical, only bounds smaller

### fit SAM as it is done during the MSE simulation
fit_est <- FLR_SAM(stk = cod4_stk2, idx = cod4_idx, 
                   conf = cod4_conf_sam_no_mult, 
                   newtonsteps = 0, rel.tol = 0.001)
### extract model parameters and use them in the simulation as starting values
sam_initial <- sam_getpar(fit_est)
### create FLStock ####
### create template with 1 iteration
### cod4_stk2 is used as template, i.e. the input values (catch) include
### the catch multiplier, 
### the results (stock numbers & harvest) are used from the real WGNSSK fit
stk <- SAM2FLStock(object = fit, stk = cod4_stk2)
if (isTRUE(verbose)) summary(stk)
## An object of class "FLStock"
## 
## Name: cod.27.47d 
## Description: as used by WGNSSK 2018 
## Quant: age 
## Dims:  age 	year	unit	season	area	iter
## 	6	56	1	1	1	1	
## 
## Range:  min	max	pgroup	minyear	maxyear	minfbar	maxfbar 
## 	1	6	6	1963	2018	2	4	
## 
## catch         : [ 1 56 1 1 1 1 ], units =  NA 
## catch.n       : [ 6 56 1 1 1 1 ], units =  NA 
## catch.wt      : [ 6 56 1 1 1 1 ], units =  NA 
## discards      : [ 1 56 1 1 1 1 ], units =  NA 
## discards.n    : [ 6 56 1 1 1 1 ], units =  NA 
## discards.wt   : [ 6 56 1 1 1 1 ], units =  NA 
## landings      : [ 1 56 1 1 1 1 ], units =  NA 
## landings.n    : [ 6 56 1 1 1 1 ], units =  NA 
## landings.wt   : [ 6 56 1 1 1 1 ], units =  NA 
## stock         : [ 1 56 1 1 1 1 ], units =  NA 
## stock.n       : [ 6 56 1 1 1 1 ], units =  NA 
## stock.wt      : [ 6 56 1 1 1 1 ], units =  NA 
## m             : [ 6 56 1 1 1 1 ], units =  NA 
## mat           : [ 6 56 1 1 1 1 ], units =  NA 
## harvest       : [ 6 56 1 1 1 1 ], units =  f 
## harvest.spwn  : [ 6 56 1 1 1 1 ], units =  NA 
## m.spwn        : [ 6 56 1 1 1 1 ], units =  NA
### set units
units(stk)[1:17] <- as.list(c(rep(c("t", "1000", "kg"), 4),
                              "", "", "f", "", ""))
if (isTRUE(verbose)) plot(stk)

plot of chunk unnamed-chunk-1

### save for later comparison
stk_orig <- stk

### add uncertainty ####
### first approach: use variance-covariance


### add iteration dimension
stk <- FLCore::propagate(stk, n)
dim(stk)
## [1]    6   56    1    1    1 1000
### add uncertainty estimated by SAM as iterations
set.seed(1)
uncertainty <- SAM_uncertainty(fit = fit, n = n, print_screen = FALSE, 
                               idx_cov = TRUE, catch_est = TRUE)
### add noise to stock
stock.n(stk)[] <- uncertainty$stock.n
stock(stk)[] <- computeStock(stk)
### add noise to F
harvest(stk)[] <- uncertainty$harvest

### catch noise added later

if (isTRUE(verbose)) plot(stk, probs = c(0.05, 0.25, 0.5, 0.75, 0.95))

plot of chunk unnamed-chunk-1

### maximum observed F
max(fbar(stk))
## [1] 1.291715
# 1.359563 in year 1999 with 10,000 iterations
max(harvest(stk))
## [1] 1.652389
# 2.086832 in year 2001 for age 6 (plusgroup)

### get estimated catch numbers
catch_n <- uncertainty$catch_n


### check MCMC approach ####
# library(tmbstan) # cran package
# 
# ### create template stock for storing results
# MCMC_iter <- n
# MCMC_warmup <- 1000
# stk_MCMC <- propagate(stk, MCMC_iter)
# 
# ### run MCMC
# system.time(mcmc <- tmbstan(fit$obj, chains = 1, iter = MCMC_warmup + MCMC_iter, 
#                             warmup = MCMC_warmup, 
#                             seed = 1, control = list(max_treedepth = 15)))
# ### extract 
# mc <- extract(mcmc, inc_warmup = FALSE, permuted = FALSE)
# 
# table(gsub(x = dimnames(mc)$parameters, pattern = "\\[[0-9]{1,}\\]", 
#            replacement = ""))
# # itrans_rho         logF      logFpar         logN     logScale logSdLogFsta 
# #          1          336            9          336           13            2 
# # logSdLogN  logSdLogObs         lp__ 
# #         2            7            1 
# ### gives N and F @age
# ### scale for 
# 
# 
# ### find positions for results in MCMC
# nms <- dimnames(mc)$parameters
# F_pos <- grep(x = nms, pattern = "logF\\[[0-9]{1,3}\\]$")
# N_pos <- grep(x = nms, pattern = "logN\\[[0-9]{1,3}\\]$")
# factor_pos <- grep(x = nms, pattern = "logScale\\[[0-9]{1,2}\\]$")
# 
# ### in the MCMC results age and years are mixed within the same row,
# ### each row represents one iteration
# ### this needs to be reformatted to be useful...
# 
# ### fishing mortality:
# harvest(stk_MCMC)[] <- aperm(array(data = c(exp(mc[,, F_pos])),
#                                    dim = dim(harvest(stk_MCMC))[c(6, 1:5)]),
#                              perm = c(2:6, 1))
# 
# ### stock numbers at age
# stock.n(stk_MCMC)[] <- aperm(array(data = c(exp(mc[,, N_pos])),
#                                    dim = dim(stock.n(stk_MCMC))[c(6, 1:5)]),
#                              perm = c(2:6, 1))
# stock(stk_MCMC) <- computeStock(stk_MCMC)
# 
# ### catch factor
# ### get ages and years
# ages <- fit$conf$minAge:fit$conf$maxAge
# yrs <- fit$conf$keyScaledYears
# ### get catch factors
# catch_factor <- lapply(split(exp(mc[,, factor_pos]), seq(MCMC_iter)), 
#                        function(x) {
#   x[t(fit$conf$keyParScaledYA + 1)]
# })
# catch_factor <- unlist(catch_factor)
# ### coerce into FLQuant
# catch_factor <- FLQuant(catch_factor,
#                       dimnames = dimnames(catch.n(stk_MCMC[ac(ages), ac(yrs)])))
# ### multiply catch numbers
# catch.n(stk_MCMC)[ac(ages), ac(yrs)] <- catch_factor * 
#   catch.n(stk_MCMC)[ac(ages), ac(yrs)]
# ### split into landings and discards, based on landing fraction
# lfrac <- propagate((landings.n(stk)[ac(ages), ac(yrs)] / 
#                       catch.n(stk)[ac(ages), ac(yrs)]), MCMC_iter)
# landings.n(stk_MCMC)[ac(ages), ac(yrs)] <- catch.n(stk_MCMC)[ac(ages), ac(yrs)] *
#   lfrac
# discards.n(stk_MCMC)[ac(ages), ac(yrs)] <- catch.n(stk_MCMC)[ac(ages), ac(yrs)] *
#   (1 - lfrac)
# ### update stock
# catch(stk_MCMC)[, ac(yrs)] <- computeCatch(stk_MCMC)[, ac(yrs)]
# landings(stk_MCMC)[, ac(yrs)] <- computeLandings(stk_MCMC)[, ac(yrs)]
# discards(stk_MCMC)[, ac(yrs)] <- computeDiscards(stk_MCMC)[, ac(yrs)]
# 
# ### plot MCMC stock
# plot(stk_MCMC)
# ### compare with original SAM fit
# plot(FLStocks(MCMC = stk_MCMC, original = stk_orig))
# ### compare with first uncertainty approach
# plot(FLStocks(MCMC = stk_MCMC, original = stk_orig, Cov = stk))

### try SAM internal "simstudy" ####
### "Simulate data from fitted model and re-estimate from each run"

# set.seed(0)
# system.time(fits <- simstudy(fit = fit, nsim = n))
# class(fits) <- "sam_list"
# 
# stk_sim <- SAM2FLStock(object = fits, stk = cod4_stk2)
# plot(FLStocks(Cov = stk, simstudy = stk_sim,
#               original = stk_orig))

### extend stock for MSE simulation ####

### special case for NS cod
### maturity data available for 2018 (based on the IBTS Q1)
### stock weights, M etc in 2018 based on a three year average to enable 
### calculation of SSB
### although SAM estimates F in 2018, this is not reported or taken forward into
### forcasts by the WG
# stk_stf2017 <- stf(window(stk, end = 2017), n_years + 1)
stk_stf2018 <- stf(window(stk, end = 2018), n_years)
### use all available data
stk_stf <- stk_stf2018

### biological data for OM ####
### Resample weights, maturity and natural mortality from the last 5 years 
### (2013-2017)
### set up an array with one resampled year for each projection year 
### (including intermediate year) and replicate
### use the same resampled year for all biological parameters
### this is the approach used in eqsim for North Sea cod
set.seed(2)

### use last five data years to sample biological parameters
sample_yrs <- 2013:2017
### get year position of sample years
sample_yrs_pos <- which(dimnames(stk_stf)$year %in% sample_yrs)

### create samples for biological data (weights, etc.)
### the historical biological parameters are identical for all iterations
### and consequently do not need to be treated individually
### (but keep age structure)
### create vector with resampled years
bio_samples <- sample(x = sample_yrs_pos, 
                      size = (n_years + 1) * n, replace = TRUE)
### do the same for selectivity
sel_samples <- sample(x = sample_yrs_pos, 
                      size = (n_years + 1) * n, replace = TRUE)
### years to be populated
bio_yrs <- which(dimnames(stk_stf)$year %in% 2018:dims(stk_stf)$maxyear)


### insert values
catch.wt(stk_stf)[, bio_yrs] <- c(catch.wt(stk)[, bio_samples,,,, 1])
stock.wt(stk_stf)[, bio_yrs] <- c(stock.wt(stk)[, bio_samples,,,, 1])
landings.wt(stk_stf)[, bio_yrs] <- c(landings.wt(stk)[, bio_samples,,,, 1])
discards.wt(stk_stf)[, bio_yrs] <- c(discards.wt(stk)[, bio_samples,,,, 1])
m(stk_stf)[, bio_yrs] <- c(m(stk)[, bio_samples,,,, 1])
mat(stk_stf)[, bio_yrs] <- c(mat(stk)[, bio_samples,,,, 1])
### maturity data for 2018 exists, re-insert real data
mat(stk_stf)[, ac(2018)] <- mat(stk_orig)[, ac(2018)]
### use different samples for selectivity
harvest(stk_stf)[, bio_yrs] <- c(harvest(stk)[, sel_samples,,,, 1])

if (isTRUE(verbose)) plot(stk_stf)

plot of chunk unnamed-chunk-1

### stock recruitment ####
### fit hockey-stick model
### get residuals from smoothed residuals

### use only data from 1997 and later
sr <- as.FLSR(window(stk_stf, start = 1997), model = "segreg")
### fit model individually to each iteration and suppress output to screen
suppressWarnings(. <- capture.output(sr <- fmle(sr)))
### run in parallel
# library(doParallel)
# cl <- makeCluster(10)
# registerDoParallel(cl)
# sr <- fmle_parallel(sr, cl)
# ### run again for failed iterations
# pos_error <- which(is.na(params(sr)["a"]))
# sr_corrected <- fmle(FLCore::iter(sr, pos_error))
# sr[,,,,, pos_error] <- sr_corrected[]
# params(sr)[, pos_error] <- params(sr_corrected)

if (isTRUE(verbose)) {
  
  plot(sr)
  ### check breakpoints
  summary(params(sr)["b"])
  
  ### plot model and data
  as.data.frame(FLQuants(fitted = sr@fitted, rec = sr@rec, SSB = sr@ssb)) %>%
    mutate(age = NULL,
           year = ifelse(qname == "SSB", year + 1, year)) %>%
    tidyr::spread(key = qname, value = data) %>%
    ggplot() +
    geom_point(aes(x = SSB, y = rec, group = iter), 
               alpha = 0.5, colour = "grey", shape = 1) +
    geom_line(aes(x = SSB, y = fitted, group = iter)) +
    theme_bw() + xlim(0, NA) + ylim(0, NA)
  
  ### Check extent of autocorrelation
  # Not significant, so no need to account for it in this OM
  acf(window(stock.n(stk_orig)[1], start = 1998))
  
  ### Check method proposed for generating recruitment compares with past recruitment estimates
  test <- as.data.frame(FLQuants(fitted = sr@fitted, rec = sr@rec, SSB = sr@ssb))
  test <- mutate(test, age = NULL, year = ifelse(qname == "SSB", year + 1, year))
  test <- tidyr::spread(test, key = qname, value = data)
  test <- test[complete.cases(test),]
  test$res <- rep(NA, nrow(test))
  
  # Generate residuals for future recruitments
  foreach(iter_i = seq(dim(sr)[6]), .packages = "FLCore", 
          .errorhandling = "pass") %do% {
            
            set.seed(iter_i^2)
            
            ### get residuals for current iteration
            res_i <- c(FLCore::iter(residuals(sr), iter_i))
            res_i <- res_i[!is.na(res_i)]
            
            ### calculate kernel density of residuals
            density <- density(x = res_i)
            ### sample residuals
            mu <- sample(x = res_i, size = length(res_i), replace = TRUE)
            ### "smooth", i.e. sample from density distribution
            test$res[test$iter==iter_i] <- rnorm(n = length(res_i), mean = mu, sd = density$bw)
            
          }
  
  # Generate future recruitments from past SSBs and generated residuals
  test$future <- test$fitted * exp(test$res)
  
  # 10 randomly selected iters for plotting
  # should probably increase the number later
  i_samp <- sample(seq(dim(sr)[6]), 10, replace=FALSE)
  
  # Plot past and future stock recruit pairs for selected iters
  ggplot(test[is.element(test$iter, i_samp),]) +
    geom_point(aes(x = SSB, y = rec), 
               alpha = 0.5, colour = "red", shape = 19) +
    geom_point(aes(x = SSB, y = future), 
               alpha = 0.5, colour = "black", shape = 19) +
    geom_line(aes(x = SSB, y = fitted)) +
    facet_wrap(~iter) +
    theme_bw() + xlim(0, NA) + ylim(0, NA)
  
  # Empirical cumulative distributions for the same iters
  ggplot(test[is.element(test$iter, i_samp),]) +
    stat_ecdf(aes(rec), geom = "step", colour = "red") +
    stat_ecdf(aes(future), geom = "step", colour = "black") +
    facet_wrap(~iter) +
    theme_bw() + xlim(0, NA) + ylim(0, NA)
  
  # Combine previous two plots over iters
  # Stock recruit pairs
  ggplot(test[is.element(test$iter, i_samp),]) +
    geom_point(aes(x = SSB, y = rec), 
               alpha = 0.5, colour = "red", shape = 19) +
    geom_point(aes(x = SSB, y = future), 
               alpha = 0.5, colour = "black", shape = 19) +
    theme_bw() + xlim(0, NA) + ylim(0, NA)
  
  # Empirical cumulative distribution
  ggplot(test[is.element(test$iter, i_samp),]) +
    stat_ecdf(aes(rec), geom = "step", colour = "red") +
    stat_ecdf(aes(future), geom = "step", colour = "black") +
    theme_bw() + xlim(0, NA) + ylim(0, NA)
  
  rm(test, i_samp)
}
## Warning in c(ssb) <= b: longer object length is not a multiple of shorter
## object length
## Warning in a * c(ssb): longer object length is not a multiple of shorter
## object length

plot of chunk unnamed-chunk-1

## An object of class "FLPar"

plot of chunk unnamed-chunk-1

### generate residuals for MSE
### years with missing residuals
# NW: dimnames produces NULL for me
# yrs_res <- dimnames(sr)$year[which(is.na(iterMeans(rec(sr))))]
yrs_res <- colnames(rec(sr))[which(is.na(iterMeans(rec(sr))))]

### go through iterations and create residuals
### use kernel density to create smooth distribution of residuals
### and sample from this distribution
res_new <- foreach(iter_i = seq(dim(sr)[6]), .packages = "FLCore", 
                   .errorhandling = "pass") %dopar% {
                     
  set.seed(iter_i)
  
  ### get residuals for current iteration
  res_i <- c(FLCore::iter(residuals(sr), iter_i))
  res_i <- res_i[!is.na(res_i)]
  
  ### calculate kernel density of residuals
  density <- density(x = res_i)
  ### sample residuals
  mu <- sample(x = res_i, size = length(yrs_res), replace = TRUE)
  ### "smooth", i.e. sample from density distribution
  res_new <- rnorm(n = length(yrs_res), mean = mu, sd = density$bw)

  return(res_new)
  
}
## Warning: executing %dopar% sequentially: no parallel backend registered
summary(exp(unlist(res_new)))
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##  0.1215  0.7231  0.9899  1.1293  1.3881  5.1390
### insert into model
residuals(sr)[, yrs_res] <- unlist(res_new)
### exponeniate residuals to get factor
residuals(sr) <- exp(residuals(sr))
sr_res <- residuals(sr)

if (isTRUE(verbose)) plot(sr_res)

plot of chunk unnamed-chunk-1

### process noise ####
### create FLQuant with process noise
### this will be added to the values obtained from fwd() in the MSE

### create noise for process error
set.seed(3)
proc_res <- stock.n(stk_stf) %=% 0 ### template FLQuant
proc_res[] <- stats::rnorm(n = length(proc_res), mean = 0, 
                           sd = uncertainty$proc_error)
### the proc_res values are on a normale scale,
### exponentiate to get log-normal 
proc_res <- exp(proc_res)
### proc_res is a factor by which the numbers at age are multiplied

### for historical period, numbers already include process error from SAM
### -> remove deviation
proc_res[, dimnames(proc_res)$year <= 2017] <- 1

### remove deviation for first age class (recruits)
proc_res[1, ] <- 1

### try saving in stock recruitment model ... 
### this gets passed on to the projection module
fitted(sr) <- proc_res

if (isTRUE(verbose)) plot(proc_res)

plot of chunk unnamed-chunk-1

### stf for 2018: assume catch advice is taken ####
c2018 <- 53058
ctrl <- fwdControl(data.frame(year = 2018, quantity = "catch", 
                              val = c2018))

### project forward for intermediate year (2018)
stk_int <- stk_stf
stk_int[] <- fwd(stk_stf, ctrl = ctrl, sr = sr, sr.residuals = sr_res,
                 sr.residuals.mult = TRUE, maxF = 5)[]
### add process noise
stock.n(stk_int) <- stock.n(stk_int) * proc_res
stock(stk_int)[] <- computeStock(stk_int)

### create stock for MSE simulation
stk_fwd <- stk_stf
### insert values for 2018
stk_fwd[, ac(2018)] <- stk_int[, ac(2018)]
### insert stock number for 2019 in order to calculate SSB at beginning of 
### 2019
stock.n(stk_fwd)[, ac(2019)] <- stock.n(stk_int)[, ac(2019)]
stock(stk_fwd)[, ac(2019)] <- computeStock(stk_fwd[, ac(2019)])

#all.equal(window(stk_fwd, end = 2018), window(stk_stf, end = 2018))

### biological data for OEM ####

### base on OM stock
stk_oem <- stk_fwd

### projection years
proj_yrs <- 2018:range(stk_oem)[["maxyear"]]

### use means of sampled values for projection period
catch.wt(stk_oem)[, ac(proj_yrs)] <- 
  yearMeans(catch.wt(stk_oem)[, ac(sample_yrs)])
landings.wt(stk_oem)[, ac(proj_yrs)] <- 
  yearMeans(landings.wt(stk_oem)[, ac(sample_yrs)])
discards.wt(stk_oem)[, ac(proj_yrs)] <- 
  yearMeans(discards.wt(stk_oem)[, ac(sample_yrs)])
stock.wt(stk_oem)[, ac(proj_yrs)] <- 
  yearMeans(stock.wt(stk_oem)[, ac(sample_yrs)])
m(stk_oem)[, ac(proj_yrs)] <- yearMeans(m(stk_oem)[, ac(sample_yrs)])
### maturity starts one year later because there is data for 2018
mat(stk_oem)[, ac(proj_yrs[-1])] <- yearMeans(mat(stk_oem)[, ac(sample_yrs)])

### remove stock assessment results
stock.n(stk_oem)[] <- stock(stk_oem)[] <- harvest(stk_oem)[] <- NA


### indices ####
### use real FLIndices object as template (included in FLfse)
idx <- cod4_idx
### extend for simulation period
idx <- window(idx, end = yr_data + n_years)
### add iterations
idx <- lapply(idx, propagate, n)

### insert catchability
for (idx_i in seq_along(idx)) {
  
  ### set catchability for projection
  index.q(idx[[idx_i]])[] <- uncertainty$survey_catchability[[idx_i]]
  
}
### create copy of index with original values
idx_raw <- lapply(idx ,index)
### calculate index values
idx <- calc_survey(stk = stk_fwd, idx = idx)

### create deviances for indices
### first, get template
idx_dev <- lapply(idx, index)
### create random noise based on sd
set.seed(4)
for (idx_i in seq_along(idx_dev)) {
  ### insert sd
  idx_dev[[idx_i]][] <- uncertainty$survey_sd[[idx_i]]
  ### noise
  idx_dev[[idx_i]][] <- stats::rnorm(n = length(idx_dev[[idx_i]]),
                                     mean = 0, sd = idx_dev[[idx_i]])
  ### exponentiate to get from normal to log-normal scale
  idx_dev[[idx_i]] <- exp(idx_dev[[idx_i]])
}

### modify residuals for historical period so that index values passed to 
### stock assessment are the ones observed in reality
### IBTS Q1, values up to 2018
idx_dev$IBTS_Q1_gam[, dimnames(idx_dev$IBTS_Q1_gam)$year <= 2018] <- 
  idx_raw$IBTS_Q1_gam[, dimnames(idx_raw$IBTS_Q1_gam)$year <= 2018] /
  index(idx$IBTS_Q1_gam)[, dimnames(idx$IBTS_Q1_gam@index)$year <= 2018]
### IBTS Q3, values up to 2017
idx_dev$IBTS_Q3_gam[, dimnames(idx_dev$IBTS_Q3_gam)$year <= 2017] <- 
  idx_raw$IBTS_Q3_gam[, dimnames(idx_raw$IBTS_Q3_gam)$year <= 2017] /
  index(idx$IBTS_Q3_gam)[, dimnames(idx$IBTS_Q3_gam@index)$year <= 2017]

if (isTRUE(verbose)) {

  ### compare simulated to original survey(s)
  as.data.frame(FLQuants(cod4_q1 = index(cod4_idx$IBTS_Q1_gam), 
                         cod4_q3 = index(cod4_idx$IBTS_Q3_gam),
                         sim_q1 = (index(idx$IBTS_Q1_gam)),
                         sim_q3 = (index(idx$IBTS_Q3_gam))
  )) %>%
    mutate(survey = ifelse(grepl(x = qname, pattern = "*_q1$"), "Q1", "Q3"),
           source = ifelse(grepl(x = qname, pattern = "^sim*"), "sim", "data")) %>%
    filter(year <= 2019) %>%
    ggplot(aes(x = year, y = data, colour = source)) +
    facet_grid(paste("age", age) ~ paste("IBTS", survey), scales = "free_y") +
    stat_summary(fun.y = quantile, fun.args = 0.25, geom = "line",
                 alpha = 0.5) +
    stat_summary(fun.y = quantile, fun.args = 0.75, geom = "line",
                 alpha = 0.5) +
    stat_summary(fun.y = median, geom = "line") +
    theme_bw()

}

plot of chunk unnamed-chunk-1

### check survey
# idx0 <- calc_survey(stk = stk_fwd, idx = idx)
# idx0 <- lapply(seq_along(idx0), function(idx_i) {
#   idx_tmp <- idx0[[idx_i]]
#   index(idx_tmp) <- index(idx_tmp) * idx_dev[[idx_i]]
#   return(idx_tmp)
# })
# plot(index(idx0[[2]]))

### catch noise ####
### take estimates from sam: uncertainty$catch_sd is "logSdLogObs"
### assume catch observed by SAM in projection is log-normally distributed
### around operating model catch

### create noise for catch
set.seed(5)
catch_res <- catch.n(stk_fwd) %=% 0 ### template FLQuant
catch_res[] <- stats::rnorm(n = length(catch_res), mean = 0, 
                            sd = uncertainty$catch_sd)
### the catch_res values are on a normale scale,
### exponentiate to get log-normal 
catch_res <- exp(catch_res)
### catch_res is a factor by which the numbers at age are multiplied

### for historical period, pass on real observed catch
### -> remove deviation
catch_res[, dimnames(catch_res)$year <= 2017] <- 1

if (isTRUE(verbose)) plot(catch_res, probs = c(0.05, 0.25, 0.5, 0.75, 0.95))

plot of chunk unnamed-chunk-1

### check SAM ####
# 
# stk_tmp <- window(stk_stf, end = 2018)
# catch.wt(stk_tmp)[,ac(2018)] <- landings.wt(stk_tmp)[,ac(2018)] <-
#   discards.wt(stk_tmp)[,ac(2018)] <- NA
# stk_tmp <- stk_tmp[,,,,, 1:10]
# idx_tmp <- window(idx, end = 2018)
# idx_tmp[[2]] <- window(idx_tmp[[2]], end = 2017)
# idx_tmp <- lapply(idx_tmp, FLCore::iter, 1:10)
# 
# fit3 <- FLR_SAM(stk = stk_tmp, 
#                idx = idx_tmp, conf = cod4_conf_sam)
# stk3 <- SAM2FLStock(fit3)
# plot(iter(FLStocks(cod4 = stk, sim = stk3), 1))
# 
# 

### save OM ####

### path
input_path <- paste0("input/cod4/", n, "_", n_years, "/")
dir.create(input_path)
## Warning in dir.create(input_path): 'input\cod4\1000_20' already exists
### stock
saveRDS(stk_fwd, file = paste0(input_path, "stk.rds"))
### stock recruitment
saveRDS(sr, file = paste0(input_path, "sr.rds"))
### recruitment residuals
saveRDS(sr_res, file = paste0(input_path, "sr_res.rds"))
### surveys
saveRDS(idx, file = paste0(input_path, "idx.rds"))
saveRDS(idx_dev, file = paste0(input_path, "idx_dev.rds"))
### catch noise
saveRDS(catch_res, file = paste0(input_path, "catch_res.rds"))
### process error
saveRDS(proc_res, file = paste0(input_path, "proc_res.rds"))
### observed stock
saveRDS(stk_oem, file = paste0(input_path, "stk_oem.rds"))
### sam initial parameters
saveRDS(sam_initial, file = paste0(input_path, "sam_initial.rds"))
### sam configuration
saveRDS(cod4_conf_sam_no_mult, file = paste0(input_path, "cod4_conf_sam_no_mult"))
### catch numbers
saveRDS(catch_n, file = paste0(input_path, "catch_n.rds"))
save.image(file = paste0(input_path, "image.RData"))

# stk_fwd <- readRDS(file = paste0(input_path, "stk.rds"))
# sr <- readRDS(file = paste0(input_path, "sr.rds"))
# sr_res <- readRDS(file = paste0(input_path, "sr_res.rds"))
# idx <- readRDS(file = paste0(input_path, "idx.rds"))
# idx_dev <- readRDS(file = paste0(input_path, "idx_dev.rds"))
# catch_res <- readRDS(file = paste0(input_path, "catch_res.rds"))
# proc_res <- readRDS(file = paste0(input_path, "proc_res.rds"))
# stk_oem <- readRDS(file = paste0(input_path, "stk_oem.rds"))
# sam_initial <- readRDS(file = paste0(input_path, "sam_initial.rds"))
# cod4_conf_sam_no_mult <- readRDS(file = paste0(input_path, 
#                                                "cod4_conf_sam_no_mult"))

### prepare objects for new a4a standard mse package ####
### https://github.com/flr/mse

### save workspace to start from here
# save.image(file = "input/cod4/image_10.RData")
# load(file = "input/cod4/image_10.RData")

### reference points
refpts_mse <- list(Btrigger = 150000,
                   Ftrgt = 0.31,
                   Fpa = 0.39,
                   Bpa = 150000,
                   Blim = 107000)
### some specifications for short term forecast with SAM
cod4_stf_def <- list(fwd_yrs_average = -3:0,
                     fwd_yrs_rec_start = 1998,
                     fwd_yrs_sel = -3:-1,
                     fwd_yrs_lf_remove = -2:-1,
                     fwd_splitLD = TRUE)

### some arguments (passed to mp())
genArgs <- list(fy = dims(stk_fwd)$maxyear, ### final simulation year
                y0 = dims(stk_fwd)$minyear, ### first data year
                iy = yr_data, ### first simulation (intermediate) year
                nsqy = 3, ### not used, but has to provided
                nblocks = 1, ### block for parallel processing
                seed = 1 ### random number seed before starting MSE
)

### operating model
om <- FLom(stock = stk_fwd, ### stock 
           sr = sr, ### stock recruitment and precompiled residuals
           projection = mseCtrl(method = fwd_WKNSMSE, 
                                args = list(maxF = 2,
                                            ### process noise on stock.n
                                            proc_res = "fitted"
                                ))
)

### observation (error) model
oem <- FLoem(method = oem_WKNSMSE,
             observations = list(stk = stk_oem, idx = idx), 
             deviances = list(stk = FLQuants(catch.dev = catch_res), 
                              idx = idx_dev),
             args = list(idx_timing = c(0, -1),
                         catch_timing = -1,
                         use_catch_residuals = TRUE, 
                         use_idx_residuals = TRUE,
                         use_stk_oem = TRUE))
### implementation error model (banking and borrowing)
# iem <- FLiem(method = iem_WKNSMSE, 
#              args = list(BB = TRUE))

### default management
ctrl_obj <- mpCtrl(list(
  ctrl.est = mseCtrl(method = SAM_wrapper,
                     args = c(### short term forecast specifications
                       forecast = TRUE, 
                       fwd_trgt = "fsq", fwd_yrs = 1, 
                       cod4_stf_def,
                       ### speeding SAM up
                       newtonsteps = 0, rel.tol = 0.001,
                       par_ini = list(sam_initial),
                       track_ini = TRUE, ### store ini for next year
                       ### SAM model specifications
                       conf = list(cod4_conf_sam_no_mult),
                       parallel = FALSE ### TESTING ONLY
                     )),
  ctrl.phcr = mseCtrl(method = phcr_WKNSMSE,
                      args = refpts_mse),
  ctrl.hcr = mseCtrl(method = hcr_WKNSME, args = list(option = "A")),
  ctrl.is = mseCtrl(method = is_WKNSMSE, 
                    args = c(hcrpars = list(refpts_mse),
                             ### for short term forecast
                             fwd_trgt = list(c("fsq", "hcr")), fwd_yrs = 2,
                             cod4_stf_def#,
                             ### TAC constraint
                             #TAC_constraint = TRUE,
                             #lower = -Inf, upper = Inf,
                             #Btrigger_cond = FALSE,
                             ### banking and borrowing 
                             #BB = TRUE,
                             #BB_check_hcr = FALSE,
                             #BB_check_fc = TRUE,
                             #BB_rho = list(c(-0.1, 0.1))
                    ))#,
  #ctrl.tm = NULL
))
### additional tracking metrics
tracking_add <- c("BB_return", "BB_bank_use", "BB_bank", "BB_borrow")

### save mse objects
input <- list(om = om, oem = oem, ctrl.mp = ctrl_obj,
              genArgs = genArgs, tracking = tracking_add)
saveRDS(object = input, 
        file = paste0(input_path, "base_run.rds"))
# input <- readRDS(paste0(input_path, "/base_run.rds"))

### run MSE ####


### run MSE
### WARNING: takes a while...
### check normal execution
# res1 <- mp(om = input$om,
#            oem = input$oem,
#            #iem = iem,
#            ctrl.mp = input$ctrl.mp,
#            genArgs = input$genArgs,
#            tracking = input$tracking)



### create MSE input objects for running fixed F=0 ####

# ### load image with objects for 10,000 iterations and 100 years
# load(file = "input/cod4/10000_100/image.RData")
# ### genArgs
# genArgs_F0 <- list(fy = dims(stk_fwd)$maxyear, ### final simulation year
#                    y0 = dims(stk_fwd)$minyear, ### first data year
#                    iy = yr_data, ### first simulation (intermediate) year
#                    nsqy = 3, ### not used, but has to provided
#                    nblocks = 1, ### block for parallel processing
#                    seed = 1 ### random number seed before starting MSE
# )
# ### OM
# om_F0 <- FLom(stock = stk_fwd, sr = sr,
#               projection = mseCtrl(method = fwd_WKNSMSE, 
#                                    args = list(maxF = 2,
#                                                proc_res = "fitted"
#                                                )))
# ### define target
# ctrl_F0 <- mpCtrl(list(
#   ctrl.hcr = mseCtrl(method = fixedF.hcr, 
#                      args = list(ftrg = 0))))
# ### fake OEM, otherwise mp falls over...
# oem_F0 <- FLoem(observations = list(stk = FLQuant(0)), 
#                 deviances = list(stk = FLQuant(0))
# )
# 
# ### combine elements
# input_F0 <- list(om = om_F0, oem = oem_F0, ctrl.mp = ctrl_F0, 
#                  genArgs = genArgs_F0)
# 
# ### save
# saveRDS(object = input_F0, file = "input/cod4/10000_100/data_F0.RData")

### create Rmarkdown file
# knitr::spin(hair = "OM.R", format = "Rmd", precious = TRUE, comment = c('^### ------------------------------------------------------------------------ ###$', '^### ------------------------------------------------------------------------ ###$'))