Skip to contents

What this study can establish

This is the first, deliberately bounded N09 validation increment. We simulate data from known negative-binomial mixed and spatial models, fit both correctly specified and deliberately incomplete candidates, and examine how the existing residual diagnostics behave. It is a study of operating characteristics, not just a check that plotting functions run.

There are three separate questions:

  1. Do the PIT calculations behave sensibly when the generating distribution is known, before any parameters have been estimated?
  2. How do parameter fitting and the choice of latent-effect conditioning change the diagnostics?
  3. Which checks reveal deliberately omitted structure, and which can miss it?

No calculation, conditioning default, or default panel has been changed by this study. The conclusions below apply to these designs, not to every CPUE family or model. The residual article remains the guide to everyday usage. Randomised quantile residuals provide the underlying distributional idea (Dunn and Smyth 1996); fitted mixed-model diagnostics require care over their conditioning and interpretation (Waagepetersen 2006).

Fixed design and predictive targets

Each backend uses 100 independent datasets, with 480 observations over six years. New latent effects and responses are generated for each dataset, while the sampling design is held fixed. The response is a simulated count per standardised sampling unit: it could represent CPUE, not necessarily total catch. Both models use a log link and NB2 conditional variance μ+μ2/4\mu + \mu^2/4.

Backend Generating structure Fitted candidates
glmmTMB Year, a continuous covariate, and 20 vessel random intercepts; four observations per vessel/year Full model; omit the covariate
sdmTMB Year, the same type of covariate, a persistent spatial field, and an independent yearly spatial field; 80 stations Full model; omit the covariate; omit the yearly field

The covariate distribution shifts gradually through time. The spatial case uses a fixed 25-knot mesh in a 100 by 100 coordinate domain, range 30, spatial SD 0.45, and yearly-field SD 0.6. The same mesh generates and fits the data; this is not a study of mesh approximation error. Data generation uses the native simulate_new() interface, with explicit known parameters, not a bootstrap from an estimated model. The implementations are described by Brooks et al. (2017) and Anderson et al. (2025).

Every candidate is fitted once by maximum likelihood. There are no replacement datasets or hidden convergence retries. The production study uses 499 response simulations per diagnostic, batches of 50, and a 100-point response ECDF grid. Three separate pilot datasets per backend checked execution and timing; they do not appear in any results below.

conditioning Quantity held fixed or resimulated Backends in this study
"fitted" Hold estimated latent effects at their fitted values; simulate new responses Both
"conditional_draw" Hold non-latent parameters fixed; draw one joint approximate conditional latent-effect vector and share it across all response simulations sdmTMB
"new_effects" Hold estimated non-latent parameters fixed; simulate new latent effects and responses in each replicate Both

The existing defaults are "new_effects" for glmmTMB and "fitted" for sdmTMB. A single conditional draw is not a posterior predictive calculation integrated over many latent draws. These schemes ask different questions; a plot that looks closer to its reference is not, by itself, a reason to select one. Native sdmTMB conditioning is documented in simulate.sdmTMB().

Fit eligibility and failures

A fit is eligible when its optimiser reports convergence, its reported Hessian is positive definite, and its log likelihood is finite. Gradients and warnings are recorded separately, not used as an undisclosed exclusion rule. The following denominators include every attempted fit. Diagnostic summaries use eligible fits only; their usable counts are shown below.

fit_table <- study$fit_summary
fit_table$scenario <- scenario_labels[fit_table$scenario]
fit_table$largest_gradient <- format(fit_table$largest_gradient, scientific = TRUE, digits = 3)
knitr::kable(fit_table[, c("backend", "scenario", "attempted", "eligible", "warnings", "errors", "largest_gradient")],
  col.names = c("Backend", "Candidate", "Attempted", "Eligible", "Warnings", "Errors", "Largest gradient"), digits = 4)
Backend Candidate Attempted Eligible Warnings Errors Largest gradient
glmmTMB.full glmmTMB Full model 100 100 0 0 1.05e-02
glmmTMB.omit_x glmmTMB Omit covariate 100 100 0 0 3.39e-03
sdmTMB.full sdmTMB Full model 100 100 0 0 2.78e-07
sdmTMB.omit_st sdmTMB Omit yearly field 100 100 0 0 2.07e-05
sdmTMB.omit_x sdmTMB Omit covariate 100 100 0 0 1.62e-07

