---
title: "RMarkdown version of lab CAST"
author: "Constantin T Yiannoutsos"
date: "March 21, 2018"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, packages, echo=FALSE, results="hide", message=FALSE}
options(width=72)
```
# Introduction: The R package ```gsDesign```
First, we import the library ```gsDesign``` into R.
```{r, enrollment, message=FALSE}
################################################
### Sequential monitoring of clinical trials ###
################################################
library(gsDesign)
```
# Defining user-specified spending functions
The function ```gsDesign``` can carry out lots of analyses. Here we focus on the definition of a user-specified spending fuction.
The CAST study had a function that spent half the alpha level (of 2.5%) during the interim analyses prior to the final analysis, and half of the alpha level during the final analysis.
We first define the spending function:
```{r, sf}
sfcast <- function(alpha, t, param)
{
# set spending using constant alpha/2 until last interim then alpha/2 at final
x <- list(name="CAST example", param=param, parname=NULL,
sf=sfcast, spend=cumsum(c(rep(alpha/(2*(length(t)-1)),length(t)-1), alpha/2)))
class(x) <- "spendfn"
x
}
```
Notice that the object that is being created ($x$) has a number of attributes, such as ```name```, ```param``` and it must be of class ```spendfn``` to be recognized by the package.
Now let's try it out!
First we will plot the spending fuunction to see hwo the alpha level is being spent
```{r, sfexample, fig.width=4.5, fig.height=4.5, message=FALSE, fig.align='center', fig.cap='Figure 1. Alpha spending function based on user-specified spending function, assuming α=0.025.'}
t<-0:20/20
plot(t, sfcast(0.025, t, NULL)$spend, type="l",
xlab="Proportion of information",
ylab="Cumulative proportion of total spending")
```
# Using ```sfcast``` in the CAST trial example
Now, let's define the CAST trial bounds:
```{r, CASTbounds, fig.width=4.5, fig.height=4.5, message=FALSE, fig.align='center', fig.cap='Figure 2. Group sequential bounds in the CAST study.'}
x <- gsDesign(k=length(t), test.type=2, sfu=sfcast, alpha=0.025)
plot(x$timing, x$upper$bound, type="l", ylim=c(-3.5,3.5) ,
ylab="Z(t)", xlab="Trial fraction")
lines(x$timing, x$lower$bound)
```
Now recall that the first DSMB review of the CAST study was after 32/425 events were observed (i.e., $t=0.075$) and the log-rank test statistic was $Z(t)=-2.82$. During the second DSMB meeting, 42/300 events were observed ($t=14\%$) after the expected number of total events was revised to 300 from 425. During that time, $Z(t)=-3.20$.
To see whether we have crossed a boundary in either case, we simply plot these two points on the previous plot.
```{r, CASTreviews, fig.width=4.5, fig.height=4.5, message=FALSE, fig.align='center', fig.cap='Figure 3. Group sequential bounds in the CAST study with log-rank statistics at the two DSMB reviews.'}
x <- gsDesign(k=length(t), test.type=2, sfu=sfcast, alpha=0.025)
plot(x$timing, x$upper$bound, type="l", ylim=c(-3.5,3.5) ,
ylab="Z(t)", xlab="Trial fraction")
lines(x$timing, x$lower$bound)
text(32/425, -2.82, "X")
text(42/300, -3.2, "X", col="red")
```