R/refinedBoundaries.R

##########
# A gatekeeping test on a primary and a secondary endpoint in a group sequential design with multiple interim looks
# R program for Refined Boundaries
# Version 1.2
# Programmer: Jiangtao Gou
# Version 1.0: 2017/Mar/14-Apr/12
# Version 1.1: 2019/Jun/24
# Version 1.2: 2023/Jun/26
# Reference: Tamhane AC, Gou J, Jennison C, Mehta CR, Curto T.
#   A Gatekeeping Test on a Primary and a Secondary Endpoint in a Group
#   Sequential Design with Multiple Interim Looks.
#   Biometrics (2018).
##########

# require(mvtnorm)
# require(ldbounds)
# require(xtable)

#
# Function 1
# function cdBoundary
# Generate lower and upper bounds for programs calculating the secondary endpoint's type I error when rho=1
# Input:
#  c boundaries cvec (vector),
#  d boundaries dvec (vector),
#  gamma, square root of information gammaVec (vector),
#  effect size of secondary endpoint dlt (number),
#  lower or upper bound upper (binary).
# Output:
#  lower or upper bounds (vector).
# Dependency:
#  None.
#
#' Lower and Upper Bounds Generator
#'
#' Generate lower and upper bounds for programs calculating the secondary endpoint's type I error when the correlation rho between the primary endpoint and the secondary endpoint equals 1.
#'
#' @param cvec primary boundary.
#' @param dvec secondary boundary.
#' @param gammaVec square root of information vector.
#' @param dlt test statistic of the primary endpoint follows a normal distribution with mean \code{dlt} and standard deviation 1.
#' @param upper type of bounds, upper bound is \code{TRUE}, lower bound is \code{FALSE}.
#' @return lower and upper bounds for programs calculating the secondary endpoint's type I error when the correlation rho is 1.
#'
#' @author Jiangtao Gou
#'
#' @details
#' This function generates upper and lower bounds for further computation. For more details, refer to Tamhane et al. (2018, Biometrics), section 4.2.
#'
#' @references
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'  Gou, J. (2022). Sample size optimization and initial allocation of the significance levels in group sequential trials with multiple endpoints. \emph{Biometrical Journal}, 64(2), 301–311.
#'
#' @examples
#' cvec <- rep(1.992,3)
#' dvec <- c(1.535*sqrt(3),1.535*sqrt(3/2),1.535)
#' gammaVec <- c(sqrt(1/3),sqrt(2/3),1)
#' dlt <- 2
#' uBoundary <- cdBoundary(cvec, dvec, gammaVec, dlt, upper=TRUE)
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
cdBoundary <- function (cvec, dvec, gammaVec, dlt, upper=TRUE) {
  K <- length(cvec);
  if (upper == TRUE) {
    uBoundary <- rep(Inf,K);
    uBoundary[1:(K-1)] = cvec[1:(K-1)] - gammaVec[1:(K-1)]*dlt;
    return(uBoundary);
  } else {
    lBoundary <- rep(-Inf,K);
    lBoundary[K] = max(cvec[K] - gammaVec[K]*dlt,dvec[K]);
    return(lBoundary);
  }
}
# End of function cdBoundary
#

#
# Function 2
# function genCorrMat
# Correlation matrix generator.
# Input:
#  gammaVec: a vector which contains gamma_{1}, ..., gamma_{K-1}, gamma_{K},
#  type: For primary endpoint calculation, type is 1,
#   the returned matrix is K by K. For secondary endpoint calculation,
#   type is 2, the returned matrix is (K+1) by (K+1).
#  rhoPS: correlation between primary and secondary endpoints
# Output:
#  Correlation matrix generator, K by K for primary endpoint, (K+1) by (K+1) for secondary endpoint.
# Dependency:
#  None.
#
#' Correlation Matrix Generator
#'
#' Generate correlation matrix between standardized sample mean test statistics for the two endpoint at different looks.
#'
#' @author Jiangtao Gou
#' @author Fengqing (Zoe) Zhang
#'
#' @param gammaVec a vector which contains gamma_(1), ..., gamma_(K-1), gamma_(K), square root of information vector.
#' @param type type of primary or secondary endpoint. For primary endpoint calculation, \code{type} is 1, the returned matrix is K by K. For secondary endpoint calculation, \code{type} is 2, the returned matrix is (K+1) by (K+1).
#' @param rhoPS correlation between primary and secondary endpoints.
#' @return correlation matrix, K by K for primary endpoint, (K+1) by (K+1) for secondary endpoint, where K is the number of interims.
#'
#' @details
#' This function generates correlation matrix between different mean statistics. For more details, refer to Tamhane et al. (2018, Biometrics), section 2.
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @references
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'  Tamhane, A. C., & Gou, J. (2022). Chapter 2 - Multiple test procedures based on p-values. In X. Cui, T. Dickhaus, Y. Ding, & J. C. Hsu (Eds.), \emph{Handbook of multiple comparisons} (Vol. 45, pp. 11–34).
#'
#' @examples
#' corrMat <- genCorrMat(gammaVec=c(sqrt(1/3), sqrt(2/3), 1), type=2, rhoPS = 0.3)
#'
genCorrMat <- function (gammaVec, type, rhoPS = 0) {
  K <- length(gammaVec);
  if (type == 1) {
    corrMat <- matrix(rep(1,K*K),nrow=K,ncol=K,byrow=TRUE);
    for (i in 1:K) {
      for (j in 1:K){
        corrMat[i,j] <- min(gammaVec[i],gammaVec[j])/max(gammaVec[i],gammaVec[j]);
      }
    }
    return(corrMat);
  } else if (type == 2) {
    corrMat <- matrix(rep(1,(K+1)*(K+1)),nrow=K+1,ncol=K+1,byrow=TRUE);
    for (i in 1:K) {
      for (j in 1:K){
        corrMat[i,j] <- min(gammaVec[i],gammaVec[j])/max(gammaVec[i],gammaVec[j]);
      }
    }
    for (i in 1:K) {
      corrMat[i,K+1] <- rhoPS*gammaVec[i]/gammaVec[K];
      corrMat[K+1,i] <- rhoPS*gammaVec[i]/gammaVec[K];
    }
    return(corrMat);
  } else {
    warning("Type is 1 (for primary endpoint calculation) or 2 (for secondary endpoint calculation).");
    return(type);
  }
}
# End of function genCorrMat
#

