Skip to contents

Overview

We consider a delayed effect scenario where

  • The control group time-to-event distribution is exponential with a median of 15 months.
  • The experimental group has a hazard ratio vs. control of 1 for 6 months and 0.6 thereafter.
  • Enrollment at a constant rate for 12 months.
  • Total study duration from 20 to 48 months.
  • Exponential dropout rate of 0.001 per month.
enroll_rate <- define_enroll_rate(duration = 12, rate = 1)
fail_rate <- define_fail_rate(
  duration = c(6, 100),
  fail_rate = log(2) / 15,
  hr = c(1, .6),
  dropout_rate = 0.001
)

enroll_rate |>
  lt() |>
  lt_header(title = "Enrollment Table of Scenario 1")
fail_rate |>
  lt() |>
  lt_header(title = "Failure Table of Scenario 1")

For the above scenarios, we investigate the power, sample size and events under 6 tests:

  • fh_05: The Fleming-Harrington with \(\rho=0, \gamma=0.5\) test to obtain power of 85% given 1-sided Type I error of 0.025.
  • fh_00: The regular logrank test with \(\rho=0, \gamma=0\) under fixed study duration \(\in\{20, 24, 28, \ldots, 60\}\).
  • mc2_test: The MaxCombo test including 2 WLR tests, i.e., \(\{(\rho=0, \gamma=0, \tau = -1), (\rho=0, \gamma=0.5, \tau = -1)\}\).
  • mc2_test: The MaxCombo test including 3 WLR tests, i.e., \(\{(\rho=0, \gamma=0, \tau = -1), (\rho=0, \gamma=0.5, \tau = -1), (\rho=0.5, \gamma=0.5, \tau = -1)\}\).
  • mc4_test: The MaxCombo test including 4 WLR tests, i.e., \(\{(\rho=0, \gamma=0, \tau = -1), (\rho=0, \gamma=0.5, \tau = -1), (\rho=0.5, \gamma=0.5, \tau = -1), (\rho=0.5, \gamma=0, \tau = -1)\}\).
  • mb_6: The Magirr-Burman with \(\rho=-1, \gamma=0, \tau = 6\) test with fixed study duration \(\in\{20, 24, 28, \ldots, 60\}\).

We then compute power for the logrank test. The general summary is that the Fleming-Harrington test has a meaningful power gain relative to logrank regardless of the study durations evaluated.

tab <- NULL

for (trial_duration in seq(24, 60, 4)) {
  # Fleming-Harrington rho=0, gamma=0.5 test
  fh_05 <- gs_design_wlr(
    enroll_rate = enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    alpha = 0.025, beta = 0.15,
    weight = list(method = "fh", param = list(rho = 0, gamma = 0.5)),
    upper = gs_b,
    lower = gs_b,
    upar = qnorm(.975),
    lpar = -Inf,
    analysis_time = trial_duration
  ) |> to_integer()

  # Regular logrank test
  fh_00 <- gs_power_wlr(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    weight = list(method = "fh", param = list(rho = 0, gamma = 0)),
    upper = gs_b,
    lower = gs_b,
    upar = qnorm(.975),
    lpar = -Inf,
    analysis_time = trial_duration,
    event = .1
  )

  # MaxCombo test 1
  mc2_test <- data.frame(
    rho = 0, gamma = c(0, .5), tau = -1,
    test = 1:2, analysis = 1, analysis_time = trial_duration
  )

  mc_2 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    fh_test = mc2_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # MaxCombo test 2
  mc3_test <- data.frame(
    rho = c(0, 0, .5), gamma = c(0, .5, .5), tau = -1,
    test = 1:3, analysis = 1, analysis_time = trial_duration
  )

  mc_3 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    fh_test = mc3_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # MaxCombo test
  mc4_test <- data.frame(
    rho = c(0, 0, .5, .5), gamma = c(0, .5, .5, 0), tau = -1,
    test = 1:4, analysis = 1, analysis_time = trial_duration
  )

  mc_4 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    fh_test = mc4_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # Magirr-Burman rho=-1, gamma=0, tau = 6 test
  mb_6 <- gs_power_wlr(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    weight = list(method = "fh", param = list(rho = -1, gamma = 0, tau = 15)),
    upper = gs_b,
    lower = gs_b,
    upar = qnorm(.975),
    lpar = -Inf,
    analysis_time = trial_duration,
    event = .1
  )

  tab_new <- tibble(
    `Study duration` = trial_duration,
    N = fh_05$analysis$n[1],
    Events = fh_05$analysi$event[1],
    `Events/N` = Events / N,
    # We use the AHR from regular WLR as the AHR of different MaxCombo test
    AHR = as.numeric(fh_00$analysis$ahr[1]),
    `FH(0, 0.5) power` = fh_05$bound$probability[1],
    `FH(0, 0) power` = fh_00$bound$probability[1],
    `MC2 power` = mc_2$bound$probability[1],
    `MC4 power` = mc_4$bound$probability[1],
    `MC3 power` = mc_3$bound$probability[1],
    `MB6 power` = mb_6$bound$probability[1]
  )
  tab <- rbind(tab, tab_new)
}

