Nothing
## ----include=FALSE--------------------------------------
library(gsDesign)
## ----gssurvpower_quick_start----------------------------
design <- gsSurv(
k = 3, test.type = 4, alpha = 0.025, sided = 1, beta = 0.1,
sfu = sfHSD, sfupar = -4, sfl = sfHSD, sflpar = -2,
lambdaC = log(2) / 12, hr = 0.7, hr0 = 1,
eta = 0.01, gamma = 10, R = 16, minfup = 12, T = 28
)
pwr_design <- gsSurvPower(x = design, plannedCalendarTime = design$T)
pwr_design$power
## ----gssurvpower_at_design------------------------------
cat("Design power:", round((1 - design$beta) * 100, 1), "%\n")
cat("gsSurvPower: ", round(pwr_design$power * 100, 1), "%\n")
## ----gssurvpower_worse_hr-------------------------------
pwr_worse <- gsSurvPower(x = design, hr = 0.8, plannedCalendarTime = design$T)
cat("Power at HR = 0.8:", round(pwr_worse$power * 100, 1), "%\n")
## ----gssurvpower_sensitivity----------------------------
hr_grid <- seq(0.55, 0.90, by = 0.05)
power_vals <- sapply(hr_grid, function(h) {
p <- gsSurvPower(x = design, hr = h, plannedCalendarTime = design$T)
p$power
})
results <- data.frame(HR = hr_grid, Power = round(power_vals * 100, 1))
results
## ----timing_setup---------------------------------------
total_N <- floor(sum(design$gamma * design$R))
## ----timing_baseline------------------------------------
pwr_multi <- gsSurvPower(
x = design,
targetEvents = design$n.I,
plannedCalendarTime = design$T,
minN = c(NA, total_N, total_N),
minFollowUp = c(NA, 2, 12),
maxExtension = c(3, 12, 20)
)
data.frame(
Analysis = 1:design$k,
Planned_Time = round(design$T, 1),
Actual_Time = round(pwr_multi$T, 1),
Target_Events = round(design$n.I, 1),
Actual_Events = round(pwr_multi$n.I, 1)
)
cat("Power:", round(pwr_multi$power * 100, 1), "%\n")
## ----timing_slow_enrollment_simple----------------------
pwr_slow_simple <- gsSurvPower(
x = design,
gamma = design$gamma / 2,
targetN = total_N,
targetEvents = design$n.I
)
pwr_slow_simple |> gsBoundSummary()
## ----timing_slow_enrollment-----------------------------
pwr_slow <- gsSurvPower(
x = design,
gamma = design$gamma / 2,
targetEvents = design$n.I,
plannedCalendarTime = design$T,
minN = c(NA, total_N, total_N),
minFollowUp = c(NA, 2, 12),
maxExtension = c(3, 12, 20)
)
data.frame(
Analysis = 1:design$k,
Planned_Time = round(design$T, 1),
Actual_Time = round(pwr_slow$T, 1),
Target_Events = round(design$n.I, 1),
Actual_Events = round(pwr_slow$n.I, 1)
)
cat("Power:", round(pwr_slow$power * 100, 1), "%\n")
## ----timing_fast_failure--------------------------------
pwr_fast <- gsSurvPower(
x = design,
lambdaC = log(2) / 8,
targetEvents = design$n.I,
plannedCalendarTime = design$T,
minN = c(NA, total_N, total_N),
minFollowUp = c(NA, 2, 12),
maxExtension = c(3, 12, 20)
)
data.frame(
Analysis = 1:design$k,
Planned_Time = round(design$T, 1),
Actual_Time = round(pwr_fast$T, 1),
Target_Events = round(design$n.I, 1),
Actual_Events = round(pwr_fast$n.I, 1)
)
cat("Power:", round(pwr_fast$power * 100, 1), "%\n")
## ----informationRates_demo------------------------------
# Scenario 1 with informationRates and fullSpendingAtFinal
planned_info_rates <- c(design$timing[-design$k], 0.95)
pwr_slow_ir <- gsSurvPower(
x = design,
gamma = design$gamma / 2,
targetEvents = design$n.I,
plannedCalendarTime = design$T,
minN = c(NA, total_N, total_N),
minFollowUp = c(NA, 2, 12),
maxExtension = c(3, 12, 20),
informationRates = planned_info_rates,
fullSpendingAtFinal = TRUE
)
spending_frac_used <- pmin(planned_info_rates, pwr_slow_ir$timing)
spending_frac_used[design$k] <- 1
data.frame(
Analysis = 1:design$k,
Actual_Events = round(pwr_slow_ir$n.I, 1),
Actual_InfoFrac = round(pwr_slow_ir$timing, 3),
Planned_InfoFrac = round(planned_info_rates, 3),
Spending_Frac = round(spending_frac_used, 3)
)
cat("Power (default spending): ", round(pwr_slow$power * 100, 1), "%\n")
cat("Power (capped + full final): ", round(pwr_slow_ir$power * 100, 1), "%\n")
## ----gssurvpower_vs_gsdesign----------------------------
design_events <- design$n.I
hr_grid <- seq(0.55, 0.95, by = 0.05)
comparison <- data.frame(
HR = hr_grid,
gsDesign_plot = sapply(hr_grid, function(h) {
delta_ratio <- abs(log(h)) / abs(log(design$hr))
theta_h <- design$delta * delta_ratio
gsp <- gsDesign::gsProbability(
k = design$k, theta = theta_h,
n.I = design$n.I,
a = design$lower$bound, b = design$upper$bound, r = 18)
sum(gsp$upper$prob)
}),
fixed_events = sapply(hr_grid, function(h) {
gsSurvPower(x = design, hr = h, targetEvents = design_events)$power
}),
fixed_calendar = sapply(hr_grid, function(h) {
gsSurvPower(x = design, hr = h, plannedCalendarTime = design$T)$power
})
)
comparison[, -1] <- round(comparison[, -1] * 100, 2)
comparison
## ----gssurvpower_bounds---------------------------------
design_events <- design$n.I
cat("Design bounds (Z-scale):\n")
cat(" Efficacy:", round(design$upper$bound, 4), "\n")
cat(" Futility:", round(design$lower$bound, 4), "\n\n")
for (h in c(0.5, 0.7, 0.8, 1.0)) {
pwr <- gsSurvPower(x = design, hr = h, targetEvents = design_events)
cat(sprintf("HR=%.1f Efficacy: %s Futility: %s (identical: %s)\n",
h,
paste(round(pwr$upper$bound, 4), collapse = ", "),
paste(round(pwr$lower$bound, 4), collapse = ", "),
identical(pwr$upper$bound, design$upper$bound) &&
identical(pwr$lower$bound, design$lower$bound)))
}
## ----alpha_change---------------------------------------
# Design at one-sided alpha = 0.0125
design_a0125 <- gsSurv(
k = 3, test.type = 4, alpha = 0.0125, sided = 1, beta = 0.1,
sfu = sfHSD, sfupar = -4, sfl = sfHSD, sflpar = -2,
lambdaC = log(2) / 12, hr = 0.7, hr0 = 1,
eta = 0.01, gamma = 10, R = 16, minfup = 12, T = 28
)
cat("=== Original design (alpha = 0.0125) ===\n")
cat("Efficacy bounds:", round(design_a0125$upper$bound, 4), "\n")
cat("Futility bounds:", round(design_a0125$lower$bound, 4), "\n\n")
# Power at alpha = 0.025 with same event counts (timing preserved)
events_a0125 <- design_a0125$n.I
pwr_a025 <- gsSurvPower(x = design_a0125, alpha = 0.025, targetEvents = events_a0125)
cat("=== gsSurvPower at alpha = 0.025 ===\n")
cat("Efficacy bounds:", round(pwr_a025$upper$bound, 4), "\n")
cat("Futility bounds:", round(pwr_a025$lower$bound, 4), "\n")
cat("Power: ", round(pwr_a025$power * 100, 1), "%\n\n")
# Cross-check: gsBoundSummary at the same alternate alpha
# (only test.type 1, 4, 6, 7, 8 are supported)
cat("=== gsBoundSummary (alpha = 0.025) ===\n")
print(gsBoundSummary(design_a0125, alpha = 0.025))
## ----alpha_binding--------------------------------------
design3 <- gsSurv(
k = 3, test.type = 3, alpha = 0.0125, sided = 1, beta = 0.1,
sfu = sfHSD, sfupar = -4, sfl = sfHSD, sflpar = -2,
lambdaC = log(2) / 12, hr = 0.7, eta = 0.01,
gamma = 10, R = 16, minfup = 12, T = 28
)
events3 <- design3$n.I
pwr3_a025 <- gsSurvPower(x = design3, alpha = 0.025, targetEvents = events3)
cat("=== Binding futility (test.type=3) at alpha = 0.025 ===\n")
cat("Original efficacy:", round(design3$upper$bound, 4), "\n")
cat("New efficacy: ", round(pwr3_a025$upper$bound, 4), "\n")
cat("Original futility:", round(design3$lower$bound, 4), "\n")
cat("New futility: ", round(pwr3_a025$lower$bound, 4), "\n")
cat("Power: ", round(pwr3_a025$power * 100, 1), "%\n")
## ----alpha_output_fields--------------------------------
cat("test.type:", pwr3_a025$test.type, "(same as input design)\n")
cat("alpha: ", pwr3_a025$alpha, "(updated to new value)\n")
## ----gssurvpower_events---------------------------------
pwr_events <- gsSurvPower(
x = design,
targetEvents = c(75, 150, 225)
)
cat("Analysis times:", round(pwr_events$T, 1), "\n")
cat("Events at each analysis:",
round(pwr_events$n.I, 1), "\n")
cat("Power:", round(pwr_events$power * 100, 1), "%\n")
## ----gssurvpower_slower_enrollment----------------------
pwr_slow_enroll <- gsSurvPower(
x = design,
gamma = design$gamma / 2,
plannedCalendarTime = design$T
)
cat("Original final expected events:", round(pwr_design$n.I[design$k], 1), "\n")
cat("Slower-enrollment final events:", round(pwr_slow_enroll$n.I[design$k], 1), "\n")
cat("Original power:", round(pwr_design$power * 100, 1), "%\n")
cat("Slower-enrollment power:", round(pwr_slow_enroll$power * 100, 1), "%\n")
## ----calendar_spending----------------------------------
# Information-based spending (default)
pwr_info <- gsSurvPower(
x = design,
plannedCalendarTime = design$T,
spending = "information"
)
# Calendar-based spending
pwr_cal <- gsSurvPower(
x = design,
plannedCalendarTime = design$T,
spending = "calendar"
)
# Compare spending fractions and bounds
data.frame(
Analysis = 1:design$k,
Calendar_Time = round(pwr_info$T, 1),
InfoFraction = round(pwr_info$timing, 3),
CalendarFraction = round(pwr_cal$T / max(pwr_cal$T), 3),
Bound_Info = round(pwr_info$upper$bound, 4),
Bound_Calendar = round(pwr_cal$upper$bound, 4)
)
## ----calendar_ignores_usTime----------------------------
pwr_cal_override <- gsSurvPower(
x = design,
plannedCalendarTime = design$T,
spending = "calendar",
usTime = c(0.2, 0.6, 1),
lsTime = c(0.3, 0.8, 1)
)
# Bounds are identical regardless of usTime/lsTime
identical(pwr_cal$upper$bound, pwr_cal_override$upper$bound)
## ----stratified_events----------------------------------
# Per-stratum event targets: rows = analyses, columns = strata
event_matrix <- matrix(
c(20, 10, # interim: 20 from stratum 1, 10 from stratum 2
40, 20), # final: 40 from stratum 1, 20 from stratum 2
nrow = 2, byrow = TRUE
)
pwr_strat <- gsSurvPower(
k = 2, test.type = 1, alpha = 0.025, sided = 1,
lambdaC = matrix(log(2) / c(6, 12), ncol = 2),
hr = 0.7, eta = 0.01,
gamma = matrix(c(5, 5), ncol = 2), R = 12, ratio = 1,
targetEvents = event_matrix
)
# The analysis times are solved so that total expected events
# match the row sums of the target matrix
data.frame(
Analysis = 1:2,
Target_Stratum1 = event_matrix[, 1],
Target_Stratum2 = event_matrix[, 2],
Target_Total = rowSums(event_matrix),
Expected_Events = round(pwr_strat$n.I, 1),
Calendar_Time = round(pwr_strat$T, 1)
)
cat("Power:", round(pwr_strat$power * 100, 1), "%\n")
## ----biomarker_design-----------------------------------
prevalence <- 0.6
median_bm_pos <- 12 # control median in biomarker+ (months)
median_bm_neg <- 10 # control median in biomarker- (shorter prognosis)
bm_design <- gsSurvCalendar(
test.type = 4, alpha = 0.0125, beta = 0.1,
sfu = sfHSD, sfupar = -4, sfl = sfHSD, sflpar = -2,
calendarTime = c(12, 24, 36),
lambdaC = log(2) / median_bm_pos, hr = 0.65, eta = 0.01,
gamma = 10, R = 18, minfup = 18, ratio = 1
)
summary(bm_design)
gsBoundSummary(bm_design)
## ----stratified_power-----------------------------------
# Control hazard rates by stratum
lambdaC_pos <- log(2) / median_bm_pos
lambdaC_neg <- log(2) / median_bm_neg
# Enrollment rates by stratum (proportionate to prevalence)
gamma_pos <- bm_design$gamma
gamma_neg <- bm_design$gamma * (1 - prevalence) / prevalence
# Stratified inputs: matrix with columns = strata
lambdaC_strat <- matrix(c(lambdaC_pos, lambdaC_neg), ncol = 2)
gamma_strat <- matrix(c(gamma_pos, gamma_neg), ncol = 2)
pwr_overall <- gsSurvPower(
k = 3, test.type = 4, alpha = 0.0125, sided = 1,
sfu = sfHSD, sfupar = -4, sfl = sfHSD, sflpar = -2,
lambdaC = lambdaC_strat, hr = 0.75, eta = 0.01,
gamma = gamma_strat, R = 18, ratio = 1,
plannedCalendarTime = c(12, 24, 36)
)
summary(pwr_overall)
gsBoundSummary(pwr_overall)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.