#
# Function 3
# function ldPrimaryBoundary
# Primary boundaries calculation of Lan-DeMets OBF and POC
# Input:
#  tVec: a vector of information, gammaVec = sqrt(tVec)
#  alpha: significance level
#  type: type 1 OBF, type 2 POC
#  initIntvl: paramter for function uniroot (two numbers)
# Output:
#  Primary boundaries (vector)
# Dependency:
#  genCorrMat,
#  pmvnorm (package mvtnorm).
#  uniroot (package stats)
#
#' Calculate Primary Boundaries, the Error Spending Approach
#'
#' Primary boundaries calculation of Lan-DeMets OBF and POC.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @author Jiangtao Gou
#'
#' @seealso \code{primaryBoundary}
#'
#' @param tVec a vector of information, gammaVec = sqrt(tVec).
#' @param alpha significance level
#' @param type type of sequential procedure. OBF is 1, POC is 2.
#' @param initIntvl paramter for function uniroot (two numbers)
#' @return a vector of primary boundaries.
#'
#' @references
#' Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'
#'  Gou, J. (2023). Trigger strategy in repeated tests on multiple hypotheses. \emph{Statistics in Biopharmaceutical Research}, 15(1), 133–140.
#'
ldPrimaryBoundary <- function (tVec,alpha,type=1,initIntvl=c(0.8,8)) {
  K <- length(tVec);
  cVec <- rep(0,K);
  gammaVec <- sqrt(tVec);
  target <- function (ckk,cVec,gammaVec,alpha) {
    kk <- length(gammaVec);
    lowerB <- rep(-Inf,kk);
    upperB <- c(cVec,ckk);
    meanV <- rep(0,kk);
    corrM <- genCorrMat(gammaVec,1);
    result <- mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
    return(result - 1 + alpha);
  }
  if (type == 1) {
    # print('It is OBF');
    alphaVec <- 2 - 2*pnorm(qnorm(1-alpha/2)/gammaVec);
    cVec[1] <- qnorm(1-alphaVec[1]);
    for (i in 2:K) {
      result.OF <- stats::uniroot(target, lower = initIntvl[1], upper = initIntvl[2], tol = 2.5e-16, cVec = cVec[1:(i-1)], gammaVec = gammaVec[1:i], alpha = alphaVec[i]);
      cVec[i] = result.OF$root;
    }
    return(cVec);
  } else if (type == 2) {
    # print('It is POC');
    alphaVec <- alpha*log(1 + (exp(1)-1)*tVec);
    cVec[1] <- qnorm(1-alphaVec[1]);
    for (i in 2:K) {
      result.PO <- stats::uniroot(target, lower = initIntvl[1], upper = initIntvl[2], tol = 2.5e-16, cVec = cVec[1:(i-1)], gammaVec = gammaVec[1:i], alpha = alphaVec[i]);
      cVec[i] = result.PO$root;
    }
    return(cVec);
  } else {
    warning("Only OBF (1) and POC (2) are currently available.");
    return(K);
  }
}
# End of function ldPrimaryBoundary
#

#
# Function 4
# function ldSecControl
# Secondary boundaries calculation of Lan-DeMets OBF and POC
# Input:
#  ap: significance level for the primary endpoint
#  alpha: targeted significance level for the secondary endpoint
#  cvec: a vector of calculated primary boundaries
#  tVec: a vector of information, gammaVec = sqrt(tVec)
#  ExtrmLoc: an integer between 1 and K, locate the maximum of type I error of secondary endpoint
#  type: Type 1 OBF d, Type 2 POC d.
# Output:
#  Difference between alpha and the calculated error rate
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  pmvnorm (package mvtnorm),
#  pnorm (package stats),
#  bounds (package ldbounds).
#
#'
#' Difference between the Error Rate and Significance Level, the Error Spending Approach
#'
#' Calculate the difference between the error rate and significance level for the secondary endpoint, Lan-DeMets error spending approach.
#'
#' @param ap significance level for the primary endpoint
#' @param alpha targeted significance level for the secondary endpoint
#' @param cvec a vector of calculated primary boundaries
#' @param tVec a vector of information, gammaVec = sqrt(tVec)
#' @param ExtrmLoc an integer between 1 and K, locate the maximum of type I error of secondary endpoint
#' @param type type of sequential procedures. Type 1 OBF d, Type 2 POC d.
#' @return difference between alpha and the calculated error rate.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @author Jiangtao Gou
#'
#' @seealso \code{secControl}
#'
#' @references
#' Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'
ldSecControl <- function (ap,alpha,cvec,tVec,ExtrmLoc,type=2) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  if (type == 1) {
    dvec.obf <- ldbounds::ldBounds(t=tVec,iuse=c(1),alpha=c(ap),sides=1);
    dvec <- dvec.obf$upper.bounds;
  } else if (type == 2) {
    dvec.poc <- ldbounds::ldBounds(t=tVec,iuse=c(2),alpha=c(ap),sides=1);
    dvec <- dvec.poc$upper.bounds;
  } else {
    warning("Type 1 OBF d, Type 2 POC d.");
    return(K);
  }
  dlt <- (cvec[ExtrmLoc] - dvec[ExtrmLoc])/gammaVec[ExtrmLoc];
  ErrRate <- 1 - pnorm(max(cvec[1]-gammaVec[1]*dlt, dvec[1]));
  for (i in 2:K) {
    lowerB <- cdBoundary(cvec[1:i], dvec[1:i], gammaVec[1:i], dlt, upper=FALSE);
    upperB <- cdBoundary(cvec[1:i], dvec[1:i], gammaVec[1:i], dlt, upper=TRUE);
    meanV <- rep(0,i);
    corrM <- genCorrMat(gammaVec[1:i],1);
    ErrRate = ErrRate + mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
  }
  return(ErrRate - alpha);
}
# End of function ldSecControl
#

