Skip to contents

Introduction

The sbt package implements the southern bluefin tuna stock assessment model in RTMB (Kristensen et al. 2016; Kristensen 2026). Its public examples use a fully simulated dataset returned by sbt_example_data(), rather than the CCSBT assessment source datasets.

The simulated example retains the dimensions, biological structure, fleet timing, and observation types needed to exercise the ESC31 model. Its catches, indices, compositions, sample sizes, and tagging and close-kin outcomes were simulated. It is therefore useful for learning and testing the complete model, but it is not a CCSBT assessment dataset and its fitted values are not stock assessment results.

Data interfaces

The public example and the private assessment workflow have deliberately different interfaces.

Interface Returns Intended use
sbt_example_data() A complete, processed, simulated model-data list Public examples, vignettes, and tests
sbtdata::sbt_load_data("2026") Frozen source objects for the named release Authorised assessment work
get_data(data_in) A processed model-data list made from an explicit high-level input list Assessment configuration and sensitivity analyses
sbt_fit(data_in = data_in) A staged fit containing the processed data and model configuration Fitting a configured assessment

The private sbtdata package does not return the processed list used by the model. It returns the individual frozen source objects. The assessment project selects those objects, writes all switches and configuration values explicitly in data_in, and passes that list to get_data() or sbt_fit().

source_data <- sbtdata::sbt_load_data("2026")

data_in <- list(
  # Assessment years, switches, and selectivity configuration are written here.
  catch = source_data$catch,
  cpue = source_data$cpue
  # Other source objects follow explicitly.
)

data <- get_data(data_in)

The full assessment configuration belongs in the private assessment repository; it is not reproduced in this public package.

Source datasets and simulated counterparts

The assessment source datasets that were formerly exposed as package-level objects have been removed from sbt. The public example retains a simulated, processed counterpart for every observation stream and biological input needed by the model. The names below are useful when translating a private data_in configuration into the processed list described on this page.

Private source object What it supplies Simulated processed counterpart
length_mean Mean length by year, season, and age length_mu_ysa
length_sd Standard deviation of length by age length_sd_a
catch Reported catch by year and fishery catch_obs_ysf
catch_UA Unaccounted catch additions Included in catch_obs_ysf after processing
scenarios_surface, scenarios_LL1 Historical catch-scenario multipliers Applied before catch_obs_ysf is created
POPs Parent–offspring matches and comparisons pop_obs
paly Probability of age given length and year paly
HSPs Half-sibling matches and comparisons hsp_obs
GTs Gene-tag releases, samples, and matches gt_obs
aerial_survey Juvenile aerial-survey observations aerial_survey
aerial_cov Aerial-survey covariance matrix aerial_cov
troll Trolling-survey index and uncertainty troll_years, troll_obs, and troll_sd
cpue Longline CPUE index and uncertainty cpue_years, cpue_obs, and cpue_sd
age_freq Fishery age compositions and effective sample sizes af_obs, af_n, af_year, and fishery and age bounds
length_freq Fishery and CPUE length compositions lf_obs, lf_n, cpue_lfs, and associated year and fishery indices
tag_reporting Conventional-tag reporting rates tag_rep_rates_ya
tag_releases Conventional-tag releases tag_release_cta
tag_recaptures Conventional-tag recaptures tag_recap_ctaa

The legacy objects POPs_v1, data_csv1, data_labrep1, and data_par1 are also no longer part of the public package. They support historical ADMB comparisons and belong with the private assessment and comparison material, rather than the current public example. Selectivity timing, likelihood switches, priors, bounds, and other model configuration are ordinary elements of the processed list and can be inspected with names(data) below.

The Cape Town procedure controls returned by sbt_ctp_controls() remain public because they define an algorithm; they are not stock-assessment observations.

Simulating the example

The simulated data are generated from an sbt operating model. The model is first evaluated at its generating parameters to obtain expected compositions, abundance indices, tagging outcomes, and close-kin probabilities. Observation error is then applied using the corresponding model sampling distributions: multinomial draws for compositions, lognormal draws for abundance indices, binomial draws for close-kin and gene-tagging outcomes, and Dirichlet-multinomial draws for conventional-tag recaptures. Catch histories and sampling designs are also simulated inputs.

