#' Simulates the Equilibrium Results for a Population.
#'
#' Simulate a fish stock forward in time given biological parameters, fishery
#' parameters and advice parameters.
#'
#' @param fit A list returned from the function fitModels
#' @param bio.years The years to sample maturity, weights and M from, given as
#' a vector of length 2, i.e. c(2010, 2015) select from the
#' years 2010 to 2015 inclusive.
#' @param bio.const A flag (default FALSE), if TRUE mean of the biological values from the
#' years selected are used
#' @param sel.years The years to sample the selection patterns from, given as
#' a vector of length 2, i.e. c(2010, 2015) select from the
#' years 2010 to 2015 inclusive.
#' @param sel.const A flag (default FALSE), if TRUE mean of the selection patterns from the
#' years selected are used
#' @param Fscan F values to scan over, i.e. seq(0, 2, by = 0.05)
#' @param Fcv Assessment error in the advisory year
#' @param Fphi Autocorrelation in assessment error in the advisory year
#' @param SSBcv Spawning stock biomass error in the advisory year
#' @param rhologRec A flag for recruitment autocorrelation, default (TRUE), or a
#' vector of numeric values specifcying the autocorrelation
#' parameter for the residuals for each SR model.
#' @param Blim SSB limit reference point
#' @param Bpa SSB precuationary reference point
#' @param recruitment.trim A numeric vector with two log-value clipping the
#' extreme recruitment values from a continuous lognormal distribution.
#' The values must be set as c("high","low").
#' @param Btrigger If other than 0 (default) the target F applied is reduced by
#' SSB/Btrigger. This is the "ICES Advice Rule".
#' @param Nrun The number of years to run in total (the last 50 years from that
#' will be retained to compute equilibrium values from)
#' @param process.error Use stochastic recruitment or mean recruitment?
#' TRUE (default) uses the predictive distribution of recruitment,
#' model estimate of recruitment + simulated observation
#' error. FALSE uses model prediction of recruitment with
#' no observation error.
#' @param verbose Flag, if TRUE (default) indication of the progress of the
#' simulation is provided in the console. Useful to turn to FALSE when
#' knitting documents.
#' @param extreme.trim a pair of quantiles (low, high) which are used to trim
#' the equilibrium catch values, across simulations within
#' an F scenario, when calculating the mean catch and
#' landings for that F scenario. These mean values
#' calculated accross simulations within an F scenario
#' are used to find which F scenario gave the maximum catch.
#' \code{extreme.trim} can therefore be used to stablise the
#' estimate of mean equilibrium catch and landings by F
#' scenario. The default is c(0, 1) which includes all the
#' data and is effectively an untrimmed mean.
#' @param R.initial Initial recruitment for the simulations. This is common
#' accross all simulations. Default = mean of all recruitments
#' in the series.
#' @param keep.sims Flag, if TRUE returns a matrix of population tragectories
#' for each value of F in Fscan (see examples).
#' @return
#' A list containing the results from the forward simulation and the reference
#' points calculated from it.
#'
#' @details
#' Details of the steps required to evaluate reference points are given in
#' ICES (2017). WHile, details of the calculation of MSY ranges is given in
#' ICES (2015).
#'
#' @references
#' ICES (2015) Report of the Workshop to consider F MSY ranges for stocks in
#' ICES categories 1 and 2 in Western Waters (WKMSYREF4).
#' \href{http://ices.dk/sites/pub/Publication\%20Reports/Expert\%20Group\%20Report/acom/2015/WKMSYREF4/01\%20WKMSYREF4\%20Report.pdf}{01
#' WKMSYREF4 Report.pdf}
#'
#' ICES (2017) ICES fisheries management reference points for category 1 and 2
#' stocks.
#' DOI: \href{https://doi.org/10.17895/ices.pub.3036}{10.17895/ices.pub.3036}
#'
#' @seealso
#'
#' \code{\link{eqsr_fit}} fits multiple stock recruitment models to a data set.
#'
#' \code{\link{eqsr_plot}} plots the results from eqsr_fit.
#'
#' \code{\link{eqsim_plot}} summary plot of the forward simulation showing estimates
#' of various reference points.
#'
#' \code{\link{eqsim_plot_range}} summary plots of the forward simulation showing
#' the estimates of MSY ranges (ICES, 2015)
#'
#' \code{\link{msy-package}} gives an overview of the package.
#'
#' @examples
#' \dontrun{
#' data(icesStocks)
#' FIT <- eqsr_fit(icesStocks$saiNS,
#' nsamp = 1000,
#' models = c("Ricker", "Segreg"))
#' SIM <-
#' eqsim_run(
#' FIT,
#' bio.years = c(2004, 2013),
#' sel.years = c(2004, 2013),
#' Fcv = 0.24,
#' Fphi = 0.42,
#' Blim = 106000,
#' Bpa = 200000,
#' Fscan = seq(0, 1.2, len = 40)
#' )
#'
#' # extract tragectories
#' ssbsim <- SIM$rbya$ssb
#' years <- SIM$rbya$simyears
#' models <- SIM$rbya$srmodels$model
#' Ftarget <- SIM$rbya$Ftarget
#'
#' Fval <- which(Ftarget == 0)
#' Fval <- which(Ftarget > .3)[1]
#' x <- ssbsim[Fval,,]
#' df <- data.frame(year = 1:nrow(x),
#' ssb = c(x),
#' sim = rep(1:ncol(x), each = nrow(x)),
#' model = rep(models, each = nrow(x)))
#' xyplot(ssb ~ year | model, groups = sim, data = df, type = "l", col = grey(0.5, alpha = 0.5))
#'
#' fit <- density(x[x>1e-3], from = 0)
#' plot(fit$x,fit$y*mean(x>1e-3),col="red", type = "l")
#' lines(x = 0, y = mean(x<=1e-3), type = "h", lwd = 3)
#'
#' }
#'
#' @export
eqsim_run <- function(fit,
bio.years = c(-5, -1) + FLCore::dims(fit$stk)$maxyear, # years sample weights, M and mat
bio.const = FALSE,
sel.years= c(-5, -1) + FLCore::dims(fit$stk)$maxyear, # years sample sel and discard proportion by number from
sel.const = FALSE,
Fscan = seq(0, 2, len = 40), # F values to scan over
Fcv = 0,
Fphi = 0,
SSBcv = 0,
rhologRec = TRUE,
Blim,
Bpa,
recruitment.trim = c(3, -3),
Btrigger = 0,
Nrun = 200, # number of years to run in total
process.error = TRUE, # use predictive recruitment or mean recruitment? (TRUE = predictive)
verbose = TRUE,
extreme.trim = c(0, 1),
R.initial = mean(fit$rby$rec),
keep.sims = FALSE)
{
if (abs(Fphi) >= 1) stop("Fphi, the autocorelation parameter for log F should be between (-1, 1)")
if (diff(recruitment.trim) > 0) stop("recruitment truncation must be given as c(high, low)")
# commented out as above line is a better check
# if ((recruitment.trim[1] + recruitment.trim[2]) > 0) stop("recruitment truncation must be between a high - low range")
if (verbose) icesTAF::msg("Setting up...")
if (length(bio.years) > 2)
stop("bio.years must be given as a length two vector: c(first, last)")
if (length(sel.years) > 2)
stop("sel.years must be given as a length two vector: c(first, last)")
btyr1 <- bio.years[1]
btyr2 <- bio.years[2]
slyr1 <- sel.years[1]
slyr2 <- sel.years[2]
# Keep at most 50 simulation years (which will be the last 50 of the Nrun
# forward simulated years)
keep <- min(Nrun, 50)
SR <- fit $ sr.sto
data <- fit $ rby[,c("rec","ssb","year")]
stk <- fit $ stk
# forecast settings (mean wt etc)
stk.win <- FLCore::window(stk, start = btyr1, end = btyr2)
stk.winsel <- FLCore::window(stk, start = slyr1 , end = slyr2)
littleHelper <- function(x,i) {
x2 <- x
x2[i] <- NA
x2[] <- apply(x2,1,mean,na.rm=TRUE)
x[i] <- x2[i]
return(x)
}
west <- matrix(FLCore::stock.wt(stk.win), ncol = btyr2 - btyr1 + 1)
i <- west == 0
if(any(i)) west <- littleHelper(west,i)
weca <- matrix(FLCore::catch.wt(stk.win), ncol = btyr2 - btyr1 + 1)
i <- weca == 0
if(any(i)) weca <- littleHelper(weca,i)
wela <- matrix(FLCore::landings.wt(stk.win), ncol = btyr2 - btyr1 + 1)
if(any(i)) wela <- littleHelper(wela,i)
Mat <- matrix(FLCore::mat(stk.win), ncol = btyr2 - btyr1 + 1)
M <- matrix(FLCore::m(stk.win), ncol = btyr2 - btyr1 + 1)
landings <- matrix(FLCore::landings.n(stk.winsel), ncol = slyr2 - slyr1 + 1)
# if zero, use 0.10 of minimum value
catch <- matrix(FLCore::catch.n(stk.winsel), ncol = slyr2 - slyr1 + 1)
sel <- matrix(FLCore::harvest(stk.winsel), ncol = slyr2 - slyr1 + 1)
Fbar <- matrix(FLCore::fbar(stk.winsel), ncol = slyr2 - slyr1 + 1)
sel <- sweep(sel, 2, Fbar, "/")
if (sel.const == TRUE) { # take means of selection
sel[] <- apply(sel, 1, mean)
landings[] <- apply(landings, 1, mean)
catch[] <- apply(catch, 1, mean)
}
# 22.2.2014 Added weight of landings per comment from Carmen
if (bio.const==TRUE){ # take means of wts Mat and M and ratio of landings to catch
west[] <- apply(west, 1, mean)
weca[] <- apply(weca, 1, mean)
wela[] <- apply(wela, 1, mean)
Mat[] <- apply(Mat, 1, mean)
M[] <- apply(M, 1, mean) #me
}
land.cat= landings / catch # ratio of number of landings to catch
# TODO: Check if this is sensible
i <- is.na(land.cat)
if(any(i)) land.cat[i] <- 1
Fprop <- apply(FLCore::harvest.spwn(stk.winsel), 1, mean)[drop=TRUE] # vmean(harvest.spwn(stk.win))
Mprop <- apply(FLCore::m.spwn(stk.win), 1, mean)[drop=TRUE] # mean(m.spwn(stk.win))
# get ready for the simulations
Nmod <- nrow(SR)
NF <- length(Fscan)
ages <- FLCore::dims(stk)$age
ssb_lag <- fit$rby$ssb_lag[1]
ssby <- Ferr <- array(0, c(Nrun,Nmod),dimnames=list(year=1:Nrun,iter=1:Nmod))
Ny <- Fy <- WSy <- WCy <- Cy <- Wy <- Wl <- Ry <-
array(0, c(ages, Nrun, Nmod),
dimnames = list(age = (range(stk)[1]:range(stk)[2]),
year = 1:Nrun,
iter = 1:Nmod))
# TODO per note from Carmen:
# NOTE: If we want Ferr to be a stationary AR(1) process, it would make
# more sense to initialise Ferr as a Normal dist with zero mean and
# standard deviation of AR(1) marginal distribution, i.e. standard
# deviation of initial Ferr = Fcv/sqrt(1- Fphi^2), instead of just
# initialising Ferr=0
# 2014-03-12: Changed per note form Carmen/John
Ferr[1,] <- stats::rnorm(n=Nmod, mean=0, sd=1)*Fcv/sqrt(1-Fphi^2)
for(j in 2:Nrun)
Ferr[j,] <- Fphi * Ferr[j-1,] + Fcv * stats::rnorm(n = Nmod, mean = 0, sd = 1)
# 2014-03-12: Changed per note form Carmen/John
# Errors in SSB: this is used when the ICES MSY HCR is applied for F
SSBerr <- matrix(stats::rnorm(n = Nrun * Nmod, mean = 0, sd = 1), ncol = Nmod) * SSBcv
rsam <- array(sample(1:ncol(weca), Nrun * Nmod, TRUE), c(Nrun, Nmod))
rsamsel <- array(sample(1:ncol(sel), Nrun * Nmod, TRUE), c(Nrun, Nmod))
Wy[] <- c(weca[, c(rsam)])
Wl[] <- c(wela[, c(rsam)])
Ry[] <- c(land.cat[, c(rsamsel)])
# initial recruitment
R <- R.initial
# set up arrays to contain simulations
ssbs <- cats <- lans <- recs <- array(0, c(7, NF))
ferr <- ssbsa <- catsa <- lansa <- recsa <- array(0, c(NF, keep, Nmod))
if (keep.sims) {
# keep all ssbs
ssbsall <- catsall <- lansall <- recsall <- array(0, c(NF, Nrun, Nmod))
}
begin <- Nrun - keep + 1
# New from Simmonds' 29.1.2014
# Residuals of SR fits (1 value per SR fit and per simulation year
# but the same residual value for all Fscan values):
resids= array(stats::rnorm(Nmod*(Nrun+1), 0, SR$cv),c(Nmod, Nrun+1))
# 2014-03-12: Changed per note form Carmen/John
# Autocorrelation in Recruitment Residuals:
if(rhologRec==TRUE){
fittedlogRec <- do.call(cbind, lapply( c(1:nrow(fit$sr.sto)), function(i){
FUN <- match.fun(fit$sr.sto$model[i])
FUN(fit$sr.sto[i, ], fit$rby$ssb) } ) )
# Calculate lag 1 autocorrelation of residuals:
rhologRec <- apply(log(fit$rby$rec)-fittedlogRec, 2, function(x){stats::cor(x[-length(x)],x[-1])})
}
if (is.numeric(rhologRec)) {
# Draw residuals according to AR(1) process:
for(j in 2:(Nrun+1)){ resids[,j] <- rhologRec * resids[,j-1] + resids[,j]*sqrt(1 - rhologRec^2) }
}
# Limit how extreme the Rec residuals can get:
lims = t(array(SR$cv,c(Nmod,2))) * recruitment.trim
for (k in 1:Nmod) { resids[k,resids[k,]>lims[1,k]]=lims[1,k]}
for (k in 1:Nmod) { resids[k,resids[k,]<lims[2,k]]=lims[2,k]}
# end New from Simmonds 29.1.2014
if (verbose) icesTAF::msg("Running forward simulations.")
if (verbose) loader(0)
# Looping over each F value in Fscan. For each of the Nmod SR fits
# (replicates), do a forward simulation during Nrun years
# There are Rec residuals for each SR fit and year, which take the same
# values for all Fscan
for (i in 1:NF) {
# The F value to test
Fbar <- Fscan[i]
############################################################################
# Population in simulation year 1:
# Zpre: Z that occurs before spawning
Zpre <- Fbar * sel[,rsamsel[1,]] * Fprop + M[,rsam[1,]] * Mprop
# Zpos: Z that occurs after spawning
# Zpos not used anywhere
Zpos <- Fbar * (1-Fprop) * sel[,rsamsel[1,]] + M[,rsam[1,]] * (1-Mprop)
# run Z out to age 50 for plus group...
# TODO:
# Comments from Carmen: Zcum is a cumulative sum:
# There is a matrix of F-at-age and a matrix of M-at-age (each has 49 ages, Nmod replicates)
# The F and M matrices are summed, giving Z-at-age (49 ages, Nmod replicates)
Ztot <- Fbar * sel[c(1:ages, rep(ages, 49 - ages)), rsamsel[1,]] + M[c(1:ages, rep(ages, 49 - ages)), rsam[1,]]
Zcum <- apply(Ztot, 2, function(x) c(0, cumsum(x)))
# create initial population structure
N1 <- R * exp(- unname(Zcum))
# set up age structure out to age 50 in first years for all simulations
Ny[,1,] <- rbind(N1[1:(ages-1),], colSums(N1[ages:50,]))
# calculate ssb in first year using a different stock.wt and Mat selection and M for each simulation
ssby[1,] <- colSums(Mat[,rsam[1,]] * Ny[,1,] * west[,rsam[1,]] / exp(Zpre))
# if rec recruiting year class comes from previous years ssb, as in fish recruiting
# at age 2 or winter ring herring ageing then run some more initial years
# using the same intial population
# - NOTE roll forward one year incase ssb_lag is 0 so that we always have a year j-1.
for (j in 2:pmax(2, ssb_lag + 2)) {
Ny[,j,] <- rbind(N1[1:(ages-1),], colSums(N1[ages:50,]))
ssby[j,] <- colSums(Mat[,rsam[j-1,]] * Ny[,1,] * west[,rsam[j-1,]] / exp(Zpre))
}
# Years (2 + ssb_lag) to Nrun:
for (j in (2+ssb_lag):Nrun) {
# year j is the projection year,
# year j-1 is where fishing is going to take place
# conceptually the assessment takes place in year j-2
# apply HCR
# (intended) Fbar to be applied in year j-1 (depends on SSB in year j-1):
# 2014-03-12: Changed per note form Carmen/John
# Fnext <- Fbar * pmin(1, SSB/Btrigger)
Fnext <- Fbar * pmin(1, ssby[j-1,] * exp(SSBerr[j-1,]) / Btrigger)
# apply some noise to the F
# Notes from Carmen:
# Assessment and/or implementation error (modifies intended F to get
# realised F)
# Error: AR(1) process on log(F) with autocorrel = Fphi, and
# conditional stand deviation = Fcv
# Might make more sense to have the "Ferr" matrix calculated before
# the Fscan loop starts so that the same errors in F are applied to
# all Fscan values ???? (as for Rec residuals)
# Outcommented 2014-03-12 because F-error already been drawn outside the
# loop, so this line here is no longer needed:
# Ferr[j,] <- Fphi * Ferr[j-1,] + rnorm(Nmod, 0, Fcv)
# realised Fbar in year j-1:
Fnext <- exp(Ferr[j,]) * Fnext
# get a selection pattern for each simulation and apply this to get N
Zpre <- rep(Fnext, each = length(Fprop)) * Fprop * sel[, rsamsel[j-1,]] + M[, rsam[j-1,]] * Mprop
# get Fy
Fy[ , j-1, ] <- rep(Fnext, each = ages) * sel[, rsamsel[j-1,]]
# roll population one year forward having decided in the F value
Ny[ -1, j, ] <- Ny[1:(ages-1), j-1, ] * exp(-Fy[1:(ages-1), j-1, ] - M[1:(ages-1), rsam[j-1,]])
# calculate plus group
Ny[ages, j, ] <- Ny[ages, j, ] + Ny[ages, j-1, ] * exp(-Fy[ages, j-1, ] - M[ages, rsam[j-1,]])
if (ssb_lag == 0) {
# calculate ssb ignores contribution of recruiting age 0 fish
ssby[j, ] <- apply(array(Mat[, rsam[j,]] * Ny[,j,] * west[, rsam[j,]] / exp(Zpre), c(ages, Nmod)), 2, sum)
}
# simulate recruitment in year j
# get ssb from appropriate year, if ssb_lag is zero, then current year ssb is used
SSBforRec <- ssby[j-ssb_lag,]
# predict recruitment using various models
if (process.error) {
# Changes 29.1.2014
# new random draws each time
# allrecs <- sapply(unique(SR $ mod), function(mod) exp(match.fun(mod) (SR, SSB) + rnorm(Nmod, 0, SR $ cv)))
# same random draws used for each F
###### 2014-03-13 TMP COMMENT - ERROR OCCURS HERE
allrecs <- sapply(unique(SR$mod), function(mod) exp(match.fun(mod)(SR, SSBforRec) + resids[,j]))
# end Changes 29.1.2014
} else {
allrecs <- sapply(unique(SR$mod), function(mod) exp(match.fun(mod) (SR, SSBforRec)))
}
# Comment from Carmen:
# For each of the Nmod replicates, this selects the appropriate SR model
# type to use in that replicate
# Note that the order of SR model types that comes out in "select" is
# not necessarily the same order in which the SR model types were
# entered as inputs -- I presume the **next 2 lines** of code have
# been checked to avoid potential bugs due to this reordering ????
select <- cbind(seq(Nmod), as.numeric(factor(SR$mod, levels = unique(SR$mod))))
Ny[1,j,] <- allrecs[select]
# calculate ssb now we have the recruiting age class abundance
ssby[j, ] <- apply(array(Mat[, rsam[j,]] * Ny[,j,] * west[, rsam[j,]] / exp(Zpre), c(ages, Nmod)), 2, sum)
# calculate catch.n (should this be j-1? does it matter?)
Cy[, j, ] <- Ny[, j-1, ] * Fy[, j-1, ] / (Fy[, j-1, ] + M[, rsam[j-1,]]) * (1 - exp(-Fy[, j-1, ] - M[, rsam[j-1,]]))
}
# convert to catch weight
Cw <- Cy * Wy # catch Numbers *catch wts
land <- Cy * Ry * Wl # catch Numbers * Fraction (in number) landed and landed wts
Lan <- apply(land, 2:3, sum)
Cat <- apply(Cw, 2:3, sum)
# summarise everything and spit out!
ferr[i, , ] <- Ferr[begin:Nrun, ]
ssbsa[i, , ] <- ssby[begin:Nrun, ]
catsa[i, , ] <- Cat[begin:Nrun, ]
lansa[i, , ] <- Lan[begin:Nrun, ]
recsa[i, , ] <- Ny[1, begin:Nrun, ]
# store quantiles
quants <- c(0.025, 0.05, 0.25, 0.5, 0.75, 0.95, 0.975)
ssbs[, i] <- stats::quantile(ssbsa[i, , ], quants)
cats[, i] <- stats::quantile(catsa[i, , ], quants)
lans[, i] <- stats::quantile(lansa[i, , ], quants)
recs[, i] <- stats::quantile(recsa[i, , ], quants)
# if user has requested full simulations
if (keep.sims) {
ssbsall[i, , ] <- ssby
catsall[i, , ] <- Cat
lansall[i, , ] <- Lan
recsall[i, , ] <- Ny[1,,]
}
if (verbose) loader(i/NF)
}
if (verbose) icesTAF::msg("Summarising simulations")
dimnames(ssbs) <- dimnames(cats) <-
dimnames(lans) <- dimnames(recs) <-
list(quants=c("p025","p05","p25","p50","p75","p95","p975"),
fmort=Fscan)
rbp2dataframe <- function(x,variable) {
x <- data.frame(t(x))
x$variable <- variable
x$Ftarget <- as.numeric(row.names(x))
rownames(x) <- NULL
return(x)
}
rbp <- rbind(rbp2dataframe(recs,"Recruitment"),
rbp2dataframe(ssbs,"Spawning stock biomass"),
rbp2dataframe(cats,"Catch"),
rbp2dataframe(lans,"Landings"))
rbp <- rbp[,c(9,8,1:7)]
# STOCK REFERENCE POINTS
FCrash05 <- Fscan[which.max(cats[2,]):NF][ which(cats[2, which.max(cats[2,]):NF] < 0.05*max(cats[2,]) )[1] ]
FCrash50 <- Fscan[which.max(cats[4,]):NF][ which(cats[4, which.max(cats[4,]):NF] < 0.05*max(cats[4,]) )[1] ]
# Einar amended 30.1.2014
if(missing(extreme.trim)) {
catm <- apply(catsa, 1, mean)
lanm <- apply(lansa, 1, mean)
} else {
# 2014-03-12 Outcommented per note from Carmen/John - see below
#x <- catsa
#i <- x > quantile(x,extreme.trim[2]) |
# x < quantile(x,extreme.trim[1])
#x[i] <- NA
#catm <- apply(x, 1, mean, na.rm=TRUE)
#
#x <- lansa
#i <- x > quantile(x,extreme.trim[2]) |
# x < quantile(x,extreme.trim[1])
#x[i] <- NA
#lanm <- apply(x, 1, mean, na.rm=TRUE)
# 2014-03-12: Above replaced with the following per note from Carmen/John
# If we want to remove whole SR models, we could use the following code. But it is too extreme, it ends up getting rid of most models:
# auxi2 <- array( apply(catsa, 1, function(x){auxi<-rep(TRUE,Nmod); auxi[x > quantile(x, extreme.trim[2]) | x < quantile(x, extreme.trim[1])] <- FALSE; x <- auxi } ), dim=c(keep,Nmod,NF))
# auxi2 <- (1:Nmod)[apply(auxi2, 2, function(x){length(unique(as.vector(x)))})==1]
# apply(catsa[,,auxi2],1,mean)
# So I think the alternative is not to get rid of whole SR models, but of different SR models depending on the value of F:
catm <- apply(catsa, 1, function(x){mean(x[x <= stats::quantile(x, extreme.trim[2]) & x >= stats::quantile(x, extreme.trim[1])])})
lanm <- apply(lansa, 1, function(x){mean(x[x <= stats::quantile(x, extreme.trim[2]) & x >= stats::quantile(x, extreme.trim[1])])})
}
# end Einar amended 30.1.2014
maxcatm <- which.max(catm)
maxlanm <- which.max(lanm)
# Einar added 29.1.2014
rbp$Mean <- NA
rbp$Mean[rbp$variable == "Catch"] <- catm
rbp$Mean[rbp$variable == "Landings"] <- lanm
# end Einar added 29.1.2014
catsam <- apply(catsa, c(1,3), mean)
lansam <- apply(lansa, c(1,3), mean)
maxpf <- apply(catsam, 2, which.max)
maxpfl <- apply(lansam, 2, which.max)
FmsyLan <- Fscan[maxpfl]
msymLan <- mean(FmsyLan)
vcumLan <- stats::median(FmsyLan)
fmsy.densLan <- stats::density(FmsyLan)
vmodeLan <- fmsy.densLan$x[which.max(fmsy.densLan$y)]
FmsyCat <- Fscan[maxpf]
msymCat <- mean(FmsyCat)
vcumCat <- stats::median(FmsyCat)
fmsy.densCat <- stats::density(FmsyCat)
vmodeCat <- fmsy.densCat$x[which.max(fmsy.densCat$y)]
pFmsyCat <- data.frame(Ftarget=fmsy.densCat$x,
value=cumsum(fmsy.densCat$y * diff(fmsy.densCat$x)[1]),
variable="pFmsyCatch")
pFmsyLan <- data.frame(Ftarget=fmsy.densLan$x,
value=cumsum(fmsy.densLan$y * diff(fmsy.densLan$x)[1]),
variable="pFmsyLandings")
pProfile <- rbind(pFmsyCat,pFmsyLan)
# PA REFERENCE POINTS
if(!missing(Blim)) {
pBlim <- apply(ssbsa > Blim, 1, mean)
i <- max(which(pBlim > .95))
grad <- diff(Fscan[i + 0:1]) / diff(pBlim[i + 0:1])
flim <- Fscan[i] + grad * (0.95 - pBlim[i]) # linear interpolation i think..
i <- max(which(pBlim > .90))
grad <- diff(Fscan[i + 0:1]) / diff(pBlim[i + 0:1])
flim10 <- Fscan[i]+grad*(0.9-pBlim[i]) # linear interpolation i think..
i <- max(which(pBlim > .50))
grad <- diff(Fscan[i + 0:1]) / diff(pBlim[i + 0:1])
flim50 <- Fscan[i]+grad*(0.5-pBlim[i]) # linear interpolation i think..
pBlim <- data.frame(Ftarget = Fscan,value = 1-pBlim,variable="Blim")
pProfile <- rbind(pProfile,pBlim)
} else {
flim <- flim10 <- flim50 <- Blim <- NA
}
if(!missing(Bpa)) {
pBpa <- apply(ssbsa > Bpa, 1, mean)
pBpa <- data.frame(Ftarget = Fscan,value = 1-pBpa,variable="Bpa")
pProfile <- rbind(pProfile,pBpa)
} else {
Bpa <- NA
}
# GENERATE REF-TABLE
catF <- c(flim, flim10, flim50, vcumCat, Fscan[maxcatm], FCrash05, FCrash50)
lanF <- c( NA, NA, NA, vcumLan, Fscan[maxlanm], NA, NA)
catC <- stats::approx(Fscan, cats[4,], xout = catF)$y
lanC <- stats::approx(Fscan, lans[4,], xout = lanF)$y
catB <- stats::approx(Fscan, ssbs[4,], xout = catF)$y
lanB <- stats::approx(Fscan, ssbs[4,], xout = lanF)$y
Refs <- rbind(catF, lanF, catC, lanC, catB, lanB)
rownames(Refs) <- c("catF","lanF","catch","landings","catB","lanB")
colnames(Refs) <- c("F05","F10","F50","medianMSY","meanMSY","FCrash05","FCrash50")
#TODO: id.sim - user specified.
# 2014-03-12 Ammendments per note from Carmen/John
# CALCULATIONS:
# Fmsy: value that maximises median LT catch or median LT landings
auxi <- stats::approx(Fscan, cats[4, ],xout=seq(min(Fscan),max(Fscan),length=200))
FmsyMedianC <- auxi$x[which.max(auxi$y)]
MSYMedianC <- max(auxi$y)
# Value of F that corresponds to 0.95*MSY:
FmsylowerMedianC <- auxi$x[ min( (1:length(auxi$y))[auxi$y/MSYMedianC >= 0.95] ) ]
FmsyupperMedianC <- auxi$x[ max( (1:length(auxi$y))[auxi$y/MSYMedianC >= 0.95] ) ]
auxi <- stats::approx(Fscan, lans[4, ],xout=seq(min(Fscan),max(Fscan),length=200))
FmsyMedianL <- auxi$x[which.max(auxi$y)]
MSYMedianL <- max(auxi$y)
# Value of F that corresponds to 0.95*MSY:
FmsylowerMedianL <- auxi$x[ min( (1:length(auxi$y))[auxi$y/MSYMedianL >= 0.95] ) ]
FmsyupperMedianL <- auxi$x[ max( (1:length(auxi$y))[auxi$y/MSYMedianL >= 0.95] ) ]
F5percRiskBlim <- flim
refs_interval <- data.frame(FmsyMedianC = FmsyMedianC,
FmsylowerMedianC = FmsylowerMedianC,
FmsyupperMedianC = FmsyupperMedianC,
FmsyMedianL = FmsyMedianL,
FmsylowerMedianL = FmsylowerMedianL,
FmsyupperMedianL = FmsyupperMedianL,
F5percRiskBlim = F5percRiskBlim,
Btrigger = Btrigger)
# END 2014-03-12 Ammendments per note from Carmen/John
sim <- list(ibya=list(Mat = Mat, M = M, Fprop = Fprop, Mprop = Mprop,
west = west, weca = weca, sel = sel),
rbya=list(ferr = ferr, ssb = ssbsa, catch = catsa,
landings = lansa, rec = recsa,
srmodels = SR, Ftarget = Fscan, simyears = begin:Nrun),
rby=fit$rby,
rbp=rbp,
Blim=Blim,
Bpa=Bpa,
Refs = Refs,
pProfile=pProfile,
id.sim=fit$id.sr,
refs_interval=refs_interval,
rhologRec = rhologRec)
if (keep.sims) {
sim$rbya_all <- list(ssb=ssbsall, catch = catsall, landings = lansall, rec = recsall)
}
if (verbose) icesTAF::msg("Calculating MSY range values")
sim <- eqsim_range(sim)
return(sim)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.