#
# Function 5
# function primaryBoundary
# Original OBF and POC boundaries for primary endpoints
# Input:
#  gammaVec: square root of information (vector)
#  alpha: significance level for the primary endpoint
#  type: type 1: OBF, type 2: POC.
#  initIntvl: parameters for uniroot function.
# Output:
#  Original OBF and POC boundaries (primary endpoints) (a number, cK)
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  pmvnorm (package mvtnorm),
#  uniroot (package stats).
#
#' Calculate Primary Boundaries, Standard Approach
#'
#' Primary boundaries calculation of standard (original) OBF and POC.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @author Jiangtao Gou
#'
#' @seealso \code{ldPrimaryBoundary}
#'
#' @param gammaVec a vector of square root of information.
#' @param alpha significance level
#' @param type type of sequential procedure. OBF is 1, POC is 2.
#' @param initIntvl paramter for function uniroot (two numbers)
#' @return original OBF and POC boundaries (primary endpoints) (a number, c_(K)).
#'
#' @references
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2017+). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, to appear.
#'
primaryBoundary <- function (gammaVec,alpha,type=1,initIntvl=c(1,4)) {
  K <- length(gammaVec);
  if (type == 1) {
    target <- function (c,gammaVec,alpha) {
      lowerB <- rep(-Inf,K);
      upperB <- c/gammaVec;
      meanV <- rep(0,K);
      corrM <- genCorrMat(gammaVec,1);
      result <- mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
      return(result - 1 + alpha);
    }
    result.OF <- stats::uniroot(target, lower = initIntvl[1], upper = initIntvl[2], tol = 2.5e-16, gammaVec = gammaVec, alpha = alpha);
    return(result.OF$root);
  } else if (type == 2) {
    target <- function (c,gammaVec,alpha) {
      lowerB <- rep(-Inf,K);
      upperB <- c;
      meanV <- rep(0,K);
      corrM <- genCorrMat(gammaVec,1);
      result <- mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
      return(result - 1 + alpha);
    }
    result.OF <- stats::uniroot(target, lower = initIntvl[1], upper = initIntvl[2], tol = 2.5e-16, gammaVec = gammaVec, alpha = alpha);
    return(result.OF$root);
  } else {
    warning("Only OBF (1) and POC (2) are currently available.");
    return(K);
  }
}
# End of function primaryBoundary
#

#
# Function 6
# function secControl
# Secondary boundaries calculation of original OBF and POC
# Input:
#  d: boundary of secondary endpoint (a number, dK)
#  gammaVec: square root of information (vector)
#  alpha: targeted significance level for the secondary endpoint
#  cvec: boundaries of primary endpoints
#  gammaVec: square root of information
#  ExtrmLoc: the location of the maximum of type I error of the secondary endpoint
#  type: Type 1 OBF d, Type 2 POC d.
# Output:
#  Original OBF and POC boundaries (primary endpoints) (a number, cK)
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  pmvnorm (package mvtnorm).
#'
#' Difference between the Error Rate and Significance Level, Standard Approach
#'
#' Calculate the difference between the error rate and significance level for the secondary endpoint, standard (original) approach.
#'
#' @param d boundary of secondary endpoint at the final look (a number, d_(K))
#' @param alpha targeted significance level for the secondary endpoint
#' @param cvec a vector of calculated primary boundaries
#' @param gammaVec square root of information
#' @param ExtrmLoc an integer between 1 and K, locate the maximum of type I error of secondary endpoint
#' @param type type of sequential procedures. Type 1 OBF d, Type 2 POC d.
#' @return difference between alpha and the calculated error rate.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @author Jiangtao Gou
#'
#' @seealso \code{ldSecControl}
#'
#' @references
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'
secControl <- function (d,alpha,cvec,gammaVec,ExtrmLoc,type=2) {
  K <- length(gammaVec);
  if (type == 1) {
    dvec = d/gammaVec;
  } else if (type == 2) {
    dvec = d/rep(1,K);
  } else {
    warning("Type 1 OBF d, Type 2 POC d.");
    return(K);
  }
  dlt <- (cvec[ExtrmLoc] - dvec[ExtrmLoc])/gammaVec[ExtrmLoc];
  ErrRate <- 1 - pnorm(max(cvec[1]-gammaVec[1]*dlt, dvec[1]));
  for (i in 2:K) {
    lowerB <- cdBoundary(cvec[1:i], dvec[1:i], gammaVec[1:i], dlt, upper=FALSE);
    upperB <- cdBoundary(cvec[1:i], dvec[1:i], gammaVec[1:i], dlt, upper=TRUE);
    meanV <- rep(0,i);
    corrM <- genCorrMat(gammaVec[1:i],1);
    ErrRate = ErrRate + mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
  }
  return(ErrRate - alpha);
}
# End of function secControl
#

#
# Function 7
# function primaryBoundaryVec
# Calculate the primary boundaries
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  initIntvl: parameter for function uniroot (two numbers)
#     for function primaryBoundary or function ldPrimaryBoundary
#  OBF: TRUE for OBF, FALSE for POC
#  LanDeMets: TRUE for Lan-Demets type boundaries, FALSE for original boundaries
#  digits: number of digits for output,
#  printOut: TRUE for printing the boundaries.
# Output:
#  OBF and POC boundaries (primary endpoints) (vector)
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  primaryBoundary,
#  ldPrimaryBoundary,
#  pmvnorm (package mvtnorm).
#
#'
#' Calculate the Primary Boundaries
#'
#' Primary boundaries are calculated, including the standard approach and the error spending approach.
#'
#' @param alpha significance level for the primary endpoint.
#' @param tVec information (vector).
#' @param initIntvl parameter for function uniroot (two numbers) for function primaryBoundary or function ldPrimaryBoundary
#' @param OBF type of procedures. \code{TRUE} for OBF, \code{FALSE} for POC.
#' @param LanDeMets type of procedures. \code{TRUE} for Lan-Demets type boundaries, \code{FALSE} for original boundaries.
#' @param digits number of digits for output,
#' @param printOut \code{TRUE} for printing the boundaries.
#' @return OBF and POC boundaries (primary endpoints) (vector).
#'
#' @author Jiangtao Gou
#'
#' @examples
#' require(mvtnorm)
#' K <- 4
#' alpha <- 0.025
#' tVec <- (1:K)/K
#' boundaryVector <- primaryBoundaryVec(alpha,tVec,initIntvl=c(1,4),
#'    OBF=TRUE,LanDeMets=FALSE,digits=3,printOut=TRUE)
#' boundaryVector <- primaryBoundaryVec(alpha,tVec,initIntvl=c(1,4),
#'    OBF=FALSE,LanDeMets=FALSE,digits=3,printOut=TRUE)
#' boundaryVector <- primaryBoundaryVec(alpha,tVec,initIntvl=c(1,8),
#'    OBF=TRUE,LanDeMets=TRUE,digits=3,printOut=TRUE)
#' boundaryVector <- primaryBoundaryVec(alpha,tVec,initIntvl=c(1,4),
#'    OBF=FALSE,LanDeMets=TRUE,digits=3,printOut=TRUE)
#'
#' @references
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74(1), 40-48.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
primaryBoundaryVec  <- function (alpha,tVec,OBF=TRUE,LanDeMets=FALSE,digits=2,printOut=TRUE,initIntvl=c(1,8)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  if (OBF == TRUE) {
    typeOP = 1;
  } else {
    typeOP = 2;
  }
  if (LanDeMets == FALSE) {
    bndyRep <- rep(0,1);
    for (i in 1:1) {
      bndyRep[i] <- primaryBoundary(gammaVec,alpha,typeOP,initIntvl);
    }
    cK <- median(bndyRep);
    if (OBF == TRUE) {
      bndyVec <- rep(cK,K)/gammaVec;
    } else {
      bndyVec <- rep(cK,K);
    }
    rBndyVec <- round(bndyVec, digits);
    if (printOut == TRUE) {
      message(rBndyVec);
    }
    return(bndyVec);
  } else {  # Lan-DeMets
    bndyRep <- matrix(rep(0,1*K),nrow=1);
    for (i in 1:1) {
      bndyRep[i,] <- ldPrimaryBoundary(tVec,alpha,typeOP,initIntvl);
    }
    bndyVec <- rep(0,K);
    for (j in 1:K) {
      bndyVec[j] <- median(bndyRep[,j]);
    }
    rBndyVec <- round(bndyVec, digits);
    if (printOut == TRUE) {
      message(rBndyVec);
    }
    return(bndyVec);
  }
}
#
# End of function primaryBoundaryVec
#

