knitr::opts_chunk$set(fig.align="center", external=TRUE, echo=TRUE, warning=FALSE, fig.pos="H")

Introduction

This package contains functions to run the Length-based Integrated Mixed Effects (LIME) fisheries stock assessment method. The LIME package can be used in two ways:

  1. as an age-structured operating model to generate simulated length composition, catch data, and abundance indices based on single or multiple fleets and seasons, and
  2. as an estimation model by fitting to length composition data (at a minimum) to estimate annual fishing mortality, annual recruitment, relative spawning biomass, spawning potential ratio (SPR), and other derived outputs of an age-structured model.

Length-based

LIME was developed for data-limited fisheries, where few data are available other than a representative sample of the size structure of the vulnerable portion of the population (i.e., length composition data from the catch) and an understanding of the life history of the species.

Integrated

While length composition from the catch can hold information on fishing mortality, gear selectivity, and recruitment, with process and observation error it can be very difficult to tease apart the patterns and biological mechanisms from the noise. With additional information, such as even a few years of catch trends or an abundance index, analysts can include additional information to the LIME model to help tease apart these processes. For example, catch data is much more informative of the fishing mortality rate over time than the length composition data. Catch used alongside length composition data can help decrease bias and uncertainty in estimates of fishing mortality rates.

LIME also includes all years of data in the same analysis with a penalty on the annual fishing mortality rate to keep it from increasing or decreasing unrealistically between years. However, LIME assumes the selectivity curve is constant over time for each fleet.

Mixed effects

LIME relaxes the equilibrium assumptions of other length-based methods by estimating annual fishing mortality and recruitment variation (among other parameters), deriving annual recruitment as a random effect.

See Rudd and Thorson (2017) in the reference list for full details of the model, including simulation testing to evaluate performance across life history types, population variability scenarios, and data availability scenarios, as well as violations of the model assumptions.

Bug Reports

Please alert me to any bugs or issues by using GitHub.

Comments and suggestions for additional features are welcome and we can discuss via email at mbrudd@uw.edu.

Installation

Installing the Package

  1. devtools: You can install the development version of the package from GitHub using the devtools package:
install.packages("devtools", repos='http://cran.us.r-project.org')
  1. Follow the steps to install TMB:

  2. Windows: https://github.com/kaskr/adcomp/wiki/Windows-installation

  3. Linux: https://github.com/kaskr/adcomp (See README)

  4. Mac: should be the same as Linux, please see contact info under Bug Reports if that doesn't work.

  5. Install required package TMBhelper:

devtools::install_github("kaskr/TMB_contrib_R/TMBhelper")
  1. Install LIME:
devtools::install_github("merrillrudd/LIME", dependencies=TRUE)

The installation may produce error messages requiring other packages. You can download those from CRAN if they are not automatically downloaded in the LIME installation process, and then start from the step that produced the error. Again, please use the contact info in Bug Reports if this doesn't work, as you may have discovered a new installation error... congratulations!

Load packages

library(LIME)
library(tidyverse)

Step 1: Specify biological inputs and starting values

The LIME package simulation and estimation features require the biological inputs (e.g. growth, natural mortality, maturity) and starting values for selectivity parameters in a list. Using create_lh_list will make sure all required elements are included within the list and in the required format. The create_lh_list function requires inputs for some parameters and includes default values for others.

Minimum inputs for create_lh_list

The user is required to input the following parameters to create_lh_list for simulation and estimation:

Minimum inputs: Biology

Minimum inputs: Exploitation

Other inputs for create_lh_list with default settings

Other inputs: Biology

Other inputs: Exploitation

Other inputs: Variation

Now let's populate the create_lh_list function with example values.

lh <- create_lh_list(vbk=0.21, 
           linf=65, 
           t0=-0.01,
           lwa=0.0245, 
           lwb=2.79, 
           S50=c(20), 
           S95=c(26), 
           selex_input="length",
           selex_type=c("logistic"),
           M50=34,
           maturity_input="length",
           M=0.27, 
           binwidth=1,
           CVlen=0.1,
           SigmaR=0.737,
           SigmaF=0.2,
           SigmaC=0.1,
           SigmaI=0.1,
           R0=1,
           Frate=0.1,
           Fequil=0.25,
           qcoef=1e-5,
           start_ages=0,
           rho=0.43,
           theta=10,
           nseasons=1,
           nfleets=1)

