D56: limb MALE (CLTI, major amputation, open bypass) as primary outcome; MALE incl. repeat revascularization to supplement

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-28 16:39:59 -04:00
co-authored by Claude Opus 5.5
parent d369a16208
commit 3aa6c1c5b3
12 changed files with 37 additions and 33 deletions
+2 -2
View File
@@ -174,14 +174,14 @@ restrict_variant <- function(rec, variant) {
#' Run one design under one physician variant for several outcomes.
#' Returns one row per outcome (and contrast), with the SE that the variant reports:
#' patient-level for V1, physician-cluster-robust for V2-V4.
run_design <- function(rec, design, variant, outcomes = c(male = "t_male", disease = "t_disease",
run_design <- function(rec, design, variant, outcomes = c(limb = "t_limb", male = "t_male", disease = "t_disease",
nco1 = "t_nco1", nco2 = "t_nco2")) {
run_designs(rec, design, variant, outcomes)
}
#' Several designs under one variant, sharing the PVI fit between CCW and sequential
#' trials (the sequential propensity score is the window part of the same model).
run_designs <- function(rec, designs, variant, outcomes = c(male = "t_male", disease = "t_disease",
run_designs <- function(rec, designs, variant, outcomes = c(limb = "t_limb", male = "t_male", disease = "t_disease",
nco1 = "t_nco1", nco2 = "t_nco2")) {
rec <- restrict_variant(rec, variant)
need <- intersect(designs, c("ccw", "seq"))
+1 -1
View File
@@ -18,7 +18,7 @@ oracle_records <- function(rec) {
}
#' Oracle versions of the landmark (both versions) and naive designs (V1, patient-level SE).
run_oracle <- function(rec, outcomes = c(male = "t_male", disease = "t_disease", nco1 = "t_nco1", nco2 = "t_nco2")) {
run_oracle <- function(rec, outcomes = c(limb = "t_limb", male = "t_male", disease = "t_disease", nco1 = "t_nco1", nco2 = "t_nco2")) {
o <- oracle_records(rec)
rbindlist(lapply(names(outcomes), function(nm) {
lm <- est_landmark(o, outcomes[[nm]], "V1_ignore", extra_covs = o$extra_covs)
+1 -1
View File
@@ -60,7 +60,7 @@ trial_policy <- function(trial, assign = NULL) {
#' Run one simulated trial and analyse it: ITT (by assignment, unadjusted) and naive
#' as-treated (PVI in the window vs not, ignoring assignment).
run_rct <- function(par, design = "realistic", rep = 1L, outcomes = c(male = "t_male", disease = "t_disease"),
run_rct <- function(par, design = "realistic", rep = 1L, outcomes = c(limb = "t_limb", male = "t_male", disease = "t_disease"),
source_n = 60000L) {
seed <- replicate_seed(par$world, paste0(par$scenario, "|rct|", design), rep)
pop <- make_population(par, n = source_n, seed = seed)
+4 -1
View File
@@ -217,8 +217,11 @@ simulate_course <- function(pop, par, pol = policy("natural"), seed = 1L, record
# disease composite (D34): coded CLTI or major amputation
t_disease <- pmin(t_clti_code, t_amp, na.rm = TRUE)
# limb MALE (primary, D56): coded CLTI, major amputation or open bypass. Every component
# can occur with or without a prior PVI; repeat revascularization is reported separately
t_limb <- pmin(t_clti_code, t_amp, t_bypass, na.rm = TRUE)
out <- data.table(id = pat$id, t_pvi, pvi_elective, t_clti_true, t_clti_code, t_amp, t_bypass,
t_rr, t_male, t_disease, t_death, t_nco1, t_nco2, t_nce, n_proc)
t_rr, t_male, t_disease, t_limb, t_death, t_nco1, t_nco2, t_nce, n_proc)
list(events = out, z = zmat, counts = cmat, policy = pol)
}
+2 -2
View File
@@ -9,7 +9,7 @@
# Landmark, naive and RCT estimands are not interventional in this sense; they are added
# with the estimators (oracle large-sample limits).
OUTCOMES <- c(male = "t_male", disease = "t_disease", clti = "t_clti_code", amp = "t_amp",
OUTCOMES <- c(limb = "t_limb", male = "t_male", disease = "t_disease", clti = "t_clti_code", amp = "t_amp",
bypass = "t_bypass", rr = "t_rr", death = "t_death", nco1 = "t_nco1", nco2 = "t_nco2")
truth_population <- function(par, n, seed) {
@@ -83,7 +83,7 @@ compute_truths <- function(world, scenario, n = 1e6, seed = 20261027L, horizon =
value = rd, mcse = sqrt(var / n_elig), n = n_elig)]
}
curves <- rbindlist(lapply(names(ev), function(p) rbindlist(lapply(c("male", "disease"), function(o)
curves <- rbindlist(lapply(names(ev), function(p) rbindlist(lapply(c("limb", "male", "disease"), function(o)
data.table(world = world, scenario = scenario, policy = p, outcome = o, month = seq_len(horizon),
cuminc = vapply(seq_len(horizon), function(h) mean(by_h(ev[[p]][[OUTCOMES[[o]]]], h)), 0))))))
if (verbose) message(sprintf("%s/%s: %.1f min", world, scenario,
+1 -1
View File
@@ -20,7 +20,7 @@ test_that("under the sharp null, disease, death and negative controls are identi
policy("seq_force", 3L)),
function(p) simulate_course(sw$pop, sw$par, p, seed = 5L, record = FALSE)$events)
for (r in runs[-1]) {
for (col in c("t_disease", "t_clti_code", "t_amp", "t_death", "t_nco1", "t_nco2", "t_nce")) {
for (col in c("t_limb", "t_disease", "t_clti_code", "t_amp", "t_bypass", "t_death", "t_nco1", "t_nco2", "t_nce")) {
expect_identical(r[[col]], runs[[1]][[col]], info = col)
}
}