#
# Function 8
# function initLocPeak
# Return the initial location of maximum, with originical d-vec
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  cVec: primary boundaries are given
#  type: OBF 1, POC 2
#  initIntvl: parameters for uniroot
# Output:
#  Inital location of maximum (a number between 1 and K)
# Dependency:
#  secControl
#  uniroot (package stats).
#
#' Find the Location of Maximum, Standard OBF and POC
#'
#' Calculate the location of maximal tyep I error of the standard O'Brien-Fleming and Pocock refined secondary boundaries.
#'
#' @author Jiangtao Gou
#' @param alpha type I error.
#' @param tVec information vector.
#' @param cvec primary group sequential boundary.
#' @param type type of the test procedure for the secondary endpoint. O'Brien- Fleming (OBF) type error spending funciton is 1, Pocock (POC) type error spending funciton is 2.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return location of maximum, a number between 1 and the number of interims
#'
#' @details
#' This function search the location of the maximal point, in order to calculate the standard (origiinal) O'Brien-Fleming (OBF) and Pocock (POC) refined secondary boundaries.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{SecondaryBoundary}, \code{ldInitLocBeak}
#' @examples
#' require(mvtnorm)
#' K <- 8
#' gammaVec <- sqrt((1:K)/K)
#' tVec <- gammaVec^2
#' alpha <- 0.025
#' c <- 2.072274
#' cvec <- c/gammaVec
#' loc <- initLocPeak(alpha,tVec,cvec,type=2,initIntvl=c(1,3))
#'
#' @references
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, to appear.
#'
initLocPeak <- function (alpha,tVec,cvec,type=2,initIntvl=c(1,4)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  locVec <- rep(0,1);
  for (j in 1:1) {
    resultVec <- rep(0,K); # Need to be predefined, otherwise the program does not work
    for (i in 1:K) {
      result <- stats::uniroot(secControl,lower=initIntvl[1],upper=initIntvl[2],tol=2.5e-16,alpha=alpha,cvec=cvec,gammaVec=gammaVec,ExtrmLoc=i,type=type);
      resultVec[i] <- result$root;
      # print(resultVec);
    }
    locVec[j] <- which.max(resultVec);
  }
  # print(locVec);
  locPeak <- as.numeric(names(sort(-table(locVec)))[1]) # Find the mode
  # Reference: <http://stackoverflow.com/questions/2547402/is-there-a-built-in-function-for-finding-the-mode>
  return(locPeak);
}
# End of function initLocPeak
#

#
# Function 9
# function secondaryBoundary
# Calculate the secondary boundaries (original OBF POC)
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  cVec: primary boundaries are given
#  locPeak: location of maximum, returned by function initLocPeak
#  type: OBF 1, POC 2
#  initIntvl: parameters for uniroot
# Output:
#  boundary vector
# Dependency:
#  secControl
#  uniroot (package stats).
#
#
#' Calculate the Refined Secondary Boundaries, Standard OBF and POC
#'
#' Calculate the standard O'Brien-Fleming and Pocock refined secondary boundaries
#'
#' @author Jiangtao Gou
#' @param alpha type I error.
#' @param tVec information vector.
#' @param cvec primary group sequential boundary.
#' @param locPeak location of maximum, a number between 1 and the number of interims.
#' @param type type of the test procedure for the secondary endpoint. O'Brien- Fleming (OBF) type error spending funciton is 1, Pocock (POC) type error spending funciton is 2.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return standard O'Brien-Fleming and Pocock refined secondary boundaries.
#'
#' @details
#' This function calculates the standard (origiinal) O'Brien-Fleming (OBF) and Pocock (POC) refined secondary boundaries.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{ldSecondaryBoundary}, \code{initLocBeak}
#' @examples
#' \dontrun{
#' require(mvtnorm)
#' K <- 8
#' gammaVec <- sqrt((1:K)/K)
#' tVec <- gammaVec^2
#' alpha = 0.025
#' c <- 2.072274
#' cvec <- c/gammaVec
#' loc <- initLocPeak(alpha,tVec,cvec,type=2,initIntvl=c(1,4))
#' sbvec <- secondaryBoundary(alpha,tVec,cvec,loc,type=2,
#'        initIntvl=c(1,8))
#' }
#'
#' @references
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2017+). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
secondaryBoundary <- function (alpha,tVec,cvec,locPeak,type=2,initIntvl=c(1,4)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  resultVec <- rep(0,1);
  for (i in 1:1) {
    result <- stats::uniroot(secControl, lower = initIntvl[1], upper = initIntvl[2], tol = 2.5e-16, alpha=alpha,cvec=cvec,gammaVec=gammaVec,ExtrmLoc=locPeak,type=type);
    resultVec[i] <- result$root;
  }
  dK <- median(resultVec) #
  if (type == 1) {
    bndyVec <- rep(dK,K)/gammaVec;
  } else if (type == 2) {
    bndyVec <- rep(dK,K);
  } else {
    warning("Type 1 OBF, Type 2 POC.");
  }
  return(bndyVec);
}
# End of function secondaryBoundary
#