sbt_example_simulate() performs those draws when this page is rendered. Its default reproduces the bundled realisation exactly; supplying a seed produces a new observation realisation from the same operating model. The returned data have already been processed, so they can be supplied directly to sbt_fit().

library(sbt)
library(tidyverse)
library(kableExtra)
library(scales)

theme_set(theme_bw())

simulation <- sbt_example_simulate()
data <- simulation$data
truth <- simulation$truth

The simulated population trajectory covers 1931–2025, and the catch histories cover 1952–2025. The data include all major observation types used by the model, including the conventional-tag likelihood.

The catch histories retain broad fleet timing and smooth assessment-like shapes, but use independent round-number fleet totals and reproducible annual perturbations of up to 10%. They do not reproduce observed annual or aggregate catch values.

Observation streams in the simulated example.
Data stream Processed object Number of records
Catch catch_obs_ysf 395
CPUE index cpue_obs 57
Aerial survey aerial_survey 20
Trolling index troll_obs 29
Age compositions af_obs 88
Fishery length compositions lf_obs 213
CPUE length compositions cpue_lfs 57
Parent--offspring pairs pop_obs 9005
Half-sibling pairs hsp_obs 116
Gene tagging gt_obs 8
Conventional tagging tag_release_cta / tag_recap_ctaa 73

The processed object contains the observations alongside the dimensions, indices, biological arrays, switches, and priors required by the RTMB model.

names(data)
 [1] "last_yr"               "M_switch"              "age_increase_M"
 [4] "length_m50"            "length_m95"            "paly"
 [7] "aerial_survey"         "aerial_cov"            "harvest_wall_strength"
[10] "harvest_wall_onset"    "harvest_wall_ceiling"  "harvest_wall_scale"
[13] "removal_switch_f"      "sel_min_age_f"         "sel_max_age_f"
[16] "sel_end_f"             "af_switch"             "lf_switch"
[19] "lf_minbin"             "cpue_switch"           "cpue_a1"
[22] "cpue_a2"               "cpue_sel_fishery"      "cpue_lf_switch"
[25] "cpue_lf_sel_fishery"   "aerial_switch"         "troll_switch"
[28] "pop_switch"            "hsp_switch"            "hsp_false_negative"
[31] "gt_switch"             "tag_switch"            "tag_var_factor"
[34] "first_yr"              "n_year"                "n_season"
[37] "min_age"               "max_age"               "n_age"
[40] "n_length"              "n_fishery"             "age_a"
[43] "length_mu_ysa"         "length_sd_a"           "weight_fya"
[46] "first_yr_catch"        "first_yr_catch_f"      "n_catch"
[49] "catch_year"            "catch_obs_ysf"         "sel_change_year_fy"
[52] "pop_obs"               "hsp_obs"               "gt_obs"
[55] "troll_years"           "troll_obs"             "troll_sd"
[58] "cpue_years"            "cpue_obs"              "cpue_sd"
[61] "cpue_q_yrs"            "cpue_q_years"          "af_min_age"
[64] "af_max_age"            "n_af"                  "af_year"
[67] "af_fishery"            "af_obs"                "af_n"
[70] "dl_l"                  "alk_ysal"              "lf_year"
[73] "lf_fishery"            "lf_season"             "lf_obs"
[76] "lf_n"                  "lf_raw"                "lf_slices"
[79] "af_sliced"             "af_sliced_ysfa"        "cpue_lfs"
[82] "cpue_lf_years"         "cpue_n"                "tag_shed_immediate"
[85] "tag_shed_continuous"   "tag_rep_rates_ya"      "tag_rel_min_age"
[88] "tag_rel_max_age"       "tag_release_cta"       "tag_recap_ctaa"
[91] "tag_recap_max_age"     "min_K"                 "n_K"
[94] "n_T"                   "n_I"                   "n_J"
[97] "priors"               

Fleet structure

The six catch fleets retain the assessment model’s timing and selectivity structure. A seventh selectivity block is used for the CPUE index, but does not have catch.