All 500 attempted fits were eligible, and all 1,960 diagnostic/control records completed without captured warnings or errors. The largest recorded glmmTMB gradient was approximately 0.0105; gradients were reported, not used to change the pre-specified eligibility rule. An eligible fit is not proof of an adequate model or a perfectly estimated latent covariance. Fit-status details, including excluded attempts, are retained in the downloadable results object.

First check the reference itself

Before interpreting any fitted-model results, an independent-uniform control found a grid-alignment problem in bayesplot 1.16.0, the optional plotting dependency used by influ2’s PIT ECDF panels. Its last 100 reference limits are calculated for 1:100 / 100, but are displayed at seq(0, 1, length.out = 100). The empirical curve and the limits consequently refer to different horizontal positions. This finding concerns that installed version and method, not the underlying theory of simultaneous ECDF bands (Säilynoja et al. 2022).

The control uses 10,000 independent samples of 480 uniform values. Crossing means that at least one empirical-CDF value lies outside the reference limits. This table is the frozen original audit, including the pre-correction display. The current plotting correction is described immediately below it.

audit <- study$band_audit
audit$Reference <- c(displayed = "bayesplot 1.16.0, as displayed",
  aligned = "Same limits at their own grid", dkw = "Independent DKW bound")[audit$method]
audit$Crossing <- percent(audit$rate)
audit$Interval <- paste(percent(audit$lower), "to", percent(audit$upper))
knitr::kable(audit[, c("Reference", "n", "Crossing", "Interval")],
  col.names = c("Reference", "Samples", "Crossing rate", "95% Monte Carlo interval"))
Reference Samples Crossing rate 95% Monte Carlo interval
bayesplot 1.16.0, as displayed 10000 12.5% 11.8% to 13.1%
Same limits at their own grid 10000 4.8% 4.4% to 5.2%
Independent DKW bound 10000 4.7% 4.3% to 5.1%

The original displayed limit crossing rate was 12.5%, not approximately 5%. Follow-up correction, 12 September 2026: influ2 now aligns bayesplot’s unchanged limits and the empirical CDF on (0:K) / K, including the exact zero-endpoint limits. Both PIT plots use that grid, and the difference plot subtracts it from every curve. Repeating the same control through the corrected public plotting function gives 477 crossings in 10,000 samples (4.77%), matching the original aligned audit. The separate follow-up script reproduces this without model fits or changes to the frozen artefact.

Stored PIT values, the normal-score Q-Q calculation, response ECDF, and default panels are unchanged. Even correctly aligned independent-uniform limits are not calibrated 5% thresholds for fitted-model residuals. The archived displayed_band_crossing metrics deliberately retain the original display; they have not been relabelled or recomputed using the corrected plot.

For the main study we therefore use an independent summary: the exact maximum distance of the empirical PIT CDF from uniformity, D=supu|F̂(u)u|D=\sup_u|\widehat F(u)-u|. We record whether it exceeds the 95% Dvoretzky–Kiefer–Wolfowitz (DKW) bound log(2/0.05)/(2n)\sqrt{\log(2/0.05)/(2n)}(Massart 1990). This controls crossing probability under independent uniform values, but it is not a calibrated hypothesis test for fitted-model residuals. There is no fitted-model p-value or automatic pass/fail model selection here.

Known-truth controls

For each generated dataset, two controls use the actual conditional mean, realised latent effects, and NB2 size:

  • The analytic randomised PIT is F(y1)+U{F(y)F(y1)}F(y-1)+U\{F(y)-F(y-1)\}, with an independent uniform randomiser.
  • The finite-simulation control generates 499 independent response replicates from that same known distribution and uses as_influ_residuals().

Neither control estimates a model. Their comparison isolates finite-rank behaviour from parameter fitting. Normal scores remain qnorm(pit); Pearson residuals are not used.

oracle <- study$summary[study$summary$scenario == "oracle", ]
oracle$Control <- scheme_labels[oracle$conditioning]
oracle$Interval <- paste(percent(oracle$lower), "to", percent(oracle$upper))
knitr::kable(oracle[, c("backend", "Control", "usable", "crossings", "Interval", "residual_sd")],
  col.names = c("Backend", "Control", "Datasets", "Crossings", "95% Monte Carlo interval", "Mean residual SD"), digits = 3)