#
# Function 10
# function ldInitLocPeak
# Return the initial location of maximum, with originical d-vec, for Lan-DeMets
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  cVec: primary boundaries are given
#  type: OBF 1, POC 2
#  initIntvl: parameters for uniroot
# Output:
#  Inital location of maximum (a number between 1 and K)
# Dependency:
#  ldSecControl
#  uniroot (package stats).
#
#
#' Find the Location of Maximum, Error Spending Approach
#'
#' Calculate the location of maximal type I error of secondary endpoint.
#' @author Jiangtao Gou
#' @param alpha type I error.
#' @param tVec information vector.
#' @param cvec primary group sequential boundary.
#' @param type type of the test procedure for the secondary endpoint. O'Brien- Fleming (OBF) type error spending funciton is 1, Pocock (POC) type error spending funciton is 2.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return location of maximum, a number between 1 and the number of interims.
#'
#' @details
#' This function searches the location of maximal type I error of secondary endpoint by using the error spending approach.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{ldSecondaryBoundary}, \code{initLocBeak}
#' @examples
#' \dontrun{
#' require(mvtnorm)
#' require(ldbounds)
#' K <- 6;
#' tVec <- c(140,328,453,578,659,1080)/1080;
#' alpha = 0.025;
#' cvec.obf <- ldbounds::ldBounds(tVec,iuse=c(1),alpha=c(alpha),sides=1);
#' cvec <- cvec.obf$upper.bounds;
#' loc <- ldInitLocPeak(alpha,tVec,cvec,type=2,initIntvl=c(0.9,4))
#' }
#'
#' @references
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
#'
ldInitLocPeak <- function (alpha,tVec,cvec,type=2,initIntvl=c(0.8,4)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  locVec <- rep(0,1);
  for (j in 1:1) {
    resultVec <- rep(0,K); # Need to be predefined, otherwise the program does not work
    for (i in 1:K) {
      result <- stats::uniroot(ldSecControl,lower=initIntvl[1]*alpha,upper=initIntvl[2]*alpha,tol=2.5e-16,alpha=alpha,cvec=cvec,tVec=tVec,ExtrmLoc=i,type=type);
      resultVec[i] <- result$root;
      # print(resultVec);
    }
    locVec[j] <- which.min(resultVec);
  }
  # print(locVec);
  locPeak <- as.numeric(names(sort(-table(locVec)))[1]) # Find the mode
  # Reference: <http://stackoverflow.com/questions/2547402/is-there-a-built-in-function-for-finding-the-mode>
  return(locPeak);
}
# End of function ldInitLocPeak
#

#
# Function 11
# function ldSecondaryBoundary
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  cVec: primary boundaries are given
#  locPeak: location of maximum, returned by function initLocPeak
#  type: OBF 1, POC 2
#  initIntvl: parameters for uniroot
# Output:
#  boundary vector
# Dependency:
#  ldSecControl
#  uniroot (package stats).
#
#
#' Calculate Refined Secondary Boundary, Error Spending Approach
#'
#' Refined secondary boundaries are calculated by using the error spending approach.
#'
#' @author Jiangtao Gou
#' @param alpha original significance level.
#' @param tVec information vector.
#' @param cvec primary group sequential boundary.
#' @param locPeak location of maximum, a number between 1 and the number of interims.
#' @param type type of the test procedure for the secondary endpoint. O'Brien- Fleming (OBF) type error spending funciton is 1, Pocock (POC) type error spending funciton is 2.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return refined secondary boundaries.
#'
#' @details
#' This function calculates the refined secondary boundaries of any Lan-DeMets error spending boundary based on the primary boundaries.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{secondaryBoundary}, \code{secondaryBoundaryVecLD}
#' @examples
#' \dontrun{
#' require(mvtnorm)
#' require(ldbounds)
#' K <- 6;
#' tVec <- c(140,328,453,578,659,1080)/1080;
#' alpha = 0.025;
#' cvec.obf <- ldbounds::ldBounds(t=tVec,iuse=c(1),alpha=c(alpha),sides = 1);
#' cvec <- cvec.obf$upper.bounds;
#' secbound <- ldSecondaryBoundary(alpha,tVec,cvec,locPeak=4,type=2,
#'     initIntvl=c(0.8,8))
#' }
#'
#' @references
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2017+). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
ldSecondaryBoundary <- function (alpha,tVec,cvec,locPeak,type=2,initIntvl=c(0.6,4)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  resultVec <- rep(0,1);
  for (i in 1:1) {
    result <- stats::uniroot(ldSecControl, lower = initIntvl[1]*alpha, upper = initIntvl[2]*alpha, tol = 2.5e-16, alpha=alpha,cvec=cvec,tVec=tVec,ExtrmLoc=locPeak,type=type);
    resultVec[i] <- result$root;
  }
  aprime <- median(resultVec) #
  if (type == 1) {
    dvec.obf <- ldbounds::ldBounds(t=tVec,iuse=c(1),alpha=c(aprime),sides = 1);
    ldBndyVec <- dvec.obf$upper.bounds;
  } else if (type == 2) {
    dvec.poc <- ldbounds::ldBounds(t=tVec,iuse=c(2),alpha=c(aprime),sides=1);
    ldBndyVec <- dvec.poc$upper.bounds;
  } else {
    warning("Type 1 OBF, Type 2 POC.");
  }
  return(ldBndyVec);
}
# End of function ldSecondaryBoundary
#

#
# Function 12
# nominal significance
# Input:
#  alpha: significance level for the primary endpoint
#  tVec: information (vector)
#  cVec: primary boundaries are given
#  locPeak: location of maximum, returned by function initLocPeak
#  type: OBF 1, POC 2
#  initIntvl: parameters for uniroot
# Output:
#  nominal significance
# Dependency:
#  ldSecControl
#  uniroot (package stats).
#
#' Calculate Nominal Significance, Error Spending Approach
#'
#' Nominal significance for the secondary endpoint are calculated by using the error spending approach.
#'
#' @param alpha original significance level.
#' @param tVec information vector.
#' @param cvec primary group sequential boundary.
#' @param locPeak location of maximum, a number between 1 and the number of interims.
#' @param type O'Brien- Fleming (OBF) type error spending funciton is 1, Pocock (POC) type error spending funciton is 2.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return nominal significance of the secondary group sequential boundary.
#'
#' @details
#' This function calculates the nominal significance level of any Lan-DeMets error spending boundary.
#' The original significance level is used to choose the initial searching range of the nominal significance.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @author Jiangtao Gou
#'
#' @seealso \code{nominalSig}, \code{secondaryBoundaryVecLD}
#' @examples
#' \dontrun{
#' require(mvtnorm)
#' require(ldbounds)
#' K <- 6;
#' tVec <- c(140,328,453,578,659,1080)/1080;
#' alpha <- 0.025;
#' cvec.obf <- ldbounds::ldBounds(t=tVec,iuse=c(1),alpha=c(alpha),sides = 1);
#' cvec <- cvec.obf$upper.bounds;
#' alphaprime <- ldNominalSig(alpha,tVec,cvec,locPeak=4,type=2,
#'       initIntvl=c(1,4))
#' }
#'
#' @references
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
ldNominalSig <- function (alpha,tVec,cvec,locPeak,type=2,initIntvl=c(1,4)) {
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  resultVec <- rep(0,1);
  for (i in 1:1) {
    result <- stats::uniroot(ldSecControl, lower = initIntvl[1]*alpha, upper = initIntvl[2]*alpha, tol = 2.5e-16, alpha=alpha,cvec=cvec,tVec=tVec,ExtrmLoc=locPeak,type=type);
    resultVec[i] <- result$root;
  }
  aprime <- median(resultVec) #
  return(aprime)
}
# End of function ldNominalSig
#