tab |>
  lt() |>
  lt_format(columns = c(2, 3), decimals = 1) |>
  lt_format(columns = 4, decimals = 2) |>
  lt_format(columns = 5, decimals = 4) |>
  lt_format(columns = 6:11, decimals = 2)

An Alternative Scenario

Now we consider an alternate scenario where the placebo group starts with the same median, but then has a piecewise change to a median of 30 after 16 months and with a hazard ratio of 0.85 during that late period.

enroll_rate <- define_enroll_rate(duration = 12, rate = 1)
fail_rate <- define_fail_rate(
  duration = c(6, 10, 100),
  # In Scenario 1: fail_rate = log(2) / 15,
  fail_rate = log(2) / c(15, 15, 30),
  dropout_rate = 0.001,
  # In Scenario 1: hr = c(1, .6)
  hr = c(1, .6, .85)
)
enroll_rate |>
  lt() |>
  lt_header(title = "Enrollment Table of Scenario 2")
fail_rate |>
  lt() |>
  lt_header(title = "Failure Table of Scenario 2")
tab <- NULL

for (trial_duration in seq(20, 60, 4)) {
  # Fleming-Harrington rho=0, gamma=0.5 test
  fh_05 <- gs_design_wlr(
    enroll_rate = enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    alpha = 0.025, beta = 0.15,
    weight = list(method = "fh", param = list(rho = 0, gamma = 0.5)),
    upper = gs_b,
    upar = qnorm(.975),
    lower = gs_b,
    lpar = -Inf,
    analysis_time = trial_duration
  ) |> to_integer()

  # Regular logrank test
  fh_00 <- gs_power_wlr(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    weight = "logrank",
    upper = gs_b,
    upar = qnorm(.975),
    lower = gs_b,
    lpar = -Inf,
    analysis_time = trial_duration,
    event = .1
  )

  # MaxCombo test
  mc2_test <- data.frame(
    rho = 0, gamma = c(0, .5), tau = -1,
    test = 1:2, analysis = 1, analysis_time = trial_duration
  )
  mc_2 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    fh_test = mc2_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # MaxCombo test
  mc3_test <- data.frame(
    rho = c(0, 0, .5), gamma = c(0, .5, .5), tau = -1,
    test = 1:3, analysis = 1, analysis_time = trial_duration
  )

  mc_3 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    fh_test = mc3_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # MaxCombo test
  mc4_test <- data.frame(
    rho = c(0, 0, .5, .5), gamma = c(0, .5, .5, 0), tau = -1,
    test = 1:4, analysis = 1, analysis_time = trial_duration
  )

  mc_4 <- gs_power_combo(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate, fh_test = mc4_test,
    upper = gs_spending_combo,
    upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
    lower = gs_spending_combo,
    lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.01)
  )

  # Magirr-Burman rho=-1, gamma=0, tau = 6 test
  mb_6 <- gs_power_wlr(
    enroll_rate = fh_05$enroll_rate,
    fail_rate = fail_rate,
    ratio = 1,
    weight = list(method = "fh", param = list(rho = -1, gamma = 0, tau = 15)),
    upper = gs_b,
    lower = gs_b,
    upar = qnorm(.975),
    lpar = -Inf,
    analysis_time = trial_duration,
    event = .1
  )

  tab_new <- tibble(
    `Study duration` = trial_duration,
    N = fh_05$analysis$n[1],
    Events = fh_05$analysi$event[1],
    `Events/N` = Events / N,
    # We use the AHR from regular WLR as the AHR of different MaxCombo test
    AHR = as.numeric(fh_00$analysis$ahr[1]),
    `FH(0, 0.5) power` = fh_05$bound$probability[1],
    `FH(0, 0) power` = fh_00$bound$probability[1],
    `MC2 power` = mc_2$bound$probability[1],
    `MC4 power` = mc_4$bound$probability[1],
    `MC3 power` = mc_3$bound$probability[1],
    `MB6 power` = mb_6$bound$probability[1]
  )

  tab <- rbind(tab, tab_new)
}

tab |>
  lt() |>
  lt_format(columns = c(2, 3), decimals = 1) |>
  lt_format(columns = 4, decimals = 2) |>
  lt_format(columns = 5, decimals = 4) |>
  lt_format(columns = 6:11, decimals = 2)