Backend Control Datasets Crossings 95% Monte Carlo interval Mean residual SD
glmmTMB.oracle.analytic_truth glmmTMB Known truth: analytic 100 4 1.6% to 9.8% 0.999
glmmTMB.oracle.finite_truth glmmTMB Known truth: 499 simulations 100 2 0.6% to 7.0% 0.999
sdmTMB.oracle.analytic_truth sdmTMB Known truth: analytic 100 4 1.6% to 9.8% 1.002
sdmTMB.oracle.finite_truth sdmTMB Known truth: 499 simulations 100 4 1.6% to 9.8% 1.002

With only 100 datasets per backend, small differences between these controls are Monte Carlo variation, not evidence of equivalence or a preferred count. The larger independent-uniform audit checks the reference separately.

Fitting and conditioning change the picture

The full glmmTMB model crossed the DKW reference in 0/100 datasets with fitted effects and 5/100 with new effects. The full sdmTMB model crossed in 6/100 with fitted effects, 6/100 with one conditional draw, and 28/100 with new fields. The last result is not evidence that the correctly specified spatial model is wrong: the iid reference does not account for the residual dependence under that predictive target.

The following rates use 499 simulations and the primary seed. Error bars are Wilson 95% Monte Carlo intervals over independently generated datasets, not uncertainty intervals around the CPUE index. Repeated seed/count runs do not increase these denominators.

rates <- labels_for(study$summary[study$summary$scenario != "oracle", ])
ggplot(rates, aes(Model, rate, colour = Scheme)) +
  geom_hline(yintercept = .05, linetype = 3, colour = "grey45") +
  geom_pointrange(aes(ymin = lower, ymax = upper),
    position = position_dodge(width = .5)) +
  facet_wrap(~ backend, scales = "free_x") +
  scale_y_continuous(limits = c(0, 1), labels = function(x) paste0(100 * x, "%")) +
  labs(x = NULL, y = "Datasets crossing the DKW reference", colour = "Conditioning") +
  theme(legend.position = "bottom")
DKW reference crossing rates by backend, omitted structure, and conditioning scheme.

Crossing of the independent-uniform DKW reference across 100 generated datasets per backend, conditional on fit eligibility. Points show crossing rates and bars show Wilson 95% Monte Carlo intervals; the dotted line marks 5%. Colours distinguish latent-effect conditioning. These rates describe this simulation design and are not calibrated fitted-model rejection probabilities. The known-truth controls are tabulated separately.

rates$Interval <- paste(percent(rates$lower), "to", percent(rates$upper))
knitr::kable(rates[, c("backend", "Model", "Scheme", "usable", "crossings", "Interval")],
  col.names = c("Backend", "Candidate", "Conditioning", "Usable", "Crossings", "95% Monte Carlo interval"))
Backend Candidate Conditioning Usable Crossings 95% Monte Carlo interval
glmmTMB.full.fitted glmmTMB Full model Fitted effects 100 0 0.0% to 3.7%
glmmTMB.full.new_effects glmmTMB Full model New effects 100 5 2.2% to 11.2%
glmmTMB.omit_x.fitted glmmTMB Omit covariate Fitted effects 100 0 0.0% to 3.7%
glmmTMB.omit_x.new_effects glmmTMB Omit covariate New effects 100 5 2.2% to 11.2%
sdmTMB.full.conditional_draw sdmTMB Full model One conditional draw 100 6 2.8% to 12.5%
sdmTMB.full.fitted sdmTMB Full model Fitted effects 100 6 2.8% to 12.5%
sdmTMB.full.new_effects sdmTMB Full model New effects 100 28 20.1% to 37.5%
sdmTMB.omit_st.conditional_draw sdmTMB Omit yearly field One conditional draw 100 4 1.6% to 9.8%
sdmTMB.omit_st.fitted sdmTMB Omit yearly field Fitted effects 100 0 0.0% to 3.7%
sdmTMB.omit_st.new_effects sdmTMB Omit yearly field New effects 100 18 11.7% to 26.7%
sdmTMB.omit_x.conditional_draw sdmTMB Omit covariate One conditional draw 100 6 2.8% to 12.5%
sdmTMB.omit_x.fitted sdmTMB Omit covariate Fitted effects 100 1 0.2% to 5.4%
sdmTMB.omit_x.new_effects sdmTMB Omit covariate New effects 100 7 3.4% to 13.7%

