Censored gaze-latency survival analysis¶
-
:material-timer-sand: Keep never-inspected trials
A valid trial that ends before the target AOI is inspected remains informative as a right-censored observation. It is not dropped and it is not assigned a latency of zero.
-
:material-account-check: Separate censoring from unusable gaze
Missing or incomplete gaze produces an explicit review state.
eyeprocesspydoes not infer ordinary censoring merely from a missing event time. -
:material-account-multiple: Respect repeated participants
Python exposes participant-clustered Cox uncertainty. The R package additionally exposes latent participant frailty through the specialist
coxmeengine. -
:material-source-branch: Audit specification sensitivity
AOI geometry, event detector, time origin, fixation threshold, quality rule, and model family remain explicit analysis branches with preserved provenance.
How to read the visual outputs¶
The 1−KM panel is appropriate for this single-event example only. When event types compete, use a dedicated competing-risks framework rather than relabelling 1−KM as a competing-risks cumulative-incidence estimator.
When to use it¶
Use this pathway when the outcome is genuinely time to an event: first fixation, first AOI entry, first evidence inspection, first revisit, first transition into a target AOI, or a substantively defined disengagement latency. It is especially important when a non-trivial number of trials end before that event occurs.
A typical workflow is:
canonical trials + fixation/AOI-visit events
→ define target event and time origin
→ construct event/censoring rows
→ validate observation windows and quality
→ Kaplan–Meier description
→ explicitly requested Cox and/or AFT model
→ repeated-participant treatment
→ diagnostics
→ specification sensitivity
→ manuscript-ready report
When not to use it¶
Do not use this workflow when event status cannot be determined, the observation window is unknown, competing event types require a competing-risks estimand, or the scientific question concerns the full continuous gaze trajectory rather than event latency. Informative trial termination also requires substantive sensitivity analysis; ordinary right censoring is not automatically justified simply because the recording ended.
Model choices¶
| Question | Model | Primary interpretation |
|---|---|---|
| What proportion remains uninspected over time? | Kaplan–Meier | Survival probability |
| How do covariates change the instantaneous event rate? | Cox PH | Hazard ratio |
| How do covariates multiply event time? | Weibull/log-normal AFT | Time ratio |
| How do I account for repeated trials in Python? | Clustered Cox | Marginal HR with cluster-robust SE |
| How do I estimate latent participant frailty in R? | coxme mixed Cox |
Conditional HR with random participant effect |
Cox and AFT estimates answer different questions. The package therefore summarizes them side by side but does not declare a winner. Cox partial-likelihood and AFT full-likelihood AIC/BIC are marked as non-comparable across families.
Backend map¶
| Scientific task | Python backend | R backend | Contract note |
|---|---|---|---|
| Cox PH | statsmodels.PHReg |
survival::coxph |
Semantic parity; backend diagnostics can differ numerically |
| Repeated-trial marginal Cox | PHReg.fit(groups=...) |
coxph(..., cluster=...) |
Participant dependence is handled without pretending to be frailty |
| Participant frailty Cox | Not currently exposed; request fails | coxme::coxme |
No silent substitution in Python |
| Weibull AFT | lifelines.WeibullAFTFitter |
survival::survreg(dist = "weibull") |
Time-ratio estimand aligned; parameterization may differ |
| Log-normal AFT | lifelines.LogNormalAFTFitter |
survival::survreg(dist = "lognormal") |
Time-ratio estimand aligned; parameterization may differ |
Install the modelling backends¶
The extra installs the tested statsmodels, lifelines, Patsy, and plotting dependencies used by the modelling and diagnostic examples.