#
# Function 13
# function nominalSig
# Find the nominal Significance level for Original OBF and POC boundaries
# Input:
#  gammaVec: square root of information (vector)
#  alpha: significance level for the primary endpoint
#  cvec: the boundaries
# Output:
#  Nominal significance level
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  pmvnorm (package mvtnorm)
#
#' Calculate Nominal Significance, Standard Approach
#'
#' Nominal significance for the secondary endpoint are calculated by using the standard (original) approach.
#'
#' @param gammaVec square root of information.
#' @param cvec group sequential boundary.
#' @return nominal significance
#'
#' @details
#' This function calculates he nominal significance level of any given boundary.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{ldNominalSig}, \code{secondaryBoundaryVecOrig}
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' nSig <- nominalSig(gammaVec=c(sqrt(1/3),1),cvec=c(2.2,1.8))
#'
#' @author Jiangtao Gou
#'
#' @references
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
nominalSig <- function (gammaVec,cvec) {
  K <- length(gammaVec);
  lowerB <- rep(-Inf,K); #print(lowerB)
  upperB <- cvec; #print(upperB)
  meanV <- rep(0,K);
  corrM <- genCorrMat(gammaVec,1); #print(corrM)
  result <- mvtnorm::pmvnorm(lowerB, upperB, meanV, corrM, algorithm=Miwa(steps=128));
  return(1 - result[1]);
}
# End of function primaryBoundary
#

#
# Function 14
# function secondaryBoundaryVecOrig
# Calculate the secondary boundaries
# Input:
#  alpha: significance level for the secondary endpoint
#  tVec: information (vector)
#  initIntvl: parameter for function uniroot (two numbers)
#     for function primaryBoundary or function ldPrimaryBoundary
#  primaryOBF: TRUE for OBF, FALSE for POC
#  secondaryOBF: TRUE for OBF, FALSE for POC
#  digits: number of digits for output,
#  printOut: TRUE for printing the boundaries.
# Output:
#  OBF or POC boundaries (secondary endpoints) (vector)
# Dependency:
#  genCorrMat,
#  cdBoundary,
#  primaryBoundary,
#  ldPrimaryBoundary,
#  pmvnorm (package mvtnorm).
#<http://stackoverflow.com/questions/8936099/returning-multiple-objects-in-an-r-function>
#
#
#' Calculate Refined Secondary Boundaries and Nominal Significance, Standard Approach
#'
#' Standard refined secondary boundaries, and nominal significance for the secondary endpoint are calculated by using the standard (original) approach.
#'
#' @author Jiangtao Gou
#' @param alpha type I error probability.
#' @param tVec vector of relative information levels. The last element in the vector is 1.
#' @param primaryOBF type of primary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param secondaryOBF type of secondary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return a result list including standard refined secondary boundary and the nominal significance for the secondary endpoint.
#'
#' @details
#' This function uses the standard approach (O'Brien and Fleming 1979, Pocock 1977),
#' and gives a list including refined secondary boundary and the nominal significance for the secondary endpoint.
#' There is a computing parameter \code{initIntvl}.
#' Parameter \code{initIntvl} contains the end-points of the interval to be searched for the root.
#' The lower end point should choose a number around 1,
#' and the upper end point should choose a number between 4 and 10.
#'
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{secondaryBoundaryVec}, \code{secondaryBoundaryVecLD}
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' result <- secondaryBoundaryVecOrig(alpha=0.025,tVec=c(1/2,1),primaryOBF=TRUE,
#'        secondaryOBF=FALSE, initIntvl=c(1,4))
#' result$secondaryBoundary
#' result$nomialSignificance
#'
#' @references
#'  Glimm, E., Maurer, W., and Bretz, F. (2010). Hierarchical testing of multiple endpoints in group-sequential trials. \emph{Statistics in Medicine} \bold{29}, 219-228.
#'
#'  Hung, H. M. J., Wang, S.-J., and O'Neill, R. (2007). Statistical considerations for testing multiple endpoints in group sequential or adaptive clinical trials. \emph{Journal of Biopharmaceutical Statistics} \bold{17}, 1201-1210.
#'
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Mehta, C. R., and Liu, L. (2010). Testing a primary and a secondary endpoint in a group sequential design. \emph{Biometrics} \bold{66}, 1174-1184.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
secondaryBoundaryVecOrig  <- function (alpha,tVec,primaryOBF=TRUE,secondaryOBF=FALSE,initIntvl=c(1,8)) {
  #
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  if (primaryOBF == secondaryOBF) {
    bndyVec <- primaryBoundaryVec(alpha,tVec,OBF=primaryOBF,LanDeMets=FALSE,digits=10,printOut=FALSE,initIntvl=initIntvl);
    nomialSigLvl <- alpha;
  } else {
    primaryBndyVec <- primaryBoundaryVec(alpha=alpha,tVec=tVec,OBF=primaryOBF,LanDeMets=FALSE,digits=10,printOut=FALSE,initIntvl=initIntvl);
    if (secondaryOBF == TRUE) {
      sType = 1;
    } else {
      sType = 2;
    }
    peakLocation <- initLocPeak(alpha=alpha,tVec=tVec,cvec=primaryBndyVec,type=sType,initIntvl=initIntvl);
    bndyVec <- secondaryBoundary(alpha,tVec,cvec=primaryBndyVec,locPeak=peakLocation,type=sType,initIntvl=initIntvl);
    #print(bndyVec)
    #
    nomialSigLvl <- nominalSig(gammaVec=gammaVec,cvec=bndyVec);
  }
  resultlist <- list("secondaryBoundary" = bndyVec, "nomialSignificance" = nomialSigLvl)
  return(resultlist)
}
#
# End of function secondaryBoundaryVecOrig
#

