Empowering clinical trial design with simulations
2026-03-05
TrialSimulatorrpact of fixed designA function generating trial data of
A function analyzing trial data of
A long list of parameters
A function
gsDesign, rpact, etc.TrialSimulatorMilestones in a fixed design
Make it a group sequential design
Add a futility
Make it a seamless design, even with dose selection
final_action <- function(trial){
locked_data <- trial$get_locked_data('final') # name of milestone
# do whatever analysis
# trial$save(value, name)
}
final <- milestone(name = 'final', # to request for data cut
when = enrollment(n = 1000) &
eventNumber(endpoint = 'os', n = 300) & (
calendarTime(time = 28) |
eventNumber(endpoint = 'pfs', n = 520)
),
action = final_action
)EOPh2 <- milestone(
name = 'End of Ph2', # to request for data cut
when = eventNumber(endpoint = 'orr', n = 200),
action = EOPh2_action # defined by user
)
futility <- milestones(
name = 'Fu',
when = calendarTime(time = 8),
action = fu_action
)
IAPh3 <- milestone(
name = 'IA of Ph3',
when = eventNumber(endpoint = 'pfs', n = 250)
)EOPh2_action <- function(trial){
# request for data access using milestone name
locked_data <- trial$get_locked_data('End of Ph2')
# do planned analysis
if(condition1_is_met){
trial$remove_arms('high dose')
trial$save(value = 'low', name = 'kept_arm')
}else if(condition2_is_met){
trial$remove_arms('low dose')
trial$save(value = 'high', name = 'kept_arm')
}else{
trial$save(value = 'both', name = 'kept_arm')
}
# do something else
}pfs <- endpoint(
name = 'pfs', type = 'tte',
generator = rexp, rate = log(2) / 5)
os <- endpoint(
name = 'os', type = 'tte',
generator = rexp, rate = log(2) / 14)
surrogate <- endpoint(
name = 'surrogate', type = 'non-tte',
readout = c(surrogate = 1),
generator = rbinom, size = 1, prob = .05)
pbo <- arm(name = 'placebo')
# collect endpoints in arm
pbo$add_endpoints(pfs, os, surrogate)
# print summary of arm
pboaccrual_rate <- data.frame(end_time = c(10, Inf),
piecewise_rate = c(30, 50))
trial <- trial(
name = 'Trial-3415',
n_patients = 1000,
duration = 40,
enroller = StaggeredRecruiter, accrual_rate = accrual_rate,
dropout = rweibull, shape = 2.139, scale = 38.343
)
trial$add_arms(sample_ratio = c(1, 1, 1), low, high, pbo)