Structure can remain when the marginal distribution looks plausible

Distributional agreement alone is insufficient. We also record residual association with the known omitted covariate, and a descriptive spatial neighbour score. The latter uses a symmetric four-nearest-neighbour graph within each year and residuals centred within year. It is not a new public diagnostic function or a calibrated spatial test. It provides a known-design check for spatial pattern that a pooled histogram or Q-Q plot can miss.

structure_table <- rates[, c("backend", "Model", "Scheme", "residual_sd", "covariate_spearman", "spatial_score")]
knitr::kable(structure_table,
  col.names = c("Backend", "Candidate", "Conditioning", "Mean residual SD", "Mean correlation with covariate", "Mean neighbour score"), digits = 3)
Backend Candidate Conditioning Mean residual SD Mean correlation with covariate Mean neighbour score
glmmTMB.full.fitted glmmTMB Full model Fitted effects 0.981 -0.001 NA
glmmTMB.full.new_effects glmmTMB Full model New effects 1.003 0.000 NA
glmmTMB.omit_x.fitted glmmTMB Omit covariate Fitted effects 0.972 0.613 NA
glmmTMB.omit_x.new_effects glmmTMB Omit covariate New effects 0.980 0.518 NA
sdmTMB.full.conditional_draw sdmTMB Full model One conditional draw 1.004 0.005 -0.006
sdmTMB.full.fitted sdmTMB Full model Fitted effects 0.906 -0.002 -0.105
sdmTMB.full.new_effects sdmTMB Full model New effects 0.993 0.008 0.294
sdmTMB.omit_st.conditional_draw sdmTMB Omit yearly field One conditional draw 0.995 -0.002 0.199
sdmTMB.omit_st.fitted sdmTMB Omit yearly field Fitted effects 0.974 -0.004 0.190
sdmTMB.omit_st.new_effects sdmTMB Omit yearly field New effects 0.977 0.003 0.296
sdmTMB.omit_x.conditional_draw sdmTMB Omit covariate One conditional draw 0.999 0.565 -0.025
sdmTMB.omit_x.fitted sdmTMB Omit covariate Fitted effects 0.926 0.607 -0.095
sdmTMB.omit_x.new_effects sdmTMB Omit covariate New effects 0.984 0.551 0.164

Residual SD is on the standard-normal scale. Correlations are Spearman correlations within datasets, then averaged. A missing neighbour score for glmmTMB means that no spatial graph was specified, not that spatial independence was established. Full replicate-level results additionally include fitted-mean association, year-mean variation, and the fractions of Q-Q points and response-grid points outside their pointwise intervals. Those fractions are descriptive: points within a plot are not independent replicates.

Two failures of a distribution-only interpretation are particularly clear:

  • Omitting the generating covariate leaves substantial residual association with it: mean Spearman correlation is about 0.61 for fitted-effect glmmTMB diagnostics and 0.61 for fitted-effect sdmTMB diagnostics. Yet their DKW crossing counts are only 0/100 and 1/100, respectively. Re-estimating the remaining parameters can produce a plausible pooled residual distribution without removing the omitted covariate pattern.
  • Omitting the yearly spatial field gives 0/100 DKW crossings under fitted sdmTMB conditioning, but the mean within-year neighbour score is about 0.19. Spatial pattern remains despite the reassuring marginal distribution.

For the full sdmTMB model, fitted-effect normal scores have mean SD 0.906, compared with 1.004 for the single conditional-draw scheme. The neighbour scores also differ. This supports treating conditioning as an explicit scientific choice, not declaring the method with the most normal-looking scores universally preferable.

Worked plots without refitting

The figures use the first dataset with all planned comparisons eligible: glmmTMB replicate 1 and sdmTMB replicate 1. Selection was fixed in advance and did not depend on how striking the plots looked. The multi-dataset results above carry more evidence than these individual illustrations.

validation <- readRDS(system.file("extdata", "n09-validation.rds", package = "influ2"))
mixed <- validation$examples$glmmTMB$checks
spatial <- validation$examples$sdmTMB$checks

glmmTMB: retain or omit the covariate

Both plots use fitted effects to make the conditional-response comparison explicit; this is an example choice, not a change to the glmmTMB default. They use the same observations and primary seed. Fitted-year effects can make year-wise centres look reassuring even when a covariate is omitted.