Fishery Main component Model season Catch-year accounting
LL1 Japanese longline 2 January–December
LL2 Korean and Taiwanese longline 2 January–December
LL3 Other longline 1 July–June
LL4 Spawning-ground longline 1 July–June
Indonesia Indonesian spawning-ground fishery 1 July–June
Australia Surface fishery 1 July–June
CPUE block Selectivity used by the CPUE likelihood 2 Index year; no catch

The model season identifies where the fleet operates within the two-step annual population dynamics; it is distinct from the reporting interval for its catch.

Inspecting the processed inputs

The following code converts selected arrays in the processed data list into tidy data frames. The public vignettes no longer rely on package-level source datasets.

Catch and abundance indices

ggplot(catch_plot_data, aes(x = Year, y = Catch)) +
  geom_line(colour = fit_expected_colour, linewidth = 0.45) +
  facet_wrap(~Fishery, scales = "free_y", ncol = 2) +
  labs(x = "Year", y = "Catch") +
  scale_x_continuous(breaks = pretty_breaks()) +
  scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.05)))
Figure 1: Simulated catch inputs by fishery.
ggplot(index_plot_data, aes(x = Year, y = Value)) +
  geom_line(colour = fit_expected_colour, linewidth = 0.45) +
  geom_point(colour = fit_expected_colour, size = 1) +
  facet_wrap(~Series, scales = "free_y", ncol = 2) +
  labs(x = "Year", y = "Simulated index") +
  scale_x_continuous(breaks = pretty_breaks()) +
  scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.05)))
Figure 2: Simulated CPUE, aerial-survey, and trolling indices. Each panel has its own scale.

Composition data

ggplot(length_snapshot, aes(x = Length, y = Proportion, colour = factor(Year))) +
  geom_line(linewidth = 0.5) +
  facet_wrap(~Fishery, scales = "free_y", ncol = 2) +
  labs(x = "Fork length (cm)", y = "Proportion", colour = "Year") +
  scale_x_continuous(breaks = pretty_breaks(n = 5)) +
  scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.05)))
Figure 3: Simulated length-composition proportions for the three most recent observations in each fishery.
ggplot(age_snapshot, aes(x = Age, y = Proportion, colour = factor(Year))) +
  geom_line(linewidth = 0.55) +
  geom_point(size = 0.9) +
  facet_wrap(~Fishery, scales = "free_y", ncol = 1) +
  labs(x = "Age", y = "Proportion", colour = "Year") +
  scale_x_continuous(breaks = pretty_breaks(n = 7)) +
  scale_y_continuous(limits = c(0, NA), expand = expansion(mult = c(0, 0.05)))
Figure 4: Simulated age-composition proportions for the three most recent observations in each fishery.

Biological inputs

These plotting functions work directly from the processed model-data list.

plot_length_at_age(data, years = growth_plot_years)
Figure 5: Mean length at age by season for the first, middle, and final model years.
plot_weight_at_age(data, years = growth_plot_years)
Figure 6: Weight at age by fishery for the first, middle, and final model years.
plot_paly(data)
Figure 7: Simulated conditional probability of age given length and year.

From data to a fit

Pass the processed simulated object directly to sbt_fit(). The model vignette continues from this point, fits this exact simulated realisation, and compares the fitted relative TRO with the generating truth.

fit <- sbt_fit(data)

The full optimisation is deliberately not repeated while rendering the data page. It is run as follows, and the resulting fit is bundled for the model vignette.

fit <- sbt_optimise(
  fit,
  n_passes = 2L,
  control = list(eval.max = 10000L, iter.max = 10000L),
  check = TRUE
)

References

Kristensen, Kasper. 2026. RTMB: ’R’ Bindings for ’TMB’. https://doi.org/10.32614/CRAN.package.RTMB.
Kristensen, Kasper, Anders Nielsen, Casper W. Berg, Hans Skaug, and Bradley M. Bell. 2016. “TMB: Automatic Differentiation and Laplace Approximation.” Journal of Statistical Software 70 (5): 1–21. https://doi.org/10.18637/jss.v070.i05.