##-------------------------------------------------------- ## CMSY analysis with estimation of total biomass, including Bayesian Schaefer ## written by Rainer Froese with support from Gianpaolo Coro in 2013-2014 ## This version adjusts biomass to average biomass over the year ## It also contains the FutureCrash option to improve prediction of final biomass ## Version 21 adds the purple point to indicate the 25th percentile of final biomass ## Version 22 accepts that no biomass or CPUE area available ##-------------------------------------------------------- library(R2jags) # Interface with JAGS library(coda) #----------------------------------------- # Some general settings #----------------------------------------- # set.seed(999) # use for comparing results between runs rm(list=ls(all=TRUE)) # clear previous variables etc options(digits=3) # displays all numbers with three significant digits as default graphics.off() # close graphics windows from previous sessions #----------------------------------------- # General settings for the analysis #----------------------------------------- sigR <- 0.02 # overall process error; 0.05 works reasonable for simulations, 0.02 for real data; 0 if deterministic model n <- 10000 # initial number of r-k pairs batch.mode <- T # set to TRUE to suppress graphs write.output <- T # set to true if table of output is wanted FutureCrash <- "No" #----------------------------------------- # Start output to screen #----------------------------------------- cat("-------------------------------------------\n") cat("Catch-MSY Analysis,", date(),"\n") cat("-------------------------------------------\n") #------------------------------------------ # Read data and assign to vectors #------------------------------------------ # filename_1 <- "AllStocks_Catch4.csv" # filename_2 <- "AllStocks_ID4.csv" # filename_1 <- "SimCatch.csv" # filename_2 <- "SimSpec.csv" # filename_2 <- "SimSpecWrongS.csv" # filename_2 <- "SimSpecWrongI.csv" # filename_2 <- "SimSpecWrongF.csv" # filename_2 <- "SimSpecWrongH.csv" # filename_2 <- "SimSpecWrongL.csv" # filename_1 <- "FishDataLim.csv" # filename_2 <- "FishDataLimSpec.csv" filename_1 <- "WKLIFE4Stocks.csv" filename_2 <- "WKLIFE4ID.csv" outfile<-"outfile" outfile.txt <- "outputfile.txt" cdat <- read.csv(filename_1, header=T, dec=".", stringsAsFactors = FALSE) cinfo <- read.csv(filename_2, header=T, dec=".", stringsAsFactors = FALSE) cat("Files", filename_1, ",", filename_2, "read successfully","\n") # Stocks with total biomass data and catch data from StartYear to EndYear # stocks <- sort(as.character(cinfo$stock)) # All stocks stocks<-"HLH_M07" # select one stock after the other for(stock in stocks) { # assign data from cinfo to vectors res <- as.character(cinfo$Resilience[cinfo$stock==stock]) StartYear <- as.numeric(cinfo$StartYear[cinfo$stock==stock]) EndYear <- as.numeric(cinfo$EndYear[cinfo$stock==stock]) r_low <- as.numeric(cinfo$r_low[cinfo$stock==stock]) r_hi <- as.numeric(cinfo$r_hi[cinfo$stock==stock]) stb_low <- as.numeric(cinfo$stb_low[cinfo$stock==stock]) stb_hi <- as.numeric(cinfo$stb_hi[cinfo$stock==stock]) intyr <- as.numeric(cinfo$intyr[cinfo$stock==stock]) intbio_low <- as.numeric(cinfo$intbio_low[cinfo$stock==stock]) intbio_hi <- as.numeric(cinfo$intbio_hi[cinfo$stock==stock]) endbio_low <- as.numeric(cinfo$endbio_low[cinfo$stock==stock]) endbio_hi <- as.numeric(cinfo$endbio_hi[cinfo$stock==stock]) Btype <- as.character(cinfo$Btype[cinfo$stock==stock]) FutureCrash <- as.character(cinfo$FutureCrash[cinfo$stock==stock]) comment <- as.character(cinfo$comment[cinfo$stock==stock]) # extract data on stock yr <- as.numeric(cdat$yr[cdat$stock==stock & cdat$yr >= StartYear & cdat$yr <= EndYear]) ct <- as.numeric(cdat$ct[cdat$stock==stock & cdat$yr >= StartYear & cdat$yr <= EndYear])/1000 ## assumes that catch is given in tonnes, transforms to '000 tonnes if(Btype=="observed" | Btype=="CPUE" | Btype=="simulated") { bt <- as.numeric(cdat$TB[cdat$stock==stock & cdat$yr >= StartYear & cdat$yr <= EndYear])/1000 ## assumes that biomass is in tonnes, transforms to '000 tonnes } else {bt <- NA} nyr <- length(yr) # number of years in the time series if(Btype!="observed") {bio <- bt} # change biomass to moving average as assumed by Schaefer (but not for simulations or CPUE) # for last year use reported bio if(Btype=="observed") { ma <- function(x){filter(x,rep(1/2,2),sides=2)} bio <- ma(bt) bio[length(bio)] <- bt[length(bt)] } # initialize vectors for viable r, k, bt rv.all <- vector() kv.all <- vector() btv.all <- matrix(data=vector(),ncol=nyr+1) #---------------------------------------------------- # Determine initial ranges for parameters and biomass #---------------------------------------------------- # initial range of r from input file if(is.na(r_low)==F & is.na(r_hi)==F) { start_r <- c(r_low,r_hi) } else { # initial range of r and CatchMult values based on resilience if(res == "High") { start_r <- c(0.6,1.5)} else if(res == "Medium") { start_r <- c(0.2,0.8)} else if(res == "Low") { start_r <- c(0.05,0.5)} else { # i.e. res== "Very low" start_r <- c(0.015,0.1)} } # initial range of k values, assuming k will always be larger than max catch # and max catch will never be smaller than a quarter of MSY start_k <- c(max(ct),16*max(ct)/start_r[1]) # initial biomass range from input file if(is.na(stb_low)==F & is.na(stb_hi)==F) { startbio <- c(stb_low,stb_hi) } else { # us low biomass at start as default startbio <- c(0.1,0.5) } MinYear <- yr[which.min(ct)] MaxYear <- yr[which.max(ct)] # use year and biomass range for intermediate biomass from input file if(is.na(intbio_low)==F & is.na(intbio_hi)==F) { intyr <- intyr intbio <- c(intbio_low,intbio_hi) # else if year of minimum catch is at least 3 years away from StartYear and EndYear of series, use min catch } else if((MinYear - StartYear) > 3 & (EndYear - MinYear) > 3 ) { # assume that biomass range in year before minimum catch was 0.01 - 0.4 intyr <- MinYear-1 intbio <- c(0.01,0.4) # else if year of max catch is at least 3 years away from StartYear and EndYear of series, use max catch } else if((MaxYear - StartYear) > 3 & (EndYear - MaxYear) > 3 ) { # assume that biomass range in year before maximum catch was 0.3 - 0.9 intyr <- MaxYear-1 intbio <- c(0.3,0.9) } else { # assume uninformative range 0-1 in mid-year intyr <- as.integer(mean(c(StartYear, EndYear))) intbio <- c(0,1) } # end of intbio setting # final biomass range from input file if(is.na(endbio_low)==F & is.na(endbio_hi)==F) { endbio <- c(endbio_low,endbio_hi) } else { # else use Catch/maxCatch to estimate final biomass endbio <- if(ct[nyr]/max(ct) > 0.5) {c(0.4,0.8)} else {c(0.01,0.4)} } # end of final biomass setting #---------------------------------------------- # MC with Schaefer Function filtering #---------------------------------------------- Schaefer <- function(ri, ki, startbio, intyr, intbio, endbio, sigR, pt) { # if stock is not expected to crash within 3 years if last catch continues if(FutureCrash == "No") { yr.s <- c(yr,EndYear+1,EndYear+2,EndYear+3) ct.s <- c(ct,ct[yr==EndYear],ct[yr==EndYear],ct[yr==EndYear]) nyr.s <- length(yr.s) } else{ yr.s <- yr ct.s <- ct nyr.s <- nyr } # create vector for initial biomasses startbt <-seq(from =startbio[1], to=startbio[2], by = (startbio[2]-startbio[1])/10) # create vectors for viable r, k and bt rv <- array(-1:-1,dim=c(length(ri)*length(startbt))) #initialize array with -1. The -1 remaining after the process will be removed kv <- array(-1:-1,dim=c(length(ri)*length(startbt))) btv <- matrix(data=NA, nrow = (length(ri)*length(startbt)), ncol = nyr+1) intyr.i <- which(yr.s==intyr) # get index of intermediate year #loop through r-k pairs npoints = length(ri) nstartb = length(startbt) for(i in 1 : npoints) { if (i%%1000==0) cat(".") # create empty vector for annual biomasses bt <- vector() # loop through range of relative start biomasses for(j in startbt) { # set initial biomass, including process error bt[1]=j*ki[i]*exp(rnorm(1,0, sigR)) ## set biomass in first year #loop through years in catch time series for(t in 1:nyr.s) { # for all years in the time series xt=rnorm(1,0, sigR) # set new random process error for every year # calculate biomass as function of previous year's biomass plus surplus production minus catch bt[t+1]=(bt[t]+ri[i]*bt[t]*(1-bt[t]/ki[i])-ct.s[t])*exp(xt) # if biomass < 0.01 k or > 1.1 k, discard r-k pair if(bt[t+1] < 0.01*ki[i] || bt[t+1] > 1.1*ki[i]) { break } # stop looping through years, go to next upper level if ((t+1)==intyr.i && (bt[t+1]>(intbio[2]*ki[i]) || bt[t+1]<(intbio[1]*ki[i]))) { break } #intermediate year check } # end of loop of years # if last biomass falls without expected ranges goto next r-k pair if(t < nyr.s || bt[yr.s==EndYear] > (endbio[2]*ki[i]) || bt[yr.s==EndYear] < (endbio[1]*ki[i])) { next } else { # store r, k, and bt, plot point, then go to next startbt rv[((i-1)*nstartb)+j] <- ri[i] kv[((i-1)*nstartb)+j] <- ki[i] btv[((i-1)*nstartb)+j,] <- bt[1:(nyr+1)]/ki[i] #substitute a row into the matrix, exclude FutureCrash years if(pt==T) {points(x=ri[i], y=ki[i], pch=".", cex=2, col="black") next } } } # end of loop of initial biomasses } # end of loop of r-k pairs rv=rv[rv!=-1] kv=kv[kv!=-1] btv=na.omit(btv) #delete first line cat("\n") return(list(rv, kv,btv)) } # end of Schaefer function #------------------------------------------------------------------ # Uniform sampling of the r-k space #------------------------------------------------------------------ # get random set of r and k from log space distribution ri1 = exp(runif(n, log(start_r[1]), log(start_r[2]))) ki1 = exp(runif(n, log(start_k[1]), log(start_k[2]))) #----------------------------------------------------------------- # Plot data and progress #----------------------------------------------------------------- #windows(14,9) par(mfcol=c(2,3)) # plot catch plot(x=yr, y=ct, ylim=c(0,1.2*max(ct)), type ="l", bty="l", main=paste(stock,"catch"), xlab="Year", ylab="Catch", lwd=2) points(x=yr[which.max(ct)], y=max(ct), col="red", lwd=2) points(x=yr[which.min(ct)], y=min(ct), col="red", lwd=2) # plot r-k graph plot(ri1, ki1, xlim = start_r, ylim = start_k, log="xy", xlab="r", ylab="k", main="Finding viable r-k", pch=".", cex=2, bty="l", col="lightgrey") #1 - Call MC-Schaefer function to preliminary explore the space without prior information cat(stock, ": First Monte Carlo filtering of r-k space with ",n," points\n") MCA <- Schaefer(ri=ri1, ki=ki1, startbio=startbio, intyr=intyr, intbio=intbio, endbio=endbio, sigR=sigR, pt=T) rv.all <- append(rv.all,MCA[[1]]) kv.all <- append(kv.all,MCA[[2]]) btv.all <- rbind(btv.all,MCA[[3]]) #take viable r and k values nviablepoints = length(rv.all) cat("* Found ",nviablepoints," viable points from ",n," samples\n"); #if few points were found then resample and shrink the k log space if (nviablepoints<=1000){ log.start_k.new <- log(start_k) max_attempts = 3 current_attempts = 1 while (nviablepoints<=1000 && current_attempts<=max_attempts){ if(nviablepoints > 0) { log.start_k.new[1] <- mean(c(log.start_k.new[1], min(log(kv.all)))) log.start_k.new[2] <- mean(c(log.start_k.new[2], max(log(kv.all)))) } n.new=n*current_attempts #add more points ri1 = exp(runif(n.new, log(start_r[1]), log(start_r[2]))) ki1 = exp(runif(n.new, log.start_k.new[1], log.start_k.new[2])) cat("Shrinking k space: repeating Monte Carlo in the interval [",exp(log.start_k.new[1]),",",exp(log.start_k.new[2]),"]\n") cat("Attempt ",current_attempts," of ",max_attempts," with ",n.new," points","\n") MCA <- Schaefer(ri=ri1, ki=ki1, startbio=startbio, intyr=intyr, intbio=intbio, endbio=endbio, sigR=sigR, pt=T) rv.all <- append(rv.all,MCA[[1]]) kv.all <- append(kv.all,MCA[[2]]) btv.all <- rbind(btv.all,MCA[[3]]) nviablepoints = length(rv.all) #recalculate viable points cat("* Found altogether",nviablepoints," viable points \n"); current_attempts=current_attempts+1 #increment the number of attempts } } # If tip of viable r-k pairs is 'thin', do extra sampling there gm.rv = exp(mean(log(rv.all))) if(length(rv.all[rv.all > 0.9*start_r[2]]) < 10) { l.sample.r <- (gm.rv + max(rv.all))/2 cat("Final sampling in the tip area above r =",l.sample.r,"\n") log.start_k.new <- c(log(0.8*min(kv.all)),log(max(kv.all[rv.all > l.sample.r]))) ri1 = exp(runif(50000, log(l.sample.r), log(start_r[2]))) ki1 = exp(runif(50000, log.start_k.new[1], log.start_k.new[2])) MCA <- Schaefer(ri=ri1, ki=ki1, startbio=startbio, intyr=intyr, intbio=intbio, endbio=endbio, sigR=sigR, pt=T) rv.all <- append(rv.all,MCA[[1]]) kv.all <- append(kv.all,MCA[[2]]) btv.all <- rbind(btv.all,MCA[[3]]) nviablepoints = length(rv.all) #recalculate viable points cat("Found altogether", length(rv.all), "unique viable r-k pairs and biomass trajectories\n") } # ------------------------------------------------------------ # Bayesian analysis of catch & biomass with Schaefer model # ------------------------------------------------------------ if(Btype == "observed" | Btype=="simulated") { cat("Running Schaefer MCMC analysis....\n") mcmc.burn <- as.integer(30000) mcmc.chainLength <- as.integer(60000) # burn-in plus post-burn mcmc.thin = 10 # to reduce autocorrelation mcmc.chains = 3 # needs to be at least 2 for DIC # Parameters to be returned by JAGS jags.save.params=c('r','k','sigma.b', 'alpha', 'sigma.r') # # JAGS model Model = "model{ # to avoid crash due to 0 values eps<-0.01 # set a quite narrow variation from the expected value sigma.b <- 1/16 tau.b <- pow(sigma.b,-2) Bm[1] <- log(alpha*k) bio[1] ~ dlnorm(Bm[1],tau.b) for (t in 2:nyr){ bio[t] ~ dlnorm(Bm[t],tau.b) Bm[t] <- log(max(bio[t-1] + r*bio[t-1]*(1 - (bio[t-1])/k) - ct[t-1], eps)) } # priors alpha ~ dunif(0.01,1) # needed for fit of first biomass #inverse cubic root relationship between the range of viable r and the size of the search space inverseRangeFactor <- 1/((start_r[2]-start_r[1])^1/3) # give sigma some variability in the inverse relationship sigma.r ~ dunif(0.001*inverseRangeFactor,0.02*inverseRangeFactor) tau.r <- pow(sigma.r,-2) rm <- log((start_r[1]+start_r[2])/2) r ~ dlnorm(rm,tau.r) # search in the k space from the center of the range. Allow high variability km <- log((start_k[1]+start_k[2])/2) tau.k <- pow(km,-2) k ~ dlnorm(km,tau.k) #end model }" # Write JAGS model to file cat(Model, file="r2jags.bug") ### random seed set.seed(runif(1,1,500)) # needed in JAGS ### run model jags_outputs <- jags(data=c('ct','bio','nyr', 'start_r', 'start_k'), working.directory=NULL, inits=NULL, parameters.to.save= jags.save.params, model.file="r2jags.bug", n.chains = mcmc.chains, n.burnin = mcmc.burn, n.thin = mcmc.thin, n.iter = mcmc.chainLength, refresh=mcmc.burn/20, ) # ------------------------------------------------------ # Results from JAGS Schaefer # ------------------------------------------------------ r_out <- as.numeric(mcmc(jags_outputs$BUGSoutput$sims.list$r)) k_out <- as.numeric(mcmc(jags_outputs$BUGSoutput$sims.list$k)) ## sigma_out <- as.numeric(mcmc(jags_outputs$BUGSoutput$sims.list$sigma.b)) alpha_out <- as.numeric(mcmc(jags_outputs$BUGSoutput$sims.list$alpha)) ## sigma.r_out <- as.numeric(mcmc(jags_outputs$BUGSoutput$sims.list$sigma.r)) mean.log.r.jags <- mean(log(r_out)) SD.log.r.jags <- sd(log(r_out)) lcl.log.r.jags <- mean.log.r.jags-1.96*SD.log.r.jags ucl.log.r.jags <- mean.log.r.jags+1.96*SD.log.r.jags gm.r.jags <- exp(mean.log.r.jags) lcl.r.jags <- exp(lcl.log.r.jags) ucl.r.jags <- exp(ucl.log.r.jags) mean.log.k.jags <- mean(log(k_out)) SD.log.k.jags <- sd(log(k_out)) lcl.log.k.jags <- mean.log.k.jags-1.96*SD.log.k.jags ucl.log.k.jags <- mean.log.k.jags+1.96*SD.log.k.jags gm.k.jags <- exp(mean.log.k.jags) lcl.k.jags <- exp(lcl.log.k.jags) ucl.k.jags <- exp(ucl.log.k.jags) mean.log.MSY.jags<- mean(log(r_out)+log(k_out)-log(4)) SD.log.MSY.jags <- sd(log(r_out)+log(k_out)-log(4)) gm.MSY.jags <- exp(mean.log.MSY.jags) lcl.MSY.jags <- exp(mean.log.MSY.jags-1.96*SD.log.MSY.jags) ucl.MSY.jags <- exp(mean.log.MSY.jags+1.96*SD.log.MSY.jags) } # end of MCMC Schaefer loop #------------------------------------ # get results from CMSY #------------------------------------ # get estimate of most probable r as median of mid log.r-classes above cut-off # get remaining viable log.r and log.k rem.log.r <- log(rv.all[rv.all > gm.rv]) rem.log.k <- log(kv.all[rv.all>gm.rv]) # get vectors with numbers of r and mid values in about 25 classes hist.log.r <- hist(x=rem.log.r, breaks=25, plot=F) log.r.counts <- hist.log.r$counts log.r.mids <- hist.log.r$mids # get most probable log.r as mean of mids with counts > 0 log.r.est <- median(log.r.mids[which(log.r.counts > 0)]) lcl.log.r <- as.numeric(quantile(x=log.r.mids[which(log.r.counts > 0)], 0.025)) ucl.log.r <- as.numeric(quantile(x=log.r.mids[which(log.r.counts > 0)], 0.975)) r.est <- exp(log.r.est) lcl.r.est <- exp(lcl.log.r) ucl.r.est <- exp(ucl.log.r) # do linear regression of log k ~ log r with slope fixed to -1 (from Schaefer) reg <- lm(rem.log.k ~ 1 + offset(-1*rem.log.r)) int.reg <- as.numeric(reg[1]) sd.reg <- sd(resid(reg)) se.reg <- summary(reg)$coefficients[2] # get estimate of log(k) from y where x = log.r.est log.k.est <- int.reg + (-1) * log.r.est # get estimates of CL of log.k.est from y +/- SD where x = lcl.log r or ucl.log.r lcl.log.k <- int.reg + (-1) * ucl.log.r - sd.reg ucl.log.k <- int.reg + (-1) * lcl.log.r + sd.reg k.est <- exp(log.k.est) lcl.k.est <- exp(lcl.log.k) ucl.k.est <- exp(ucl.log.k) # get MSY from remaining log r-k pairs log.MSY.est <- mean(rem.log.r + rem.log.k - log(4)) sd.log.MSY.est <- sd(rem.log.r + rem.log.k - log(4)) lcl.log.MSY.est <- log.MSY.est - 1.96*sd.log.MSY.est ucl.log.MSY.est <- log.MSY.est + 1.96*sd.log.MSY.est MSY.est <- exp(log.MSY.est) lcl.MSY.est <- exp(lcl.log.MSY.est) ucl.MSY.est <- exp(ucl.log.MSY.est) # get predicted biomass vectors as median and quantiles of trajectories median.btv <- apply(btv.all,2, median) lastyr.bio <- median.btv[length(median.btv)-1] nextyr.bio <- median.btv[length(median.btv)] lcl.btv <- apply(btv.all,2, quantile, probs=0.025) q.btv <- apply(btv.all,2, quantile, probs=0.25) ucl.btv <- apply(btv.all,2, quantile, probs=0.975) lcl.lastyr.bio <- lcl.btv[length(lcl.btv)-1] ucl.lastyr.bio <- ucl.btv[length(lcl.btv)-1] lcl.nextyr.bio <- lcl.btv[length(lcl.btv)] ucl.nextyr.bio <- ucl.btv[length(lcl.btv)] # ----------------------------------------- # Plot results # ----------------------------------------- # Analysis of viable r-k pairs plot(x=rv.all, y=kv.all, xlim=start_r, ylim=c(0.9*min(kv.all, ifelse(Btype == "observed",k_out,NA), na.rm=T), 1.1*max(kv.all)), pch=16, col="grey",log="xy", bty="l", xlab="r", ylab="k", main="Analysis of viable r-k") abline(v=gm.rv, lty="dashed") # plot points and best estimate from full Schaefer analysis if(Btype == "observed"|Btype=="simulated") { # plot r-k pairs from MCMC points(x=r_out, y=k_out, pch=16,cex=0.5) # plot best r-k pair from MCMC points(x=gm.r.jags, y=gm.k.jags, pch=19, col="green") lines(x=c(lcl.r.jags, ucl.r.jags),y=c(gm.k.jags,gm.k.jags), col="green") lines(x=c(gm.r.jags,gm.r.jags),y=c(lcl.k.jags, ucl.k.jags), col="green") } # if data are from simulation, plot true r and k if(Btype=="simulated") { l.stock <- nchar(stock) # get length of sim stock name r.char <- substr(stock,l.stock-1,l.stock) # get last character of sim stock name r.sim <- NA # initialize vector for r used in simulation if(r.char=="_H") {r.sim=1; lcl.r.sim=0.8; ucl.r.sim=1.25} else if(r.char=="_M") {r.sim=0.5;lcl.r.sim=0.4;ucl.r.sim=0.62} else if(r.char=="_L") {r.sim=0.25;lcl.r.sim=0.2;ucl.r.sim=0.31} else {r.sim=0.05;lcl.r.sim=0.04;ucl.r.sim=0.062} # plot true r-k point with error bars points(x=r.sim, y=1000, pch=19, col="red") # add +/- 20% error bars lines(x=c(lcl.r.sim,ucl.r.sim), y=c(1000,1000), col="red") lines(x=c(r.sim,r.sim), y=c(800,1250), col="red") } # plot blue dot for proposed r-k, with 95% CL lines points(x=r.est, y=k.est, pch=19, col="blue") lines(x=c(lcl.r.est, ucl.r.est),y=c(k.est,k.est), col="blue") lines(x=c(r.est,r.est),y=c(lcl.k.est, ucl.k.est), col="blue") # plot biomass graph # determine k to use for red line in b/k plot if(Btype=="simulated") {k2use <- 1000} else if(Btype == "observed") {k2use <- gm.k.jags} else {k2use <- k.est} # determine hight of y-axis in plot max.y <- max(c(bio/k2use,ucl.btv,0.6,startbio[2], intbio[2],endbio[2]),na.rm=T) plot(x=yr,y=median.btv[1:nyr], lwd=2, xlab="Year", ylab="Relative biomass b/k", type="l", ylim=c(0,max.y), bty="l", main=paste("Pred. biomass vs ", Btype,sep="")) lines(x=yr, y=lcl.btv[1:nyr],type="l") lines(x=yr, y=ucl.btv[1:nyr],type="l") points(x=EndYear,y=q.btv[yr==EndYear], col="purple", cex=1.5, lwd=2) abline(h=0.5, lty="dashed") abline(h=0.25, lty="dotted") lines(x=c(yr[1],yr[1]), y=startbio, col="blue") lines(x=c(intyr,intyr), y=intbio, col="blue") lines(x=c(max(yr),max(yr)), y=endbio, col="blue") # if observed biomass is available, plot red biomass line if(Btype == "observed"|Btype=="simulated") { lines(x=yr, y=bio/k2use,type="l", col="red", lwd=1) } # if CPUE data are available, scale to predicted biomass range, plot red biomass line if(Btype == "CPUE") { par(new=T) # prepares for new plot on top of previous plot(x=yr, y=bio, type="l", col="red", lwd=1, ann=F,axes=F,ylim=c(0,1.2*max(bio, na.rm=T))) # forces this plot on top of previous one axis(4, col="red", col.axis="red") } # plot yield and biomass against equilibrium surplus parabola max.y <-max(c(ct/MSY.est,ifelse(Btype=="observed"|Btype=="simulated",ct/gm.MSY.jags,NA),1.2),na.rm=T) # plot parabola x=seq(from=0,to=2,by=0.001) y=4*x-(2*x)^2 plot(x=x, y=y, xlim=c(0,1), ylim=c(0,max.y), type="l", bty="l",xlab="Relative biomass b/k", ylab="Catch / MSY", main="Equilibrium curve") # plot catch against CMSY biomass estimates points(x=median.btv[1:nyr], y=ct/MSY.est, pch=16, col="grey") points(x=q.btv[yr==EndYear],y=ct[yr==EndYear]/MSY.est, col="purple", cex=1.5, lwd=2) # plot catch against observed biomass or CPUE if(Btype == "observed"|Btype=="simulated") { points(x=bio/k2use, y=ct/gm.MSY.jags, pch=16, cex=0.5) } # plot exploitation rate u against u.msy # get u derived from predicted CMSY biomass u.CMSY <- ct/(median.btv[1:nyr]*k.est) u.msy.CMSY <- 1-exp(-r.est/2) # # Fmsy from CMSY expressed as exploitation rate # get u from observed or simulated biomass if(Btype == "observed"|Btype=="simulated") { u.bio <- ct/bio u.msy.bio <- 1-exp(-gm.r.jags/2) } # get u from CPUE if(Btype == "CPUE") { q=max(median.btv[1:nyr][is.na(bio)==F],na.rm=T)*k.est/max(bio,na.rm=T) u.CPUE <- ct/(q*bio) } # determine upper bound of Y-axis max.y <- max(c(1.5, 1.2*u.CMSY/u.msy.CMSY,ct[yr==EndYear]/(q.btv[yr==EndYear]*k.est)/u.msy.CMSY, ifelse(Btype=="observed"|Btype=="simulated",max(u.bio[is.na(u.bio)==F]/u.msy.bio),0), na.rm=T)) # plot u from CMSY plot(x=yr,y=u.CMSY/u.msy.CMSY, type="l", bty="l", ylim=c(0,max.y), xlab="Year", ylab="u / u_msy", main="Exploitation rate") abline(h=1, lty="dashed") points(x=EndYear,y=ct[yr==EndYear]/(q.btv[yr==EndYear]*k.est)/u.msy.CMSY, col="purple", cex=1.5, lwd=2) # plot u from biomass if(Btype == "observed"|Btype=="simulated") lines(x=yr, y=u.bio/u.msy.bio, col="red") # plot u from CPUE if(Btype == "CPUE") { par(new=T) # prepares for new plot on top of previous plot(x=yr, y=u.CPUE, type="l", col="red", ylim=c(0, 1.2*max(u.CPUE,na.rm=T)),ann=F,axes=F) axis(4, col="red", col.axis="red") } if(batch.mode == TRUE) {dev.off()} # close plot window # ------------------------------------------ # print input and results to screen cat("---------------------------------------\n") cat("Species:", cinfo$ScientificName[cinfo$stock==stock], "\n") cat("Name and region:", cinfo$EnglishName[cinfo$stock==stock], ",", cinfo$Name[cinfo$stock==stock], "\n") cat("Stock:",stock,"\n") cat("Catch data used from years", min(yr),"-", max(yr), "\n") cat("Prior initial relative biomass =", startbio[1], "-", startbio[2], "\n") cat("Prior intermediate rel. biomass=", intbio[1], "-", intbio[2], "in year", intyr, "\n") cat("Prior final relative biomass =", endbio[1], "-", endbio[2], "\n") cat("If current catches continue, is the stock likely to crash within 3 years?",FutureCrash,"\n") cat("Prior range for r =", format(start_r[1],digits=2), "-", format(start_r[2],digits=2), ", prior range for k =", start_k[1], "-", start_k[2],"\n") # if data are simulated, print true r-k if(filename_1=="SimCatch.csv") { cat("True r =", r.sim, "(because input data were simulated with Schaefer model)\n") cat("True k = 1000 \n") cat("True MSY =", 1000*r.sim/4,"\n") cat("True biomass in last year =",bio[length(bio)],"or",bio[length(bio)]/1000,"k \n") cat("True mean catch / MSY ratio =", mean(ct)/(1000*r.sim/4),"\n") } # print results from full Schaefer if available if(Btype == "observed"|Btype=="simulated") { cat("Results from Bayesian Schaefer model using catch & biomass (",Btype,")\n") cat("MSY =", gm.MSY.jags,", 95% CL =", lcl.MSY.jags, "-", ucl.MSY.jags,"\n") cat("Mean catch / MSY =", mean(ct)/gm.MSY.jags,"\n") if(Btype != "CPUE") { cat("r =", gm.r.jags,", 95% CL =", lcl.r.jags, "-", ucl.r.jags,"\n") cat("k =", gm.k.jags,", 95% CL =", lcl.k.jags, "-", ucl.k.jags,"\n") } } # results of CMSY analysis cat("Results of CMSY analysis \n") cat("Altogether", nviablepoints,"unique viable r-k pairs were found \n") cat(nviablepoints-length(rem.log.r),"r-k pairs above the initial geometric mean of r =", gm.rv, "were analysed\n") cat("r =", r.est,", 95% CL =", lcl.r.est, "-", ucl.r.est,"\n") cat("k =", k.est,", 95% CL =", lcl.k.est, "-", ucl.k.est,"\n") cat("MSY =", MSY.est,", 95% CL =", lcl.MSY.est, "-", ucl.MSY.est,"\n") cat("Predicted biomass in last year =", lastyr.bio, "2.5th perc =", lcl.lastyr.bio, "97.5th perc =", ucl.lastyr.bio,"\n") cat("Predicted biomass in next year =", nextyr.bio, "2.5th perc =", lcl.nextyr.bio, "97.5th perc =", ucl.nextyr.bio,"\n") cat("----------------------------------------------------------\n") ## Write some results into outfile if(write.output == TRUE) { # write data into csv file output = data.frame(cinfo$ScientificName[cinfo$stock==stock], stock, StartYear, EndYear, mean(ct)*1000, ifelse(Btype=="observed"|Btype=="simulate",bio[length(bio)],NA), # last biomass on record ifelse(Btype == "observed"|Btype=="simulated",gm.MSY.jags,NA), # full Schaefer ifelse(Btype == "observed"|Btype=="simulated",lcl.MSY.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",ucl.MSY.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",gm.r.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",lcl.r.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",ucl.r.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",gm.k.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",lcl.k.jags,NA), ifelse(Btype == "observed"|Btype=="simulated",ucl.k.jags,NA), r.est, lcl.r.est, ucl.r.est, # CMSY r k.est, lcl.k.est, ucl.k.est, # CMSY k MSY.est, lcl.MSY.est, ucl.MSY.est, # CMSY r lastyr.bio, lcl.lastyr.bio, ucl.lastyr.bio, # last year bio nextyr.bio, lcl.nextyr.bio, ucl.nextyr.bio)# last year + 1 bio write.table(output, file=outfile, append = T, sep = ",", dec = ".", row.names = FALSE, col.names = FALSE) # write some text into text outfile.txt cat("Species:", cinfo$ScientificName[cinfo$stock==stock], "\n", "Name:", cinfo$EnglishName[cinfo$stock==stock], "\n", "Region:", cinfo$Name[cinfo$stock==stock], "\n", "Stock:",stock,"\n", "Catch data used from years", min(yr),"-", max(yr),", biomass =", Btype, "\n", "Prior initial relative biomass =", startbio[1], "-", startbio[2], "\n", "Prior intermediate rel. biomass=", intbio[1], "-", intbio[2], "in year", intyr, "\n", "Prior final relative biomass =", endbio[1], "-", endbio[2], "\n", "Future crash with current catches?", FutureCrash, "\n", "Prior range for r =", format(start_r[1],digits=2), "-", format(start_r[2],digits=2), ", prior range for k =", start_k[1], "-", start_k[2],"\n", file=outfile.txt,append=T) if(filename_1=="SimCatch.csv") { cat(" True r =", r.sim, "(because input data were simulated with Schaefer model)\n", "True k = 1000, true MSY =", 1000*r.sim/4,"\n", "True biomass in last year =",bio[length(bio)],"or",bio[length(bio)]/1000,"k \n", "True mean catch / MSY ratio =", mean(ct)/(1000*r.sim/4),"\n", file=outfile.txt,append=T) } if(Btype == "observed"|Btype=="simulated") { cat(" Results from Bayesian Schaefer model using catch & biomass \n", "r =", gm.r.jags,", 95% CL =", lcl.r.jags, "-", ucl.r.jags,"\n", "k =", gm.k.jags,", 95% CL =", lcl.k.jags, "-", ucl.k.jags,"\n", "MSY =", gm.MSY.jags,", 95% CL =", lcl.MSY.jags, "-", ucl.MSY.jags,"\n", "Mean catch / MSY =", mean(ct)/gm.MSY.jags,"\n", file=outfile.txt,append=T) } cat(" Results of CMSY analysis with altogether", nviablepoints,"unique viable r-k pairs \n", nviablepoints-length(rem.log.r),"r-k pairs above the initial geometric mean of r =", gm.rv, "were analysed\n", "r =", r.est,", 95% CL =", lcl.r.est, "-", ucl.r.est,"\n", "k =", k.est,", 95% CL =", lcl.k.est, "-", ucl.k.est,"\n", "MSY =", MSY.est,", 95% CL =", lcl.MSY.est, "-", ucl.MSY.est,"\n", "Predicted biomass last year b/k =", lastyr.bio, "2.5th perc b/k =", lcl.lastyr.bio, "97.5th perc b/k =", ucl.lastyr.bio,"\n", "Precautionary 25th percentile b/k =",q.btv[yr==EndYear],"\n", "----------------------------------------------------------\n", file=outfile.txt,append=T) } } # end of stocks loop