Prepares catch, survey, weight, and maturity data for the chosen model years
and ages. Checks input coverage, combines older ages into a plus group when
needed, and sets up mortality, catchability, and observation-error formulas.
Optional projection settings append future years. fit_tam() calls this
function automatically; call it directly to inspect a model specification.
Usage
prepare_tam(
data,
years = NULL,
ages = NULL,
N_settings = list(process = "iid", init = "exp", mu_form = NULL, sd_form = ~1),
rec_settings = list(process = "rw", init = "free", mu_form = NULL, sd = NULL, phi = NULL),
F_settings = list(process = "rw", mu_form = NULL, sd_form = ~1, age_breaks = NULL, cor_form = ~1,
mean_ages = NULL),
M_settings = list(process = "off", mu_form = NULL, mu_supplied = ~I(0.2), sd_form = ~1,
age_breaks = NULL, first_dev_year = NULL, mean_ages = NULL),
catch_settings = list(sd_form = ~1, sd_supplied = NULL),
index_settings = list(sd_form = ~1, sd_supplied = NULL, q_form = ~q_block, q_link = "log"),
proj_settings = NULL
)
# Optional projections:
# proj_settings = list(n_proj = 3, n_mean = 3, F_mult = 1, catch = NULL)Arguments
- data
A list of tidy observation data.frames:
catch,index,weight, andmaturity. See Details.- years
Consecutive historical model years (at least two). Inferred from observed data (non-projection) if
NULL.- ages
Consecutive model ages (at least two). Inferred from observed data (non-projection) if
NULL. If the ages in the data extend beyondmax(ages), the"obs"column is summed forcatchandindexdata within each year (and survey for indices). Older-age weight and maturity are retained for abundance-based aggregation insidenll_fun(), preserving biomass and mature biomass in the plus group.- N_settings
A list with elements:
process:"off"for deterministic cohort survival,"iid"for independent cohort residuals,"rw"for residuals that accumulate through time, or"ar1"for residuals correlated between years and ages. See tinyAM-model.init:"exp"(default),"free","latent","mono"or"capped", independently ofprocess. All use first-year recruitmentlog_r0as the starting anchor."exp"uses deterministic survivorship;"free"estimates fixed older-agelog_n0states;"latent"integrates them without an initial density."mono"constrains abundance to decline from r0;"capped"bounds each older age by r0 without imposing age ordering. See Details.mu_form: ordinary fixed formula for proportional cohort gains/losses, defaultNULL. Covariates come frompop_covariatesat the destination year and older age, after survivors are combined (including the plus group). Recruitment and initialization are unaffected. These effects do not identify immigration separately from mortality or observation changes. RW residuals require independent temporal mean contrasts; constant directions cancel and are rejected. See tinyAM-model.sd_form: ordinary formula for log SD of older-age survival residuals, default~ 1. Use~ factor(age)or a supplied age-sharing column indata$pop_covariates. Its design must be constant across years. Recruitment SD is controlled separately byrec_settings; initial abundance has no separate SD. Random-effect SD terms are not enabled.
- rec_settings
A list controlling recruitment separately from cohort survival:
process:"off"for recruitment exactly following its mean formula, or"rw"(default),"iid", or"ar1"for annual log-recruitment residuals. Boundary recruitment states are controlled byinit.init:"free"(default) estimates first-year recruitment and additional pre-parent-SSB boundary states as fixed parameters;"latent"integrates them without an initial density or separate SD. Independent ofprocess, including"off", and of older-ageN_settings$init. Simulations condition on these states; joint uncertainty draws can vary them. See recruitment_formulas.mu_form: one-sided formula for the expected log recruitment.NULLis allowed for RW; off/IID/AR1 require an explicit formula, such as~ 1for a constant mean. Usebh()orricker()for a median stock-recruit curve with no residuals or IID/AR1 residuals. Ordinary covariates come fromdata$pop_covariatesat the youngest modeled age. See recruitment_formulas.sd: positive fixed recruitment SD, orNULLto estimate it. This is an innovation SD for RW/AR1 and a marginal SD for IID. Must beNULLwhen process is off.phi: fixed AR1 correlation in[0, 1), orNULLto estimate it. Must beNULLfor other processes. Estimated correlations are positive.
- F_settings
A list with elements:
process:"off"makes historical F equal its explicit mean formula, without F latent states, residual SDs or correlations."iid"gives independent departures from the mean log F,"rw"for departures that accumulate over time, or"ar1"for departures correlated between years and ages."cor_rw"accumulates changes over time with AR1 correlation between annual increments at neighbouring states within each fleet. It estimates one signed age correlation per active correlation group; its SD is the marginal SD of annual log-F increments.sd_form: ordinary age-based formula for log process SD, default~ 1, evaluated ondata$catch. Sharing an SD does not share latent F states. IID SDs describe residuals; RW/correlated-RW SDs describe annual increments; stationary AR1 retains its innovation-scale convention.age_breaks: optional increasing integer interval boundaries for shared actual F. Intervals include their lower boundary and exclude their upper boundary; the final boundary must bemax(ages) + 1. For ages1:6,c(1, 2, 3, 4, 5, 7)shares F at ages 5 and 6. Ages below the first boundary have exactly zero F in all years, with no F state or process density. Positive catch observations at those ages are rejected.NULLretains separate F states at every modeled age. All mean components and process SDs must agree within a shared block; refine blocks for age-varying means. Process correlation uses ordered blocks, not replicated fish ages. With fleet labels, supply a common vector or a named list covering all fleets;NULLentries retain separate states by age within that fleet.cor_form: categorical correlation groups constant within each fleet. Default~ 1shares correlations;~ fleetestimates separate values. For AR1,list(age = ~ fleet, year = ~ 1)allows different sharing by dimension. A single formula applies to both dimensions. Sharing parameters never correlates innovations between fleets. Unused groups are omitted.mu_form: an optional formula for mean-\(F\) (coefficients estimated as log-scale parameterslog_mu_f), evaluated ondata$catch. Required for"off","iid"and"ar1"; use~ 1for one estimated mean level or~ factor(age)for age-specific means. For"rw",NULLis allowed. Mean columns constant through time cancel from RW increments and are removed with a warning. Remaining columns must be identifiable from historical year-to-year differences. Ordinary F mean designs use historical support only; projection rows carry the terminal historical design by age. No future-year coefficients are fitted. With IID residuals,iid(),rw()andar1()can add random mean effects, e.g.~ factor(age) + rw(year). Temporal mean terms must have disjoint support, for example one per fleet; overlapping temporal mean terms and structured means with temporal residual processes are not enabled.mono()andlogistic()can instead describe a rising mean age curve with no residual process or with IID/AR1 residuals, e.g.~ logistic(age). Ordinary terms supply baseline F; realized F can depart from the rising mean. Static curves are not identifiable with RW/correlated-RW residuals. See catchability_curves.double_logistic()supplies WHAM's unnormalized four-parameter dome. Catch covariates must be available even where observations are missing. They must agree across biological ages pooled into a modeled plus group. The catch responseobscannot enter an F formula. With fleet labels, each fleet has its own F states; total F is their sum for survival and Z.for_fleet()gives one fleet its own formula, e.g.~ 0 + for_fleet("Trawl", ~ factor(year) + logistic(age)) + for_fleet("Gillnet", ~ factor(year) + factor(age)). Ordinary terms outside scopes share their coefficients. Each inner formula includes an intercept unless removed explicitly; avoid redundant global and scoped baselines. smooth_formulas adds penalizeds()and age-yeart2()relationships. Smooth means support"off","iid"and"ar1"F processes; the latter combinations are experimental and require mean/process separation checks.mean_ages: optional vector of ages to include in population weighted average F (F_bar) calculations. All ages used if absent.
- M_settings
A list with elements:
process:"off"uses only supplied/mean M. Otherwise"iid","rw", and"ar1"have the same meanings as for F, on selected years/age blocks.sd_form: ordinary age-based formula for log process SD, default~ 1. Evaluated ondata$pop_covariatesand required to be constant within each fitted M age block and across years. Use finer age_breaks for distinct state SDs.mu_form: optional formula for mean-\(M\) (applied on the log scale) built ondata$pop_covariates, yielding coefficientsmu_m. These enter the log-\(M\) surface directly and may therefore be positive or negative; they intentionally avoid alog_prefix to prevent automatic back-transformation when tidied. If provided together withmu_supplied, the intercept inmu_formis dropped (warning) so supplied levels act as fixed offsets.iid(),rw()andar1()support random mean effects with IID residuals or the residual process off. Use~ 0 + rw(year)to vary supplied M through time. All mean components must be constant within fitted M age blocks. With AR1 residuals, one age-defined IID random slope is also supported, e.g.~ 0 + capelin + iid(M_age_group, by = capelin). The grouping column must be constant across years at each age and thebycolumn numeric. This experimental combination retains shared actual M within blocks; see formula_effects for the model and statistical cautions.mu_supplied: optional one-sided formula giving supplied (non-estimated) \(M\), e.g.~ I(0.2)or a column reference such as~ M_assumptionstored in thedata$pop_covariatesdata.frame.age_breaks: optional integer break points used bycut_ages()to defineage_blockssharing absolute latent M states across ages. Existing specifications retain their original interpretation. Alternatively, end atmax(ages) + 1to use explicit half-open intervals as for F: with ages1:6,c(2, 5, 7)makes blocks 2–4 and 5–6. Ages outside M process blocks retain their existing mean M; they are not set to zero. When a narrower set ofage_breaksthan modeledagesis provided, process states are only estimated for ages within the specified range; ages outside this range are fixed to their mean or assumed levels. By default, blocks usecut_ages(ages[-1], unique(range(ages[-1]))), usually one block excluding the youngest age; two older ages form separate singleton blocks. This restricts how M can trade off against recruitment; it does not guarantee identifiability.first_dev_year: one historical modeled year at which M process states begin. Defaults to the second year ifNULL. Earlier M stays at its mean or supplied value; earlier years are not coupled to the first latent state. Ignored when the M process is off.mean_ages: optional vector of ages to include in population weighted average M (M_bar) calculations. All ages used if absent.
- catch_settings
A list with elements:
sd_form: formula for log observation SD for catch-at-age data. Ordinary terms and Gaussian formula_effects are supported, e.g.~ iid(age).sd_supplied: optional one-sided formula giving supplied SDs (on the natural scale of the log-observation residuals) for catch-at-age data. When provided, the intercept is removed fromsd_formso supplied SDs act as offsets.
- index_settings
A list with elements:
sd_form: formula for log observation SD for index-at-age data. Ordinary terms and Gaussian formula_effects are supported, e.g.~ survey + rw(age, by = survey).sd_supplied: optional one-sided formula giving supplied SDs (on the natural scale of the log-observation residuals) for index-at-age data. When provided, the intercept is removed fromsd_formso supplied SDs act as offsets.q_form: formula for catchability, evaluated on the index table. Ordinary~ q_blockallows any pattern across blocks;~ mono(q_block)is non-decreasing across ordered blocks. Seemono()for independent non-decreasing curves by survey. Structured effects such as~ survey + ar1(year, by = survey)allow shared annual changes across ages.~ survey + logistic(age, by = survey)fits rising selectivity curves.~ q_key + power(N, by = q_power_group)allows abundance-dependent catchability using internally calculated abundance at survey time. Missing power-group labels mean p = 1, not missing observations. Powers require the log q link. Seepower()and formula_effects.double_logistic()allows dome-shaped selectivity and multiplies baseline q after its inverse link. Penalizeds()andt2(age, year)terms instead modify the selected q-link predictor. See smooth_formulas for supported bases, grouping and penalties.for_survey()applies a formula to one named survey, e.g.~ 0 + for_survey("RV", ~ logistic(age)) + for_survey("Sentinel", ~ q_block). Effects are built on each survey's own reporting ages, then contribute zero to the predictor elsewhere.q_link:"log"(default) allows any positive catchability;"logit"restricts catchability to between zero and one. Use the logit link only when the survey index has an absolute abundance scale and this restriction is scientifically appropriate. Relative indices or surveys affected by herding may need the log link. The same formula and optionalmono()terms work with either link. With"logit", coefficients anddqact on logit-q rather than log-q; covariate effects are no longer constant multipliers of q. This is a restriction, not a prior favouring a value near one. q can approach a boundary with large coefficients and SEs.
- proj_settings
Optional list with elements:
n_proj: number of years to project (defaultNULLdisables projections).n_mean: number of recent historical years (default3) used to average each weight type and maturity by age. Catch/index observations in projection years are missing. Other columns are copied from the last available year in each table.F_mult: multiplier of terminal historical F (default1, status quo). Can be a value of length 1 or length =n_proj. When it is a vector of length one, that multiplier is recycled across all projection years.catch: total annual catch weight, in catch-number times mean-weight units (e.g. tonnes for thousand fish and kg). Supply one value recycled across years, orn_projvalues. Specify eithercatchorF_mult, not both.catch = "observed"is restricted tofit_hindcast()evaluation; it is not a forecast input for an ordinary fit. See tinyAM-model for the catch solver and feasibility safeguards.
Value
A named list dat containing:
years,ages— modeled ranges (years includesproj_years, if used)is_proj— logical vector identifying whether year is projectedproj_years— integer vector of projection years, if usedobs— per-type tables restricted toyearsxages(includingproj_years, if used)spawn_time,spawn_time_plus— timing matrices on modeled ages and, when retained, biological plus agesW,W_catch,P— stock weight, catch weight and proportion mature matrices (year x age). Optionalweight$typedistinguishes complete stock and catch weights; stock alone supplies both uses.plus_ages,W_plus_input,P_plus_input— retained biological ages and inputs, present only when biological data extend abovemax(ages). The last retained age represents a hidden plus group. Effective modeled W/P and hidden abundanceN_pluscan then be inspected in the likelihood report (fit$rep).obs_map— stack ofobs$catchandobs$indexmapping variableslog_obs,is_missing,is_observed,observed- vector of log observations (with NA), logical vector indicating missing and observed values, and vector of non-missing values, respectively.design matrices:
sd_catch_modmat,sd_index_modmat,q_modmat, and optionallyF_modmat,M_modmatmean-level placeholders:
log_mu_fand/ormu_m(orlog_mu_supplied_m)process settings:
N_settings,rec_settings,F_settings,M_settings,catch_settings,index_settingsprojection settings:
proj_settingsAR(1) parameter assumptions,
logit_phi_*, if applicable
Details
Settings lists
Supply only the entries to change from the defaults shown in Usage. Formulas
and vectors replace an entire entry. Optional NULL entries clear a formula,
offset or age selection; sd_form = NULL restores ~ 1.
Required entries cannot be NULL.
update() retains unspecified entries from the original fit instead.
Inputs and preparation
See as_tam_data() for table keys, units, fleet-specific catch weights and
covariate routing, and cod_obs for example data. Catch and survey zeros and
missing values are excluded from the lognormal observation likelihood;
complete predictions are still calculated.
Biological ages above the modeled plus age are retained in W_plus_input,
W_catch_plus_input and P_plus_input. The population calculation derives
effective plus-group weights and maturity from their hidden abundances;
prepared terminal biological values are placeholders. Formula covariates
use the supplied modeled-age rows, avoiding circular mortality calculations.
The equations and spawning-time definition are in tinyAM-model.
Formula designs
Ordinary formula terms create design matrices. Structured formula_effects,
mono() curves and smooth_formulas also store unique effect states and
their grouping metadata. make_par() constructs the associated parameters.
Supplied M and observation SDs act as offsets; their mean/SD formulas omit
an intercept to avoid estimating another baseline. The settings below define
available terms, restrictions and data sources.
Projections
proj_settings appends future years and marks them with is_proj in the
prepared grid and tables. Stock/catch weights and maturity use recent-year
averages by biological age; covariates and spawning timing retain terminal
historical values. See tinyAM-model for forecasting and initial-state
equations, and fit_hindcast() for held-out-data evaluation.
Examples
dat <- prepare_tam(
cod_obs,
years = 1983:2024,
ages = 2:14,
N_settings = list(process = "iid", init = "exp"),
F_settings = list(process = "rw", mu_form = NULL),
M_settings = list(process = "off", mu_supplied = ~ I(0.3)),
catch_settings = list(sd_form = ~ 1),
index_settings = list(sd_form = ~ 1, q_form = ~ q_block)
)
names(dat)
#> [1] "years" "ages" "N_settings"
#> [4] "rec_settings" "F_settings" "M_settings"
#> [7] "catch_settings" "index_settings" "proj_settings"
#> [10] "obs" "is_proj" "pop_data"
#> [13] "has_fleet" "fleets" "F_data"
#> [16] "F_columns" "F_cor" "plus_ages"
#> [19] "W_plus_input" "W_catch_plus_input" "P_plus_input"
#> [22] "spawn_time_plus" "spawn_time" "P"
#> [25] "W_catch" "W" "obs_map"
#> [28] "log_obs" "is_missing" "is_observed"
#> [31] "observed" "sd_catch_modmat" "log_sd_catch_supplied"
#> [34] "sd_index_modmat" "log_sd_index_supplied" "q_modmat"
#> [37] "N_modmat" "M_terms" "F_terms"
#> [40] "log_mu_f" "F_modmat" "mu_m"
#> [43] "M_modmat" "log_mu_supplied_m" "logit_phi_n"
#> [46] "process_sd" "rec"
## With projection settings
dat <- prepare_tam(
cod_obs,
N_settings = list(process = "iid", init = "exp"),
F_settings = list(process = "rw", mu_form = NULL),
M_settings = list(process = "off", mu_supplied = ~ I(0.3)),
catch_settings = list(sd_form = ~1),
index_settings = list(sd_form = ~1, q_form = ~q_block),
proj_settings = list(n_proj = 3, n_mean = 3, F_mult = 1)
)