Plot the biological and selectivity inputs

Now we should check out the biological parameters and selectivity we've created. Note that even though we input maturity and selectivity by length, create_lh_list converts to age and outputs both selectivity-at-age by fleet (lh$S_fa) and selectivity-at-length by fleet (lh$S_fl).

par(mfrow=c(2,2), mar=c(4,4,3,1))
plot(lh$L_a, type="l", lwd=4, xlab="Age", ylab="Length (cm)")
plot(lh$W_a, type="l", lwd=4, xlab="Age", ylab="Weight (g)")
plot(lh$Mat_l, type="l", lwd=4, xlab="Length (cm)", ylab="Proportion mature")

# plot selectivity for the first (and only) fleet (first row)
plot(lh$S_fl[1,], type="l", lwd=4, xlab="Length (cm)", ylab="Proportion selected to gear")

Check time step regarding predicted growth

Particularly for short-lived fish, it is possible that an annual time step is too coarse of a time scale to capture individual growth between years. For example, if a fish grows rapidly between ages 1 and 2, it is possible the probability of being a length given age will result in a negligible probability of being certain lengths. However, it is likely those lengths will be observed, and in this case LIME will not be able to fit the data well.

To check for this issue, we recommend plotting the probability of being in a length bin given age to make sure there is greater than negligible probability of observing all lengths. In this case, there is a small overlap between the distributions for age 1 and 2 fish, which should be enough to have an adequate model fit if fish are observed at approximately 17 cm.

For tips on what to do when there is a negligible probability of observing some lengths, see the "Format data" section in this document.

plba <- with(lh, age_length(highs, lows, L_a, CVlen))
ramp <- colorRamp(c("purple4", "darkorange"))
col_vec <- rgb( ramp(seq(0, 1, length = nrow(plba))), max = 255)
matplot(t(plba[-1,]), type="l", lty=1, lwd=3, col=col_vec, xaxs="i", yaxs="i", ylim=c(0, 0.5), xlab="Length bin (cm)", ylab="Density")
legend("topright", legend=lh$ages[seq(2,length(lh$ages),by=3)], col=col_vec[seq(2,length(lh$ages),by=3)],, lwd=3, title="Age")

Step 2: Data inputs to LIME

The first subsection on data formatting provides an overview of the simulation functions within the LIME package. To learn how to format data from your fishery, skip to the "Format data" section.

Simulating data

Using the life history list output from create_lh_list, we can simulate a population and generate data.

The generate_data function has several settings for which the user is required to input a value:

There are also several other settings not required but may be useful:

Now let's use generate_data to simulate 1 example population (itervec=1) to generate length, catch, and an abundance index. We won't specify a modpath so the simulated population will just be used locally in this vignette.

true <- generate_data(modpath=NULL,
            itervec=1, 
            Fdynamics=c("Endogenous"),
            Rdynamics="Constant",
            lh=lh,
            Nyears=20,
            Nyears_comp=c(20),
            comp_sample=rep(200,20),
            init_depl=0.7,
            seed=123,
            fleet_proportions=1)
