Trial-level functional random effects¶
Version 0.48 extends the Gaussian functional mixed-effects layer from a participant-only covariance hierarchy to an explicitly nested participant → trial → time model.
For participant \(i\), trial \(j\), and observed time \(t\),
The participant functional effect remains
The new trial functional intercept is
\(\boldsymbol\Psi_{\mathrm{trial}}\) is one shared unstructured covariance across trials. The implementation does not estimate one covariance per trial and does not replace the functional covariance with an independent scalar variance component.
Marginal covariance¶
For all observations from participant \(i\),
Participant and trial covariance matrices are parameterized through their Cholesky factors. Fixed B-spline coefficients are profiled by generalized least squares for every covariance-parameter evaluation.
The historical participant-only model continues to use the established
statsmodels.MixedLM backend. The nested backend is activated only when the
trial effect is explicitly requested.
Explicit API¶
fit = fit_functional_mixed_effects_regression(
trajectories,
design,
predictors=("condition",),
participant_column="participant_id",
trial_column="trial_id",
trial_random_effect="functional_intercept",
dimension="metric",
fixed_basis_size=4,
random_basis_size=3,
trial_random_basis_size=3,
spline_degree=2,
)
There is no Boolean shorthand. The explicit string leaves the public contract open to future trial structures without silently changing today's semantics.
Trial identity¶
Version 0.48 treats one trajectory as one observed trial. The trial_column
therefore provides the scientific trial label attached to each curve.
Trial labels need only be unique within participant. Reused labels such as
T01 across different participants are valid. Internally the nested identity
is the participant/trial pair.
The model fails closed when:
trial_columnis absent or contains missing values;- a participant/trial pair appears more than once;
- any participant contributes fewer than two observed trials;
- the trial basis is rank deficient on the observed grid;
- the number of observed nested trials does not exceed \(q_u(q_u+1)/2\), the number of free parameters in the unstructured \(q_u\times q_u\) trial covariance;
- optimization fails to converge.
The trial-count rule is a minimum covariance-complexity guard, not a theorem that the covariance is estimated precisely.
Covariance diagnostics¶
The result retains:
trial_random_effect_covariance;- covariance eigenvalues;
- condition number;
- free covariance-parameter count;
- boundary and singularity flags;
- trial B-spline basis and knots;
- trial BLUP coefficients;
- reconstructed trial random functions;
- source and composite trial identifiers.
A boundary estimate is retained. The package does not automatically delete the trial effect or refit a simpler model.
Inspect the trial effects¶
from eyetrajectoriespy import (
functional_trial_random_effect_frame,
plot_functional_trial_random_effects,
)
trial_effects = functional_trial_random_effect_frame(fit)
plot_functional_trial_random_effects(
fit,
participant_id=fit.participant_ids[0],
)
These are conditional BLUPs under the fitted covariance model. They should not be interpreted as independently estimated trial trajectories.
Residual diagnostics after the extension¶
The 0.47 diagnostic API can be applied directly to a 0.48 fit:
from eyetrajectoriespy import (
functional_mixed_effects_residual_diagnostics,
)
post_trial_diagnostics = functional_mixed_effects_residual_diagnostics(
fit,
max_lag=6,
)
The relevant scientific question is whether smooth residual dependence that was present under the participant-only model is reduced after accounting for the trial-specific smooth process. A residual ACF or variogram is diagnostic evidence, not an automatic covariance selector.
Bootstrap inference¶
Both existing participant-level bootstrap contracts remain participant-level.
The fixed-covariance bootstrap resamples whole participants and carries all their trials. It re-estimates fixed coefficients by GLS while conditioning on:
- \(\widehat{\boldsymbol\Psi}_{\mathrm{participant}}\);
- \(\widehat{\boldsymbol\Psi}_{\mathrm{trial}}\);
- \(\widehat{\sigma}^2\);
- the declared bases and model structure.
The full-refit bootstrap also resamples whole participants. Every sampled participant occurrence receives a new bootstrap participant identity, and every nested source trial receives a new bootstrap trial identity. Each replicate refits both covariance matrices and residual variance.
from eyetrajectoriespy import (
bootstrap_functional_mixed_effects_full_refit,
functional_mixed_effects_full_refit_trial_audit_frame,
)
boot = bootstrap_functional_mixed_effects_full_refit(
fit,
n_bootstrap=1000,
random_state=48,
)
audit = functional_mixed_effects_full_refit_trial_audit_frame(boot)
Trials are not independently resampled in this inferential contract.
Interpretation boundary¶
A smooth trial functional random effect and serial residual correlation are different covariance mechanisms. Version 0.48 addresses the former only.
Short-range dependence remaining after conditioning on participant and trial functional effects is a candidate motivation for the planned 0.49 explicit residual covariance layer. The package does not infer that conclusion automatically.