#
# Function 15
# function secondaryBoundaryVecLD
#
#
#' Calculate Refined Secondary Boundaries and Nominal Significance, the Error Spending Approach
#'
#' Lan-DeMets refined secondary boundaries, and nominal significance for the secondary endpoint are calculated by using the error spending approach.
#'
#' @author Jiangtao Gou
#' @param alpha type I error probability.
#' @param tVec vector of relative information levels. The last element in the vector is 1.
#' @param primaryOBF type of primary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param secondaryOBF type of secondary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return a result list including Lan-DeMets refined secondary boundary and the nominal significance for the secondary endpoint.
#'
#' @details
#' This function uses the Lan-DeMets error spending approach,
#' and gives a list including refined secondary boundary and the nominal significance for the secondary endpoint.
#' There is a computing parameter \code{initIntvl}.
#' Parameter \code{initIntvl} contains the end-points of the interval to be searched for the root.
#' For Lan-DeMets error spending approach, the lower end point should choose a number slightly less than 1,
#' and the upper end point should choose a number between 4 and 10.
#'
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{secondaryBoundaryVec}, \code{secondaryBoundaryVecOrig}
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' result <- secondaryBoundaryVecLD(alpha=0.025,tVec=c(1/2,1),primaryOBF=TRUE,
#'         secondaryOBF=FALSE,initIntvl=c(0.8,6))
#' result$secondaryBoundary
#' result$nomialSignificance
#'
#' @references
#'  Glimm, E., Maurer, W., and Bretz, F. (2010). Hierarchical testing of multiple endpoints in group-sequential trials. \emph{Statistics in Medicine} \bold{29}, 219-228.
#'
#'  Hung, H. M. J., Wang, S.-J., and O'Neill, R. (2007). Statistical considerations for testing multiple endpoints in group sequential or adaptive clinical trials. \emph{Journal of Biopharmaceutical Statistics} \bold{17}, 1201-1210.
#'
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Mehta, C. R., and Liu, L. (2010). Testing a primary and a secondary endpoint in a group sequential design. \emph{Biometrics} \bold{66}, 1174-1184.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
secondaryBoundaryVecLD <- function (alpha,tVec,primaryOBF=TRUE,secondaryOBF=FALSE,initIntvl=c(0.8,8)) {
#
  K <- length(tVec);
  gammaVec <- sqrt(tVec);
  if (primaryOBF == secondaryOBF) {
    bndyVec <- primaryBoundaryVec(alpha,tVec,OBF=primaryOBF,LanDeMets=TRUE,digits=10,printOut=FALSE,initIntvl=initIntvl);
    nomialSigLvl <- alpha;
  } else {
    if (primaryOBF == TRUE) {
      pType = 1;
    } else {
      pType = 2;
    }
    if (secondaryOBF == TRUE) {
      sType = 1;
    } else {
      sType = 2;
    }
    cvec.bounds <- ldbounds::ldBounds(t=tVec,iuse=c(pType),alpha=c(alpha),sides = 1);
    cvec <- cvec.bounds$upper.bounds;
    peakLocation <- ldInitLocPeak(alpha=alpha,tVec=tVec,cvec=cvec,type=sType,initIntvl=initIntvl);
    bndyVec <- ldSecondaryBoundary(alpha=alpha,tVec=tVec,cvec=cvec,locPeak=peakLocation,type=sType,initIntvl=initIntvl);
    #
    nomialSigLvl <- ldNominalSig(alpha=alpha,tVec=tVec,cvec=cvec,locPeak=peakLocation,type=sType,initIntvl=initIntvl);
  }
  resultlist <- list("secondaryBoundary" = bndyVec, "nomialSignificance" = nomialSigLvl)
  return(resultlist)
}
# End of function secondaryBoundaryVecLD
#

#
# Function 16
#
# function secondaryBoundaryVec
#
#
#' Calculate Refined Secondary Boundaries and Nominal Significance
#'
#' Refined secondary boundaries, and nominal significance for the secondary endpoint are calculated.
#'
#' @author Jiangtao Gou
#' @param alpha type I error probability.
#' @param tVec vector of relative information levels. The last element in the vector is 1.
#' @param pOBF type of primary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param sOBF type of secondary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param LanDeMets type of boundary, \code{TRUE} is the error spending approach, \code{FALSE} is the original approach.
#' @param initIntvl computing paramter, a pair of numbers containing the end-points of the interval to be searched for the root.
#' @return a result list including refined secondary boundary and the nominal significance for the secondary endpoint.
#'
#' @details
#' This function gives a list including refined secondary boundary and the nominal significance for the secondary endpoint.
#' There are a computing parameter \code{initIntvl}.
#' Parameter \code{initIntvl} contains the end-points of the interval to be searched for the root.
#' For Lan-DeMets error spending approach, the lower end point should choose a number slightly less than 1,
#' and the upper end point should choose a number between 4 and 10.
#'
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @seealso \code{secondaryBoundaryVecLD}, \code{secondaryBoundaryVecOrig}
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' result <- secondaryBoundaryVec(alpha=0.025,tVec=c(1/2,1),pOBF=TRUE,sOBF=FALSE,
#'        LanDeMets=FALSE,initIntvl=c(0.8,5))
#' result$secondaryBoundary
#' result$nomialSignificance
#'
#' @references
#'  Glimm, E., Maurer, W., and Bretz, F. (2010). Hierarchical testing of multiple endpoints in group-sequential trials. \emph{Statistics in Medicine} \bold{29}, 219-228.
#'
#'  Hung, H. M. J., Wang, S.-J., and O'Neill, R. (2007). Statistical considerations for testing multiple endpoints in group sequential or adaptive clinical trials. \emph{Journal of Biopharmaceutical Statistics} \bold{17}, 1201-1210.
#'
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Mehta, C. R., and Liu, L. (2010). Testing a primary and a secondary endpoint in a group sequential design. \emph{Biometrics} \bold{66}, 1174-1184.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
secondaryBoundaryVec <- function (alpha,tVec,pOBF=TRUE,sOBF=FALSE,LanDeMets=FALSE,initIntvl=c(0.8,8)) {
  #
  if (LanDeMets == FALSE) {
    bdns <- secondaryBoundaryVecOrig(alpha=alpha,tVec=tVec,primaryOBF=pOBF,secondaryOBF=sOBF,initIntvl=initIntvl);
    # bdns: boundaries and nominal significance
  } else {
    bdns <- secondaryBoundaryVecLD(alpha=alpha,tVec=tVec,primaryOBF=pOBF,secondaryOBF=sOBF,initIntvl=initIntvl);
  }
  return(bdns);
}
# End of function secondaryBoundaryVec
#