par(mfrow=c(3,2))
plot(true$F_ft[1,], type="l", lwd=4, xlab="Year", ylab="Fishing mortality", ylim=c(0,max(true$F_ft)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true$R_t, type="l", lwd=4, xlab="Year", ylab="Recruitment", ylim=c(0,max(true$R_t)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true$SPR_t, type="l", lwd=4, xlab="Year", ylab="SPR", ylim=c(0,1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true$D_t, type="l", lwd=4, xlab="Year", ylab="Relative spawning biomass", ylim=c(0,max(true$D_t)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true$Cw_ft[1,], type="l", lwd=4, xlab="Year", ylab="Catch", ylim=c(0,max(true$Cw_ft)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true$I_ft[1,], type="l", lwd=4, xlab="Year", ylab="Abundance index", ylim=c(0,max(true$I_ft)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)

The LIME package includes the plot_LCfits function which can first be used to plot the length frequency data, and later used to plot the model fits to the length frequency data. The plot_LCfits function requires the length frequency data in data frame form, which can be formatted correctly using the LFreq_df function.

LF_df <- LFreq_df(true$LF)

The length frequency data frame can then be used in the plot_LCfits function.

plot_LCfits(LF_df=LF_df)

Format data

LIME requires data input in a specific format:

Length composition data

Option 1: Matrix

With only one fleet, length composition data can be in a length frequency matrix, with years along the rows and length bins along the columns. Here are 5 years as an example:

LF_mat <- true$LF[,,1]
LF_mat[1:5,]

Option 2: Array

The length composition data can be an array of matrices (one for each fleet). Columns should be named with the upper end of the length bin and rows should be named with the year.

First five years:

LF_array <- true$LF
LF_array_sub <- array(LF_array[1:5,,1], dim=c(5, ncol(LF_array[,,1]), 1))
colnames(LF_array_sub) <- colnames(LF_mat)
rownames(LF_array_sub) <- rownames(LF_mat)[1:5]
LF_array_sub

Option 3: List

The length composition data could also be a list of matrices (one for each fleet).

One fleet, first five years:

LF_list <- list()
LF_list[[1]] <- LF_array_sub[,,1]
LF_list

Catch and abundance index

Time series data (catch and abundance index) should me in matrix form with fleets along the rows and years along the columns. Rows and columns do not need to be explicitly named with fleet number or year, but the number of years should match the total number of years modeled. If data are not available in any given year there should be a negative place-holder.

With one fleet, the catch or abundance index time series should still be in matrix form rather than a vector (the model will be looking for the first row, for the one and only fleet).

Catch, one fleet:

true$Cw_ft

Abundance index, one fleet:

true$I_ft

Data input

Observations

LIME requires inputing observed data in a list form, including:

data_all <- list("years"=1:true$Nyears, "LF"=true$LF, "I_ft"=true$I_ft, "C_ft"=true$Cw_ft, "neff_ft"=true$obs_per_year)

Life history and starting values

LIME includes a function create_inputs which checks the length frequency data and includes all input data, life history information, and starting values in a list together to input into LIME.

create_inputs requires:

inputs_all <- create_inputs(lh=lh, input_data=data_all)

Step 3: Run LIME

Estimated parameters

LIME is set up to estimate certain parameters and fix others by default.

LIME estimates by default:

Parameters estimated by default under certain conditions:

Other parameters that could be estimated but are fixed by default:

run_LIME function

The function run_LIME used to run LIME models has many settings, but hopefully most models will keep the defaults and use only a few arguments.

Basic inputs to run_LIME:

If fitting to catch data, the user must specify:

Additional settings in run_LIME:

Settings in run_LIME associated with simulation-testing:

Example: Data-rich model run

Here's the best-case scenario for running LIME: 20 years of length composition, catch, and an abundance index, with a typical 200 samples of length measurements per year, assuming the life history information is known without error.

Here we specify C_type=2 because the catch data specified in data_all in the Data input section was catch in weight, not numbers.

start <- Sys.time()
rich <- run_LIME(modpath=NULL, 
                  input=inputs_all,
                  data_avail="Index_Catch_LC",
                  C_type=2)
end <- Sys.time() - start
end

The time difference above shows the run time of the data-rich case on the machine that compiled this document. The run time will vary depending on the machine, but hopefully this gives a ballpark of how long it takes to run a model with approximately 20 years and three data types.

The object rich contains several elements of LIME output:

Check convergence

General convergence criteria for LIME models includes:

  1. Final gradient of all estimated parameters is within +/- 0.001
  2. Hessian matrix is positive definite

We can check this for any model run using the following code:

gradient <- rich$opt$max_gradient <= 0.001
hessian <- rich$Sdreport$pdHess
hessian==TRUE & gradient == TRUE

Because both the hessian and gradient checks passed, we assume that the program found the global minimum of the negative log likelihood surface and can move on to examine results.

Plot results

The LIME package includes functions to plot length composition model fits and other results.

LIME model fits to length frequency data:

plot_LCfits(Inputs=rich$Inputs,
            Report=rich$Report)

LIME estimates of key population parameters:

plot_output(Inputs=rich$Inputs,
            Report=rich$Report,
            Sdreport=rich$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,1),"SPR"=c(0,1)))

Example: Length data only

This is the scenario for which LIME was developed: integrating multiple years of length data to account for time-varying fishing mortality and recruitment. The big change from the data-rich case in the code is to make sure data_avail="LC" and C_type is set to zero or removed from the function call (because the default is zero). We can still use the inputs_all list that includes the index and catch data, but as long as data_avail="LC" the model will not include the other data types.

start <- Sys.time()
lc_only <- run_LIME(modpath=NULL, 
                  input=inputs_all,
                  data_avail="LC")
end <- Sys.time() - start
end

Note the time difference is shorter than the data-rich case.

Check convergence

gradient <- lc_only$opt$max_gradient <= 0.001
hessian <- lc_only$Sdreport$pdHess
hessian==TRUE & gradient == TRUE

Plot results

We can use the same LF_df as was calculated in the data-rich case, but compare the LIME model fits from the model that excluded catch and abundance index:

plot_LCfits(LF_df=LF_df,
            Inputs=lc_only$Inputs,
            Report=lc_only$Report)

Model fits with length data only are of course much less accurate and with higher uncertainty than the data-rich case:

plot_output(Inputs=lc_only$Inputs,
            Report=lc_only$Report,
            Sdreport=lc_only$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,0.5),"SPR"=c(0,1)))

The model meets convergence criteria but the fishing mortality rate estimates jump around between years more than is realistic. To attempt to curb this behavior, it is possible to decrease the standard deviation for fishing mortality which will serve to penalize estimates of fishing mortality that stray too far from the previous year.

inputs_all$SigmaF <- 0.1
lc_only2 <- run_LIME(modpath=NULL, 
                  input=inputs_all,
                  data_avail="LC")

gradient <- lc_only2$opt$max_gradient <= 0.001
hessian <- lc_only2$Sdreport$pdHess
hessian==TRUE & gradient == TRUE
plot_output(Inputs=lc_only2$Inputs,
            Report=lc_only2$Report,
            Sdreport=lc_only2$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,0.5),"SPR"=c(0,1)))