plot(mixed[["full:fitted"]], response_scale = "log1p")
Four-panel diagnostic for the full glmmTMB model with fitted vessel effects.

Existing four-panel diagnostic for the correctly specified glmmTMB model in the pre-selected example dataset, holding fitted vessel effects fixed. Q-Q, fitted-value, and year panels use normal-score PIT residuals. The Q-Q ribbon is a pointwise independent-uniform reference; the response ECDF ribbon is a pointwise predictive band. Neither supplies a calibrated fitted-model pass/fail test.

plot(mixed[["omit_x:fitted"]], response_scale = "log1p")
Four-panel diagnostic for the glmmTMB candidate omitting the covariate.

The same glmmTMB observations and fitted-effect conditioning after omitting the generating covariate. Other parameters, including negative-binomial dispersion, are re-estimated once in this incomplete candidate. A plausible marginal residual distribution does not establish that covariate-related structure has disappeared; the repeated-study correlation summary checks that separately.

sdmTMB: retain or omit the yearly spatial field

Here fitted-effect conditioning is the existing sdmTMB default. The full model can use fitted fields to explain local variation, whereas the incomplete candidate has no yearly field. Neither four-panel plot is a residual map; the neighbour summary above checks an additional spatial question.

plot(spatial[["full:fitted"]], response_scale = "log1p")
Four-panel diagnostic for the full spatial and yearly-field sdmTMB model.

Existing four-panel diagnostic for the correctly specified sdmTMB model in the pre-selected spatial dataset, holding fitted persistent and yearly spatial effects fixed. The normal-score PIT and response-distribution panels are conditional model checks. Their nominal reference bands do not account automatically for estimating latent effects from these same observations.

plot(spatial[["omit_st:fitted"]], response_scale = "log1p")
Four-panel diagnostic for the sdmTMB candidate without the yearly spatial field.

The same sdmTMB observations after omitting the yearly spatial field, retaining the fixed covariate and persistent spatial field. Fitted-effect conditioning is used again. The marginal panels and the separate within-year neighbour score address different aspects of this deliberate misspecification; absence of a strong Q-Q departure is not evidence that the omitted field is unnecessary.

The same PIT values on a uniform scale

The optional plots below reuse the saved full-model sdmTMB PIT values. They make the conditioning contrast visible without running the models again. The bands are calculated by the locally installed bayesplot and aligned by influ2 as described above. These figures use the corrected plotting code; the numerical study and its original crossing metrics remain frozen to their recorded versions.

patchwork::wrap_plots(
  plot(spatial[["full:fitted"]], type = "pit_ecdf_diff") + labs(title = "Fitted effects"),
  plot(spatial[["full:conditional_draw"]], type = "pit_ecdf_diff") + labs(title = "One conditional draw"),
  plot(spatial[["full:new_effects"]], type = "pit_ecdf_diff") + labs(title = "New effects"),
  ncol = 2
)
Three PIT ECDF difference displays contrasting sdmTMB conditioning targets.

PIT ECDF difference displays for the same full sdmTMB fit: fitted effects (upper left), one shared conditional latent draw (upper right), and new effects (lower left). Curves reuse stored PIT values; zero is the uniform reference. Pale limits are bayesplot’s independent-uniform simultaneous limits, with their evaluation grid corrected by influ2. The original study metrics remain frozen. Do not read crossings as calibrated rejection decisions. No new response simulations or model fits are performed.

Seed and simulation-count sensitivity

For dataset IDs 1–10 only, we repeat each eligible diagnostic with a second seed at 499 simulations and with the primary seed at 1,999 simulations. Models are not refitted. A conditional-draw seed also changes the one shared latent vector, so its sensitivity is not solely finite response-simulation noise. More response simulations do not average over that single latent draw.

sensitivity <- labels_for(study$sensitivity)
sensitivity$Change <- ifelse(sensitivity$variant == "second_seed", "Second seed, 499", "Same seed, 1,999")
knitr::kable(sensitivity[, c("backend", "Model", "Scheme", "Change", "paired", "flag_changes", "mean_absolute_distance_change")],
  col.names = c("Backend", "Candidate", "Conditioning", "Rerun", "Pairs", "Crossing changes", "Mean absolute change in D"), digits = 4)
