--- title: "End-to-End Hierarchical Lognormal Duration Workflow" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{End-to-End Hierarchical Lognormal Duration Workflow} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Scope The duration workflow is restricted to strictly positive, finite, uncensored durations modeled with a hierarchical lognormal likelihood. Zero, negative, censored, truncated, shifted-lognormal, Gamma, Weibull, survival, and mixture outcomes are outside this contract. ## Simulate durations with stored truth ```{r duration-simulation} library(gp3bayes) duration_simulation <- simulate_hierarchical_duration_data( n_participants = 16, trials_per_participant = 10, n_items = 8, baseline_median = 500, random_slope_sd = 0.15, residual_sd = 0.40, outcome_unit = "milliseconds", seed = 2030 ) duration_simulation head(duration_simulation$data) ``` The fixed effects and grouping scales are on the log-duration scale. The baseline is stored as a median in the declared outcome unit. ## Declare the duration contract ```{r duration-contract} duration_contract <- create_model_contract( family = "duration", outcome_col = "duration", participant_col = "participant_id", item_col = "item_id", trial_col = "trial_id", condition_col = "condition", predictors = c( "participant_covariate", "trial_covariate" ), interaction = c( "condition", "participant_covariate" ), random_slope = TRUE, outcome_unit = "milliseconds" ) duration_contract ``` The outcome unit is mandatory. The package never guesses a unit from column names or magnitudes. ## Prepare, convert, and audit ```{r duration-preparation} duration_prepared <- prepare_hierarchical_duration_data( duration_simulation$data, duration_contract, condition_levels = c( "control", "treatment" ) ) duration_prepared duration_prepared$decision_log ``` Explicit unit conversion uses `outcome_multiplier` and `converted_unit` together. For example, converting milliseconds to seconds is recorded as: ```{r duration-unit-conversion} duration_seconds <- prepare_hierarchical_duration_data( duration_simulation$data, duration_contract, condition_levels = c( "control", "treatment" ), outcome_multiplier = 0.001, converted_unit = "seconds" ) duration_seconds$transformations$outcome ``` ## Specify priors and check prior implications ```{r duration-specification} duration_specification <- specify_duration_model( duration_prepared, baseline = 500, intercept_scale = 1, coefficient_scale = 0.5, group_sd_scale = 1, residual_scale = 1, correlation_eta = 2, student_df = 3 ) duration_specification duration_specification$priors$table ``` ```{r duration-prior-predictive} duration_prior_predictive <- check_duration_prior_predictive( duration_specification, draws = 100, seed = 2031 ) duration_prior_predictive duration_prior_predictive$checks ``` The prior check examines overall medians, upper tails, coefficients of variation, and condition median ratios. A failure requests review and does not automatically alter the priors. ## Translate and fit through the restricted backend ```{r duration-fit, eval=FALSE} duration_translation <- translate_duration_model_to_brms( duration_specification ) duration_fit <- fit_duration_model( duration_specification, chains = 2, iter = 2000, warmup = 1000, cores = 2, seed = 2032, adapt_delta = 0.95, max_treedepth = 12, refresh = 100 ) ``` The likelihood, formula, priors, backend, and sampling algorithm are derived from the approved package specification. There is no unrestricted formula or backend argument. ## Diagnostics and posterior interpretation ```{r duration-validation, eval=FALSE} duration_diagnostics <- diagnose_duration_fit( duration_fit ) duration_posterior <- summarise_duration_posterior( duration_fit ) duration_predictive <- check_duration_posterior_predictive( duration_fit, draws = 500, seed = 2033 ) ``` Exponentiating a population-level coefficient gives a conditional median duration ratio under the lognormal model. This ratio is not automatically a causal effect. The predictive check compares observed and replicated median, mean, upper-tail, dispersion, condition-ratio, and grouping summaries. Passing those summaries does not prove global model adequacy. ## Sensitivity, recovery, and reporting ```{r duration-sensitivity-recovery, eval=FALSE} duration_sensitivity <- assess_duration_prior_sensitivity( duration_fit, scale_multipliers = c( tighter = 0.5, wider = 2 ) ) duration_recovery <- run_duration_recovery( repetitions = 20, baseline_median = 500, outcome_unit = "milliseconds", seed = 4001 ) duration_report_file <- tempfile( pattern = "gp3bayes-duration-report-", fileext = ".md" ) duration_report <- create_duration_model_report( duration_fit, diagnostics = duration_diagnostics, posterior_summary = duration_posterior, posterior_predictive = duration_predictive, prior_sensitivity = duration_sensitivity, recovery = duration_recovery, file = duration_report_file ) duration_report unlink(duration_report_file) ``` Recovery results apply to the declared synthetic data-generating process. Reports preserve the distinction between successful fitting, numerical sampling diagnostics, predictive behavior, robustness checks, and substantive interpretation.