Example: Length and catch data

This is the scenario most similar to the ideas behind catch-curve stock reduction analysis (CCSRA). CCSRA used catch and age composition data to estimate stock status. LIME can use catch and length composition, which is much easier to collect than ages. With accurate assumptions about life history information, the combination of catch and length data can be very informative of stock status.

start <- Sys.time()
catch_lc <- run_LIME(modpath=NULL, 
                  input=inputs_all,
                  data_avail="Catch_LC",
                  C_type=2)
end <- Sys.time() - start
end

Check convergence

gradient <- catch_lc$opt$max_gradient <= 0.001
hessian <- catch_lc$Sdreport$pdHess
hessian==TRUE & gradient == TRUE

Plot results

Model fits including catch data with length composition data:

plot_LCfits(LF_df=LF_df,
            Inputs=catch_lc$Inputs,
            Report=catch_lc$Report)

Including catch data improves estimates of population parameters over length data only.

plot_output(Inputs=catch_lc$Inputs,
            Report=catch_lc$Report,
            Sdreport=catch_lc$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,0.5),"SPR"=c(0,1)))

Turning off parameter estimation

There may be non-convergence issues (apparent from either a high final gradient or non-positive definite Hessian matrix). Some first checks in these cases are to 1) see if the Dirichlet-multinomial theta parameter is estimated too high, in which case it can be fixed to a high value and not estimated:

inputs_all$theta <- 50
check1 <- run_LIME(modpath=NULL,
                  input=inputs_all,
                  data_avail="LC",
                  fix_more="log_theta")

Another option is to check if the recruitment standard deviation is estimated too high or too low, in which case it can be fixed at a reasonable value:

inputs_all$SigmaR <- 0.3
check2 <- run_LIME(modpath=NULL,
                  input=inputs_all,
                  data_avail="LC",
                  fix_more="log_sigma_R")

Some length datasets may not be informative enough to tease apart fishing mortality, recruitment deviations, and selectivity. In these cases it may be convenient or helpful to fix selectivity at the starting values:

check3 <- run_LIME(modpath=NULL, 
                  input=inputs_all,
                  data_avail="LC",
                  est_selex_f=FALSE)

plot_output(Inputs=check3$Inputs,
            Report=check3$Report,
            Sdreport=check3$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,0.5),"SPR"=c(0,1)))

It is also possible to fix selectivity in a shape that is not the 2-parameter logistic curve. For example, we can set up dome-shaped selectivity using the 2-parameter logistic function on the left side of the fully selected lengths, and a normal distribution on the right side of the fully selected lengths:

## create input list with dome-shaped selectivity
lh_dome <- create_lh_list(vbk=0.21, 
           linf=65, 
           t0=-0.01,
           lwa=0.0245, 
           lwb=2.79, 
           S50=c(20), 
           S95=c(26), 
           selex_input="length",
           selex_type=c("dome"),
           dome_sd=15,
           M50=34,
           maturity_input="length",
           M=0.27, 
           binwidth=1,
           CVlen=0.1,
           SigmaR=0.737,
           SigmaF=0.2,
           SigmaC=0.1,
           SigmaI=0.1,
           R0=1,
           Frate=0.1,
           Fequil=0.25,
           qcoef=1e-5,
           start_ages=0,
           rho=0.43,
           theta=10,
           nseasons=1,
           nfleets=1)

## generate data with dome-shaped selectivity
true_dome <- generate_data(modpath=NULL,
            itervec=1, 
            Fdynamics=c("Endogenous"),
            Rdynamics="Constant",
            lh=lh_dome,
            Nyears=20,
            Nyears_comp=20,
            comp_sample=rep(200,20),
            init_depl=0.7,
            seed=123)

## create data list
data_all <- list("years"=1:true_dome$Nyears, "LF"=true_dome$LF, "I_ft"=true_dome$I_ft, "C_ft"=true_dome$Cw_ft, "neff_ft"=true_dome$obs_per_year)

inputs_dome <- create_inputs(lh=lh_dome, input_data=data_all)
plot(lh_dome$S_fl[1,], type="l", lwd=4, xlab="Length (cm)", ylab="Proportion selected to gear")
run_dome <- run_LIME(modpath=NULL, 
                  input=inputs_dome,
                  data_avail="LC",
                  vals_selex_ft=inputs_dome$S_fl)

plot_output(Inputs=run_dome$Inputs,
            Report=run_dome$Report,
            Sdreport=run_dome$Sdreport,
            lh=lh,
            True=true,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("Fish"=c(0,0.5),"SPR"=c(0,1)))

Multiple fleets

With multiple fleets, all biological inputs are the same as with a single fleet. However, we must specify selectivity for each fleet. In this case, both selectivities are logistic.

lh_mf1 <- with(lh, create_lh_list(vbk=vbk, 
           linf=linf, 
           t0=t0,
           lwa=lwa, 
           lwb=lwb, 
           S50=c(20,30), 
           S95=c(26,36), 
           selex_input="length",
           selex_type=c("logistic","logistic"),
           M50=ML50,
           M95=NULL,
           maturity_input="length",
           M=M, 
           h=h,
           binwidth=binwidth,
           CVlen=CVlen,
           SigmaR=SigmaR,
           SigmaF=SigmaF,
           SigmaC=SigmaC,
           SigmaI=SigmaI,
           R0=R0,
           Frate=Frate,
           qcoef=qcoef,
           start_ages=0,
           rho=rho,
           nseasons=1,
           nfleets=2))

Using the simulation function for multiple fleets, we need to specify the fleet dynamics for each (Fdynamics), the number of years of length composition data for each (Nyears_comp), and the proportions of each fleet (fleet_proportions).

true_mf1 <- generate_data(modpath=NULL,
            itervec=1, 
            Fdynamics=c("Constant","Endogenous"),
            Rdynamics="Constant",
            lh=lh_mf1,
            Nyears=20,
            Nyears_comp=c(20,10),
            comp_sample=rep(200, 20),
            init_depl=0.7,
            seed=123,
            fleet_proportions=c(0.6,0.4))
