Code Monkey home page Code Monkey logo

craig44 / spatialsablefishassessment Goto Github PK

View Code? Open in Web Editor NEW
2.0 3.0 1.0 10.81 MB

A R package that contains TMB stock assessment models and auxiliary functions. Initially it was built for Sablefish, but could be fit to any stock that exhibits sexual dimorphism, has two fishing fleets and generalized number of spatial regions.

Home Page: https://craig44.github.io/SpatialSablefishAssessment/

R 45.93% TeX 1.76% CSS 0.01% C++ 52.30%
fisheries r spatial

spatialsablefishassessment's Introduction

Check package

About

SpatialSablefishAssessment is a R package that contains TMB models that can be used as operating models (OMs) or Estimation Models (EMs), it also contains a bunch of utility R functions for checking inputs and visualizing/summarizing model outputs/fits to observations. The models are developed for the Alaskan sablefish stock region, but the TMB models are fairly general and can be applied to any assessment that has two fisheries, two sexes and assumes an annual cycle (time-step). There are two online Gitbook resources that are related to this package. The first is the online documentation which describes the TMB models, expected inputs and functions to investigate and summaries model fits. There is an additional online Gitbook that relates to my post-doctoral research which uses this R package can be found here.

There are currently three TMB models contained in this package

  • TagIntegrated A generalized spatially disaggregated model that assumes two fisheries, two sexes and an annual cycle
  • TagIntegratedValidate This model is used to unit-test TagIntegrated. Any change to TagIntegrated should be incorporated into TagIntegratedValidate
  • Assessment The closest version to the current ADMB model that is used for the current assessment (needs further testing and comparisons to current ADMB assessment model before being used for management advice).

Install

Before installing, it is advised to check that the R package is passing all unit-tests and you have Rtools correctly installed (see here). It is advised that you have TMB installed before attempting to install this package. In addition to installing TMB, make sure you can compile a TMB example model i.e., TMB::compile(file = system.file("examples", "simple.cpp",package = "TMB")). Once TMB is installed and you can successfully compile a TMB model, you should be able to install this package following

devtools::install_github("Craig44/SpatialSablefishAssessment")

Using SpatialSablefishAssessment

Configuring and checking model inputs (data and parameters)

This package contains TMB models and summarizing and plotting functions for a range of models used during my sablefish research. Users are responsible for configuring the data and parameter structures that are passed to the TMB::MakeADFun function which compiles the model. Each model type (defined by data$model) will expect slightly different input data and parameters structures. For

  • TagIntegrated has described inputs found here
  • Assessment I haven't documented this model yet, the best place to look is the source TMB code found here

An alternative place to look for expected names and dimensions for elements of data and parameter is an example or the source code for the model (see here). To view an example data and parameter for the TagIntegrated model run the following code

load(system.file("testdata", "MockSablefishModel.RData",package="SpatialSablefishAssessment"))
names(data)
names(parameters)
region_key

Once you have built the data and parameter objects then you can check that the dimensions are consistent with the model by using,

validate_input_data_and_parameters(data, parameters)

This function will report a message telling you either success or if one of the objects dimensions are off, then you will need to fix this because it is likely if you pass this to the TMBs MakeADFun it will crash your R session.

The following list are some useful utility functions contained in this package to visualize data inputs. All functions should be documented and queried using the usual R ? method

  • plot_input_observations
  • plot_input_catches
  • plot_mean_weight
  • plot_age_length_matrix

Once you have checked the data and parameter objects you can build the TMB model following,

my_model = TMB::MakeADFun(data = data,
                               parameters = parameters,
                               DLL = "SpatialSablefishAssessment_TMBExports", silent  = T)

Simple sanity checks

It is possible to configure a model that has zero gradients for parameters, as well as NaN or Inf in the likelihood evaluations. These usually occur when users ask the model to calculate a predicted value in a region or year that has no fish which can cause undefined behavior in some likelihood functions. To check this is not the case use the following function

pre_optim_sanity_checks(my_model)

Optimisation

## if your model is producing NA's or weird behaviour during optimisation the following can be useful
DEBUG_estimation = F
if(DEBUG_estimation) {
  mle_obj$env$tracepar = F
  options(warn=2) # covert warnings to errors and stop optimisations
}