Backend Candidate Conditioning Rerun Pairs Crossing changes Mean absolute change in D
glmmTMB.full.fitted.more_simulations glmmTMB Full model Fitted effects Same seed, 1,999 10 0 0.0056
glmmTMB.full.fitted.second_seed glmmTMB Full model Fitted effects Second seed, 499 10 0 0.0060
glmmTMB.full.new_effects.more_simulations glmmTMB Full model New effects Same seed, 1,999 10 0 0.0027
glmmTMB.full.new_effects.second_seed glmmTMB Full model New effects Second seed, 499 10 0 0.0047
glmmTMB.omit_x.fitted.more_simulations glmmTMB Omit covariate Fitted effects Same seed, 1,999 10 0 0.0034
glmmTMB.omit_x.fitted.second_seed glmmTMB Omit covariate Fitted effects Second seed, 499 10 0 0.0055
glmmTMB.omit_x.new_effects.more_simulations glmmTMB Omit covariate New effects Same seed, 1,999 10 0 0.0018
glmmTMB.omit_x.new_effects.second_seed glmmTMB Omit covariate New effects Second seed, 499 10 0 0.0031
sdmTMB.full.conditional_draw.more_simulations sdmTMB Full model One conditional draw Same seed, 1,999 10 0 0.0046
sdmTMB.full.conditional_draw.second_seed sdmTMB Full model One conditional draw Second seed, 499 10 1 0.0168
sdmTMB.full.fitted.more_simulations sdmTMB Full model Fitted effects Same seed, 1,999 10 0 0.0020
sdmTMB.full.fitted.second_seed sdmTMB Full model Fitted effects Second seed, 499 10 0 0.0039
sdmTMB.full.new_effects.more_simulations sdmTMB Full model New effects Same seed, 1,999 10 0 0.0032
sdmTMB.full.new_effects.second_seed sdmTMB Full model New effects Second seed, 499 10 0 0.0052
sdmTMB.omit_st.conditional_draw.more_simulations sdmTMB Omit yearly field One conditional draw Same seed, 1,999 10 0 0.0034
sdmTMB.omit_st.conditional_draw.second_seed sdmTMB Omit yearly field One conditional draw Second seed, 499 10 0 0.0111
sdmTMB.omit_st.fitted.more_simulations sdmTMB Omit yearly field Fitted effects Same seed, 1,999 10 0 0.0036
sdmTMB.omit_st.fitted.second_seed sdmTMB Omit yearly field Fitted effects Second seed, 499 10 0 0.0056
sdmTMB.omit_st.new_effects.more_simulations sdmTMB Omit yearly field New effects Same seed, 1,999 10 1 0.0024
sdmTMB.omit_st.new_effects.second_seed sdmTMB Omit yearly field New effects Second seed, 499 10 1 0.0057
sdmTMB.omit_x.conditional_draw.more_simulations sdmTMB Omit covariate One conditional draw Same seed, 1,999 10 0 0.0032
sdmTMB.omit_x.conditional_draw.second_seed sdmTMB Omit covariate One conditional draw Second seed, 499 10 1 0.0113
sdmTMB.omit_x.fitted.more_simulations sdmTMB Omit covariate Fitted effects Same seed, 1,999 10 0 0.0030
sdmTMB.omit_x.fitted.second_seed sdmTMB Omit covariate Fitted effects Second seed, 499 10 0 0.0048
sdmTMB.omit_x.new_effects.more_simulations sdmTMB Omit covariate New effects Same seed, 1,999 10 1 0.0042
sdmTMB.omit_x.new_effects.second_seed sdmTMB Omit covariate New effects Second seed, 499 10 0 0.0048

These ten paired datasets are a sensitivity screen, not an estimate precise enough to recommend a universal simulation count. Near a reference boundary, changing a binary crossing flag can exaggerate a small numerical change; read the continuous distance alongside the count. The defaults remain unchanged.

Across the 40 paired glmmTMB comparisons per sensitivity variant, no DKW flags changed. Across the 90 sdmTMB comparisons, three changed with the second seed and two with 1,999 simulations. Those counts pool different scenarios and schemes and are descriptive only; the disaggregated table is the primary sensitivity record.

Interpretation and the next review

