The sensitivity layer records alternative analysis states without selecting the scenario that produces the largest effect.
sim <- simulate_pupil_timecourse(
n_participants = 5,
trials_per_participant = 4,
sampling_frequency = 20,
time_window = c(-0.6, 1.4),
include_gaze = TRUE,
include_luminance = TRUE,
seed = 73
)
contract <- create_pupil_contract(
outcome_col = "pupil_mm",
participant_col = "participant_id",
trial_col = "trial_id",
condition_col = "condition",
time_col = "event_time",
pupil_unit = "millimetres",
sampling_frequency = 20,
blink_col = "blink",
interpolation_col = "interpolated",
gaze_x_col = "gaze_x",
gaze_y_col = "gaze_y",
luminance_col = "luminance",
baseline_window = c(-0.6, 0),
pfe_corrected = FALSE
)
prepared <- prepare_pupil_timecourse(sim$data, contract)
spec_for_sensitivity <- specify_pupil_timecourse_model(
prepared,
autocorrelation = "none",
smooth_basis_dimension = 5
)
suite <- create_pupil_sensitivity_suite(
spec_for_sensitivity,
baseline_windows = list(c(-0.6, -0.1), c(-0.4, -0.1)),
baseline_window_operation = "subtract",
baseline_operations = c("none", "subtract"),
interpolation_policy = c("retain", "exclude_flagged"),
gaze_adjustment = c("none", "declared_covariates"),
luminance_adjustment = c("none", "declared_covariate"),
smooth_basis_dimensions = c(5, 7),
autocorrelation = c("none", "ar1"),
analysis_windows = list(c(0.2, 1.0))
)
pupil_sensitivity_table(suite)
#> scenario_id axis value
#> 1 S001 baseline_window -0.6,-0.1
#> 2 S002 baseline_window -0.4,-0.1
#> 3 S003 baseline_operation none
#> 4 S004 baseline_operation subtract
#> 5 S005 interpolation_policy retain
#> 6 S006 interpolation_policy exclude_flagged
#> 7 S007 gaze_adjustment none
#> 8 S008 gaze_adjustment declared_covariates
#> 9 S009 luminance_adjustment none
#> 10 S010 luminance_adjustment declared_covariate
#> 11 S011 smooth_basis_dimension 5
#> 12 S012 smooth_basis_dimension 7
#> 13 S013 autocorrelation none
#> 14 S014 autocorrelation ar1
#> 15 S015 analysis_window 0.2,1scenario_id <- pupil_sensitivity_table(suite)$scenario_id[1]
scenario <- materialize_pupil_sensitivity_scenario(suite, scenario_id)
scenario$scenario_id
#> [1] "S001"
scenario$specification
#> <gp3bayes_pupil_model_specification>
#> Family: Gaussian pupil time-course
#> Formula: .pupil_model ~ .condition + s(.event_time, by = .condition, k = 5) + (1 | .participant)
#> Temporal structure: smooth
#> Condition trajectory: TRUE
#> Autocorrelation: none
#> Outcome unit: millimetres
#> Baseline: subtract
#> Unrestricted formula: FALSE
#> Fit performed: FALSEEach scenario can be fitted and reduced to the same declared
estimand. compare_pupil_sensitivity_estimands() then places
those estimands side by side. It does not identify a winner.
PFE and luminance are handled as measurement-context variables. The 0.4 foundation can audit them and compare explicitly declared adjusted/unadjusted specifications, but it does not invent a universal PFE correction or a Bayesian Open-DPSM replacement.