## optimise
mle_optim = nlminb(start = my_model$par, objective = my_model$fn, gradient  = my_model$gr, control = list(iter.max = 10000, eval.max = 10000))

# Try and improve the optimsation running the model for two additional Newton Raphson iterations
try_improve = tryCatch(expr =
                         for(i in 1:2) {
                           g = as.numeric(my_model$gr(mle_optim$par))
                           h = optimHess(mle_spatial$par, fn = my_model$fn, gr = my_model$gr)
                           mle_optim$par = mle_spatial$par - solve(h,g)
                           mle_optim$objective = my_model$fn(mle_optim$par)
                         }
                       , error = function(e){e})

try_improve

Check convergence

After a model has successfully converged during optimization, you should check there are no parameters at bounds, gradients are small and you have a positive definite hessian matrix. This can be achieved by using the following function.

post_optim_sanity_checks(my_model)

Fixing estimable parameters at input values

?fix_pars()

Sharing parameter estimates among estimable variables i.e., male and female having a common selectivity or survey catchability the same among spatial regions

?set_pars_to_be_the_same()

If you are using the TagIntegrated model then there is a special function called set_up_parameters that will set a range of parameters as fixed or shared depending on user inputs.

Model Summary

Once you are satisfied that the model has converged at global minimum, then you can get the model to report model quantities

## get MLE quantities
mle_report = my_model$report(mle_optim$par)

#########
## Plot interesting
## Model quantities i.e., recruitment SSBs model fits etc
#########

## movement assumption
plot_movement(mle_report, region_key = region_key)
# starting values
plot_movement(OM_report, region_key)
# plot selectivities
plot_selectivities(mle_report)
# starting values
plot_selectivities(OM_report)

## Regional SSBs
ssb_plt = plot_SSB(mle_report, region_key = region_key)
ssb_plt
## sum SSB over all regions
ggplot(ssb_plt$data %>% group_by(Year) %>% summarise(total_ssb = sum(SSB)), aes(x = Year, y = total_ssb)) +
  geom_line(linewidth = 1.1) +
  ylim(0,NA)

## plot F's
plot_fishing_mortalities(MLE_report = mle_report, region_key = region_key)

## plot fits to observations

# catch and index
plot_catch_fit(MLE_report = mle_report, region_key = region_key) + facet_wrap(label~Region, ncol = n_regions) + ylab("Catch (mt)")
plot_index_fit(MLE_report = mle_report, region_key = region_key)

# survey AFs
first_year_set = c(1981, seq(from = 1985, to = 1993, by = 2), 1996:1999)
plot_AF(MLE_report = mle_report, region_key = region_key, label = "srv_dom_ll", subset_years = first_year_set, sex = "male") +
  ggtitle("Male survey AF") +
  guides(shape = "none", linetype = "none") +
  ylim(0,20)
plot_AF(MLE_report = mle_report, region_key = region_key, label = "srv_dom_ll", subset_years = first_year_set, sex = "female") +
  ggtitle("Female survey AF") +
  guides(shape = "none", linetype = "none")
  
# fishery LFs
# Fixed gear
plot_LF(MLE_report = mle_report, region_key = region_key, label = "fixed", subset_years = 1991:1999, sex = "male") +
  ggtitle("Male fixed LF") +
  guides(shape = "none", linetype = "none")
plot_LF(MLE_report = mle_report, region_key = region_key, label = "fixed", subset_years = 1991:1999, sex = "female") +
  ggtitle("Female fixed LF") +
  guides(shape = "none", linetype = "none")

# plot by tag releases event
tag_fits_by_age_sex = get_tag_recovery_obs_fitted_values(mle_report, region_key = region_key)
tag_fits = tag_fits_by_age_sex %>% group_by(release_event, unique_recovery_id) %>% summarise(observed = sum(observed), predicted = sum(predicted), recovery_year = unique(recovery_year), recovery_region = unique(recovery_region), release_region = unique(release_region), release_year = unique(release_year))
tag_fits$resid = tag_fits$observed - tag_fits$predicted
tag_fits$stand_resid = tag_fits$resid / tag_fits$predicted
tag_fits$resid_sign = ifelse(tag_fits$resid < 0, "negative", "positive")
unique_release_events = unique(tag_fits$release_event)
gplt = ggplot(tag_fits %>% filter(release_event %in% unique_release_events[1:16]), aes(x = recovery_year, y = recovery_region)) +
  geom_point(aes(size = abs(stand_resid), col = resid_sign)) +
  labs(x = "Recovery year", y = "Recovery region", size = "Pearson residuals") +
  theme_bw() +
  scale_size_area() +
  facet_wrap(~release_event) +
  scale_x_discrete(breaks = every_nth(n = 5))

