## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ---- message=FALSE, warning=FALSE--------------------------------------------
library(npsurvSS)
library(dplyr)
library(tidyr)
library(tibble)
library(ggplot2)

## -----------------------------------------------------------------------------
fun_hr <- function(HR, k, range.min, range.max) {
  (HR-0.3) / (0.9-0.3) * exp(k*(HR-0.3)) / exp(k*(0.9-0.3)) * (range.max-range.min) + range.min
}

## ---- fig.show='hold'---------------------------------------------------------
HR.vec <- seq(0.3, 0.9, 0.01)
plot(HR.vec, fun_hr(HR=HR.vec, k=5, range.min=0.6, range.max=0.7),
     xlab="Hazard ratio",
     ylab="d/n ratio",
     type="l")
plot(HR.vec, fun_hr(HR=HR.vec, k=0, range.min=6, range.max=24),
     xlab="Hazard ratio",
     ylab="Control median survival (months)",
     type="l")
plot(HR.vec, fun_hr(HR=HR.vec, k=2.3, range.min=12, range.max=48),
     xlab="Hazard ratio",
     ylab="Accrual duration (months)",
     type="l")

## ---- fig.width=5-------------------------------------------------------------
p1.vec <- seq(0.5, 0.7, 0.05)
optimal <- tibble(
  p1 = rep(p1.vec, each=length(HR.vec)),
  HR = rep(HR.vec, length(p1.vec)),
  accr_time = fun_hr(HR=HR, k=2.3, range.min=12, range.max=48),
  d = (qnorm(0.975)+qnorm(0.9))^2/0.5/0.5/log(HR)^2, # schoenfeld 1981
  n = d / fun_hr(HR, k=5, range.min=0.6, range.max=0.7),
  m = fun_hr(HR=HR, k=0, range.min=6, range.max=24),
  total_time = 0,
  power=0,
  events0=0,
  events1=0
)

## -----------------------------------------------------------------------------
R   <- dim(optimal)[1]
for (r in 1:R) {
  
  # scenario specific parameters
  p1        <- optimal$p1[r]
  HR        <- optimal$HR[r]
  accr_time <- optimal$accr_time[r]
  d         <- optimal$d[r]
  n         <- optimal$n[r]
  m         <- optimal$m[r]
  
  # create arm objects
  arm0 <- create_arm(size=n*(1-p1),
                     accr_time=accr_time,
                     accr_interval=accr_time*c(0,0.25,0.5,1), # piecewise-uniform accrual
                     accr_param=c(0.05,0.25,0.7),
                     surv_scale=per2haz(m),
                     loss_scale=per2haz(m)*0.05,
                     follow_time=12)
  arm1 <- create_arm(size=n*p1,
                     accr_time=accr_time,
                     accr_interval=accr_time*c(0,0.25,0.5,1),
                     accr_param=c(0.05,0.25,0.7),
                     surv_scale=per2haz(m/HR),
                     loss_scale=arm0$loss_scale,
                     follow_time=12)
  
  # update total_time and follow_time
  duration                <- exp_duration(arm0, arm1, d=d)
  arm0$total_time         <- duration
  arm0$follow_time        <- duration - arm0$accr_time
  arm1$total_time         <- duration
  arm1$follow_time        <- duration - arm1$accr_time
  
  # record results
  optimal$total_time[r]   <- duration
  optimal$power[r]        <- power_two_arm(arm0, arm1)
  optimal$events0[r]      <- exp_events(arm0)
  optimal$events1[r]      <- exp_events(arm1)
  
}

head(optimal, 5)

## ---- fig.width=4-------------------------------------------------------------
group_by(optimal, HR) %>%
  filter(power==max(power)) %>% # identify p1 that maximizes power
  mutate(eprop=events1/d) %>%
  select(HR, p1, eprop) %>%
  gather(category, prop, 2:3) %>%
  mutate(category=ifelse(category=="p1", "Patients", "Events")) %>%
  ggplot(aes(x=HR,y=prop)) +
  geom_line(aes(col=category, lty=category), lwd=0.8) +
  labs(x="Hazard ratio", 
       y="Proportion contributed by active arm",
       col="",
       lty="")

## -----------------------------------------------------------------------------
p1.vec <- c(0.5, 3/5, 2/3)
HR.vec <- seq(0.3, 0.9, 0.05)
fixed <- tibble(
  p1 = rep(p1.vec, each=length(HR.vec)),
  HR = rep(HR.vec, length(p1.vec)),
  accr_time = fun_hr(HR=HR, k=2.3, range.min=12, range.max=48),
  d = (qnorm(0.975)+qnorm(0.9))^2/0.5/0.5/log(HR)^2, # schoenfeld 1981
  n = d / fun_hr(HR, k=5, range.min=0.6, range.max=0.7),
  m = fun_hr(HR=HR, k=0, range.min=6, range.max=24),
  ed = 0, # power, schoenfeld
  mu = 0, # power, recommended asymptotic approximation
  mu_b = 0, # power, block randomization
  mu_s = 0  # power, simple randomization
)

## -----------------------------------------------------------------------------
R   <- dim(fixed)[1]
for (r in 1:R) {
  
  # scenario specific parameters
  p1        <- fixed$p1[r]
  HR        <- fixed$HR[r]
  accr_time <- fixed$accr_time[r]
  d         <- fixed$d[r]
  n         <- fixed$n[r]
  m         <- fixed$m[r]
  
  # create arm objects
  arm0 <- create_arm(size=n*(1-p1),
                     accr_time=accr_time,
                     accr_interval=accr_time*c(0,0.25,0.5,1), # piecewise-uniform accrual
                     accr_param=c(0.05,0.25,0.7),
                     surv_scale=per2haz(m),
                     loss_scale=per2haz(m)*0.05,
                     follow_time=12)
  arm1 <- create_arm(size=n*p1,
                     accr_time=accr_time,
                     accr_interval=accr_time*c(0,0.25,0.5,1),
                     accr_param=c(0.05,0.25,0.7),
                     surv_scale=per2haz(m/HR),
                     loss_scale=arm0$loss_scale,
                     follow_time=12)
  
  # update total_time and follow_time
  duration                <- exp_duration(arm0, arm1, d=d)
  arm0$total_time         <- duration
  arm0$follow_time        <- duration - arm0$accr_time
  arm1$total_time         <- duration
  arm1$follow_time        <- duration - arm1$accr_time
  
  # record results
  fixed$ed[r]       <- power_two_arm(arm0, arm1, 
                                     test=list(test="weighted logrank", 
                                               mean.approx="event driven"))
  fixed$mu[r]       <- power_two_arm(arm0, arm1)
  fixed$mu_b[r]     <- power_two_arm(arm0, arm1, 
                                     test=list(test="weighted logrank", 
                                               var.approx="block"))
  fixed$mu_s[r]     <- power_two_arm(arm0, arm1, 
                                     test=list(test="weighted logrank", 
                                               var.approx="simple"))
  
}

## ---- fig.width=6-------------------------------------------------------------
gather(fixed, key="approximation", value="power", 7:10) %>%
  ggplot(aes(x=HR, y=power)) +
  geom_line(aes(col=approximation, lty=approximation)) +
  facet_wrap(~round(p1,2)) +
  labs(x="Hazard ratio",
       y="Power",
       col="",
       lty="")