library(RColorBrewer)
cols <- brewer.pal(3, "Set1")
plot(lh_mf1$S_fl[1,], type="l", lwd=2, xlab="Length", ylab="Selectivity", col=cols[1])
lines(lh_mf1$S_fl[2,], type="l", lwd=2, col=cols[2])
par(mfrow=c(3,2))
plot(true_mf1$F_y, type="l", lwd=4, xlab="Year", ylab="Fishing mortality", ylim=c(0,max(true_mf1$F_y)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
for(i in 1:lh_mf1$nfleets){
  lines(true_mf1$F_ft[i,], col=cols[i])
}
plot(true_mf1$R_t, type="l", lwd=4, xlab="Year", ylab="Recruitment", ylim=c(0,max(true_mf1$R_t)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true_mf1$SPR_t, type="l", lwd=4, xlab="Year", ylab="SPR", ylim=c(0,1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(true_mf1$D_t, type="l", lwd=4, xlab="Year", ylab="Relative spawning biomass", ylim=c(0,max(c(1,max(true_mf1$D_t)))), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
plot(colSums(true_mf1$Cw_ft), type="l", lwd=4, xlab="Year", ylab="Catch", ylim=c(0,max(colSums(true_mf1$Cw_ft))*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5)
for(i in 1:lh_mf1$nfleets){
  lines(true_mf1$Cw_ft[i,], col=cols[i])
}
plot(true_mf1$I_ft[1,], type="l", xlab="Year", ylab="Abundance index", ylim=c(0,max(true_mf1$I_ft)*1.1), xaxs="i", yaxs="i", cex.axis=1.5, cex.lab=1.5, col=cols[1])
lines(true_mf1$I_ft[2,], col=cols[2])

Move the generated data from an array to a data frame to plot the data.

LF_list <- lapply(1:true_mf1$nfleets, function(x){
  return(true_mf1$LF[,,x])
})
LF_df <- LFreq_df(LF_list)
plot_LCfits(LF_df=LF_df)
data_mf1 <- list("years"=1:true_mf1$Nyears, "LF"=true_mf1$LF, "I_ft"=true_mf1$I_ft, "C_ft"=true_mf1$Cw_ft, "neff_ft"=true_mf1$obs_per_year)
inputs_mf1 <- create_inputs(lh=lh_mf1, input_data=data_mf1)

For now, use the multinomial distribution for multiple fleets, specifying LFdist=0.

rich_mf1 <- run_LIME(modpath=NULL, 
                  input=inputs_mf1,
                  data_avail="Index_Catch_LC",
                  C_type=2,
                  LFdist=0)

Check that the data-rich model converges:

gradient <- rich_mf1$opt$max_gradient <= 0.001
hessian <- rich_mf1$Sdreport$pdHess
hessian==TRUE & gradient == TRUE
plot_LCfits(Inputs=rich_mf1$Inputs,
            Report=rich_mf1$Report)
plot_output(Inputs=rich_mf1$Inputs,
            Report=rich_mf1$Report,
            Sdreport=rich_mf1$Sdreport,
            lh=lh_mf1,
            True=true_mf1,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("SPR"=c(0,1)))

With length data only, we need to estimate the total fishing mortality (as opposed to annual fishing mortality for each fleet). It's also useful to set the fishing mortality penalty to something relatively small to help the estimation.

inputs_mf1$SigmaF <- 0.1
lc_mf1 <- run_LIME(modpath=NULL, 
                  input=inputs_mf1,
                  data_avail="LC",
                  LFdist=0,
                  est_totalF=TRUE)

gradient <- lc_mf1$opt$max_gradient <= 0.001
hessian <- lc_mf1$Sdreport$pdHess
hessian==TRUE & gradient == TRUE
plot_LCfits(Inputs=lc_mf1$Inputs,
            Report=lc_mf1$Report)
plot_output(Inputs=lc_mf1$Inputs,
            Report=lc_mf1$Report,
            Sdreport=lc_mf1$Sdreport,
            lh=lh_mf1,
            True=true_mf1,
            plot=c("Fish","Rec","SPR","ML","SB","Selex"),
            set_ylim=list("SPR"=c(0,1)))


merrillrudd/LIME documentation built on June 20, 2020, 2:58 p.m.