#
# Function 17
#
# function refinedBoundary
#
#
#' Summarize Primary and Refined Secondary Boundaries, Nominal Significance
#'
#' Primary boundaries, refined secondary boundaries, and nominal significance for the secondary endpoint are listed.
#'
#' @author Jiangtao Gou
#' @param alpha type I error probability.
#' @param tVec vector of relative information levels. The last element in the vector is 1.
#' @param pOBF type of primary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param sOBF type of secondary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param LanDeMets type of boundary, \code{TRUE} is the error spending approach, \code{FALSE} is the original approach.
#' @param digits number of digits after decimal point for primary and secondary boundaries.
#' @return a result list including primary boundary, refined secondary boundary, and the nominal significance for the secondary endpoint.
#'
#' @details
#' This function gives a list including primary boundary, refined secondary boundary, and the nominal significance for the secondary endpoint.
#' The number of digits for the nominal significance depends on parameter \code{alpha}.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#'
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' result <- refinedBoundary(alpha=0.05,tVec=c(0.2,0.6,1))
#' result$primaryBoundary
#' result$secondaryBoundary
#' result$nomialSignificance
#'
#' @references
#'  Glimm, E., Maurer, W., and Bretz, F. (2010). Hierarchical testing of multiple endpoints in group-sequential trials. \emph{Statistics in Medicine} \bold{29}, 219-228.
#'
#'  Hung, H. M. J., Wang, S.-J., and O'Neill, R. (2007). Statistical considerations for testing multiple endpoints in group sequential or adaptive clinical trials. \emph{Journal of Biopharmaceutical Statistics} \bold{17}, 1201-1210.
#'
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Mehta, C. R., and Liu, L. (2010). Testing a primary and a secondary endpoint in a group sequential design. \emph{Biometrics} \bold{66}, 1174-1184.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48
#'
refinedBoundary <- function (alpha,tVec,pOBF=TRUE,sOBF=FALSE,LanDeMets=FALSE,digits=2) {
  #
  initIntvl=c(0.8,8);
  pd <- primaryBoundaryVec(alpha=alpha,tVec=tVec,OBF=pOBF,LanDeMets=LanDeMets,digits=10,printOut=FALSE,initIntvl=initIntvl);
  bdns <- secondaryBoundaryVec(alpha=alpha,tVec=tVec,pOBF=pOBF,sOBF=sOBF,LanDeMets=LanDeMets,initIntvl=initIntvl);
  #
  rawlist <- list("primaryBoundary" = pd, "secondaryBoundary" = bdns$secondaryBoundary, "nomialSignificance" = bdns$nomialSignificance)
  dgt = digits;
  rpd <- round(pd, dgt);
  rsd <- round(bdns$secondaryBoundary, dgt);
  nsdgt <- 3+round(log10(1/alpha));
  nsdgt <- max(dgt, nsdgt);
  rns <- round(bdns$nomialSignificance, nsdgt);
  resultlist <- list("primaryBoundary" = rpd, "secondaryBoundary" = rsd, "nomialSignificance" = rns)
  return(resultlist)
}
# End of function refinedBoundary
#

#
# Function 18
#
# function psbTeXtable
#
#' Summarize Primary and Refined Secondary Boundaries in a TeX table
#'
#' Primary boundaries and refined secondary boundaries are listed in a TeX table.
#'
#' @author Jiangtao Gou
#' @author Fengqing (Zoe) Zhang
#' @param alpha type I error probability.
#' @param tVec vector of relative information levels. The last element in the vector is 1.
#' @param pOBF type of primary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param sOBF type of secondary boundary, \code{TURE} is the O'Brien-Fleming boundary, \code{FALSE} is the Pocock boundary.
#' @param LanDeMets type of boundary, \code{TRUE} is the error spending approach, \code{FALSE} is the original approach.
#' @param digits number of digits after decimal point to display in the table.
#' @return a TeX format table including both primary boundary and refined secondary boundary.
#'
#' @details
#' This function gives a TeX format table including both primary boundary and refined secondary boundary.
#' The number of digits after decimal point can be specified through parameter \code{digits}.
#'
#' @export
#' @import mvtnorm
#' @import stats
#' @import ldbounds
#' @import xtable
#'
#' @examples
#' require(mvtnorm)
#' require(ldbounds)
#' require(xtable)
#' psbTeXtable(alpha=0.025,tVec=c(1/2,3/4,1),pOBF=TRUE,sOBF=FALSE,LanDeMets=FALSE)
#'
#' @references
#'  Glimm, E., Maurer, W., and Bretz, F. (2010). Hierarchical testing of multiple endpoints in group-sequential trials. \emph{Statistics in Medicine} \bold{29}, 219-228.
#'
#'  Hung, H. M. J., Wang, S.-J., and O'Neill, R. (2007). Statistical considerations for testing multiple endpoints in group sequential or adaptive clinical trials. \emph{Journal of Biopharmaceutical Statistics} \bold{17}, 1201-1210.
#'
#'  Jennison, C. and Turnbull, B. W. (2000). \emph{Group Sequential Methods with Applications to Clinical Trials}. Chapman and Hall/CRC, New York.
#'
#'  Lan, K. K. G., and Demets, D. L. (1983). Discrete sequential boundaries for clinical trials. \emph{Biometrika} \bold{70}, 659-663.
#'
#'  O'Brien, P. C., and Fleming, T. R. (1979). A multiple testing procedure for clinical trials. \emph{Biometrics} \bold{35}, 549-556.
#'
#'  Pocock, S. J. (1977). Group sequential methods in the design and analysis of clinical trials. \emph{Biometrika} \bold{64}, 191-199.
#'
#'  Tamhane, A. C., Mehta, C. R., and Liu, L. (2010). Testing a primary and a secondary endpoint in a group sequential design. \emph{Biometrics} \bold{66}, 1174-1184.
#'
#'  Tamhane, A. C., Gou, J., Jennison, C., Mehta, C. R., and Curto, T. (2018). A gatekeeping procedure to test a primary and a secondary endpoint in a group sequential design with multiple interim looks. \emph{Biometrics}, 74, 40-48.
#'
psbTeXtable <- function (alpha,tVec,pOBF=TRUE,sOBF=FALSE,LanDeMets=FALSE,digits=2) {
  #
  result <- refinedBoundary(alpha=alpha,tVec=tVec,pOBF=pOBF,sOBF=sOBF,LanDeMets=LanDeMets,digits=digits);
  psb <- data.frame(result$primaryBoundary, result$secondaryBoundary);
  colnames(psb) <- c("Primary Boundary", "Refined Secondary Boundary");
  return(xtable::xtable(psb,label = 'tab:psb',
               caption = 'Primary Boundary and Refined Secondary Boundary', digits=digits));
}
# End of function psbTeXtable
#

##########

Try the gsrsb package in your browser

Any scripts or data that you put into this service are public.

gsrsb documentation built on July 9, 2023, 6:02 p.m.