Standard errors for derived quantities

spatialsablefishassessment's People

Contributors

benwilliams-noaa avatar craig44 avatar dgoethel-noaa avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

ovec8hkin

spatialsablefishassessment's Issues

Future Features

  • ADD beverton Holt SR relationship
  • ADD recruitment_deviation_estimation indicator, so users can turn off the estimation of recruit devs when data$rec_devs_sum_to_zero == 1. Currently when we constrain the recruitment deviations to sum = 0 then you have to estimate all years, but sometimes end years are not well informed and may want to be fixed during model investigations.
  • allow for general number of surveys to exist in the model

ADD projection component

Recruitment

Options for projected recruit devs

  • Simulate from normal distribution with sigma R data$future_recruitment_type = 0
  • Empirically resample from input recruitment deviations over a given period data$future_recruitment_type = 1 use data$year_ndx_for_empirical_resampling to specify period to resample

Fishing mortality

  • User specifies F values during projection (unlikely useage) data$future_fishing_type = 0 populate data$future_fishing_inputs_trwl and data$future_fishing_inputs_fixed with F values
  • User specifies Catch values during projection (more likely) data$future_fishing_type = 1 populate data$future_fishing_inputs_trwl and data$future_fishing_inputs_fixed with future catches
  • The model will calculate a Fmsy based on long-term deterministic productivity and apply that during the projection period. Create an R function find_FMSY which will search over a range of fishing mortality rates to find the one that yields a desired projected biomass outcome.

Include Taylor & Methot Recruitment Bias Ramp

Are there currently plans to integrate the Taylor & Methot (2011) recruitment bias ramp calculation into any or all of the TMB models that come packaged here?

This calculation was recently integrated into the official Alaska Sablefish ADMB stock assessment model and resulted in moderate changes to estimates of pre 1970 SSB and recruitment deviations.

Add the option to treat catchability as nuisance parameter

There are ways to solve MLE estimates for catchability parameters given observed and predicted values assuming a catchability of 1.

#' Nuicance Q code
#' Assumes lognormal likelihood
#' Defined for 3 prior values uniform, uniform-log, log-normal

set.seed(123)
N = 30
obs_std = 0.02
sig_p = 0.6
q = 0.0634

expected = rlnorm(N, log(23), sig_p)
observed_vals = rlnorm(N, log(q*expected) - 0.5*obs_std * obs_std, obs_std)
plot(1:N, observed_vals, col = "red", lwd = 2, lty = 2, type = "o", ylim = c(0,7))

## Check the analytical Q, assumes uniform prior on Q
S3 = sum(log(observed_vals / expected)/(obs_std^2))
S4 = sum(1/rep(obs_std^2, length(expected)))

q_nuisance = exp((0.5*length(observed_vals) + S3) / S4)
q_nuisance
lines(1:N, expected * q_nuisance, col = "blue", lwd = 2, lty = 3)


## Check the analytical Q, assumes uniform-log prior on Q
exp((0.5*length(observed_vals) - 1 + S3) / S4)

## Check the analytical Q, assumes LogNomral prior
mu_q = 0.1
sd_q = 0.1
exp((0.5*length(observed_vals) - 1.5 + log(mu_q)/sd_q + S3) / (S4 + 1/sd_q))

TagIntegrated Model where surveys have different selectivity types and thus different number of selectivity parameters

In a scenario where there is more than 1 survey operating, and each survey has a different selectivity type, how should users go about specifying parameters like ln_srv_sel_pars where the parameter array dimensions are conditional on the selectivity type?

I am running into an issue where my first survey has multiple time blocks and a selectivity type that requires 2 parameters, while my second survey has a single time block and a selectivity type that requires 1 parameter. How should this parameter array, and similar data and parameter structures be setup, and has the TagIntegrated model been tested against such scenarios?

@Craig44

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.