This first increment separates three sources of behaviour: finite-simulation ranks, estimating a model from the checked observations, and the predictive target defined by conditioning. They should not be combined into a single claim that a backend’s residuals are either “valid” or “invalid”.

Review the following with Nicholas before changing statistical defaults:

  1. Keep the now-corrected reference-band display separate from the remaining question of fitted-model residual calibration.
  2. Decide which scientific question each conditioning scheme should answer, using the full-model and omitted-structure results together. Do not pick a default simply because its Q-Q curve looks closest to normal.
  3. Decide whether a later increment needs calibrated fitted-model envelopes, repeated refitting, or held-out prediction checks. None is provided here.
  4. Identify the next genuinely different design to validate, rather than extending these conclusions to all six backends or all response families.

Limitations include one family, one sample size, one fixed design and spatial mesh, balanced yearly effort, modest replication, and diagnostics evaluated on the fitting observations. There are no brms, tinyVAST, hurdle/delta, sparse sampling, range-boundary, or out-of-sample validation claims. In particular, the default four panels do not replace a spatial residual investigation.

Reproduction and compact results

The fixed protocol and developer scripts contain the data generator, seed schedule, metrics, timing pilot, and report builder. From a checkout with the recorded optional dependencies installed:

Rscript --vanilla tools/n09/test-study.R
Rscript --vanilla tools/n09/run.R production /absolute/new/output-directory
Rscript --vanilla tools/n09/report.R /absolute/new/output-directory

Use one BLAS/OpenMP thread for the recorded timing setup. Each dataset is checkpointed; resuming requires identical configuration and source hashes. The report refuses incomplete production runs. It writes replicate-level CSV files to the output directory and the compact RDS used here to inst/extdata/. The source commit records the package implementation baseline; separate hashes identify the study scripts and protocol, which were added by this increment.

knitr::kable(data.frame(Package = names(study$metadata$package_versions),
  Version = unname(study$metadata$package_versions)))
Package Version
influ2 1.1.0
glmmTMB 1.1.14
sdmTMB 1.1.0
TMB 1.9.25
Matrix 1.7.6
bayesplot 1.16.0
ggplot2 4.0.3

The installed artefact contains all attempted-fit statuses, successful and failed diagnostic attempts, seeds, versions, source hashes, summaries, and the two selected sets of compact diagnostic objects. It contains no fitted models or observation-by-simulation matrices. Its compressed size is 257 KiB. The article and ordinary package tests read these results; CRAN and CI do not rerun the Monte Carlo study. Rebuilding this article is not evidence that the study was rerun under newer dependency versions.

References

Anderson, Sean C., Eric J. Ward, Phil A. English, Lewis A. K. Barnett, and James T. Thorson. 2025. “sdmTMB: An r Package for Fast, Flexible, and User-Friendly Generalized Linear Mixed Effects Models with Spatial and Spatiotemporal Random Fields.” Journal of Statistical Software 115 (2): 1–46. https://doi.org/10.18637/jss.v115.i02.
Brooks, Mollie E., Kasper Kristensen, Koen J. van Benthem, et al. 2017. “glmmTMB Balances Speed and Flexibility Among Packages for Zero-Inflated Generalized Linear Mixed Modeling.” The R Journal 9 (2): 378–400. https://doi.org/10.32614/RJ-2017-066.
Dunn, Peter K., and Gordon K. Smyth. 1996. “Randomized Quantile Residuals.” Journal of Computational and Graphical Statistics 5 (3): 236–44. https://doi.org/10.1080/10618600.1996.10474708.
Massart, Pascal. 1990. “The Tight Constant in the Dvoretzky-Kiefer-Wolfowitz Inequality.” The Annals of Probability 18 (3): 1269–83. https://doi.org/10.1214/aop/1176990746.
Säilynoja, Teemu, Paul-Christian Bürkner, and Aki Vehtari. 2022. “Graphical Test for Discrete Uniformity and Its Applications in Goodness-of-Fit Evaluation and Multiple Sample Comparison.” Statistics and Computing 32 (2): 32. https://doi.org/10.1007/s11222-022-10090-6.
Waagepetersen, Rasmus. 2006. “A Simulation-Based Goodness-of-Fit Test for Random Effects in Generalized Linear Mixed Models.” Scandinavian Journal of Statistics 33 (4): 721–31. https://doi.org/10.1111/j.1467-9469.2006.00504.x.