Nothing
#' Generate operating characteristics of phase I trials single-drug trials in multiple simulations
#'
#' Based on the toxicity outcomes, this function is used to perform multiple simulations for phase I single-drug trials and obtain relevant operating characteristics.
#'
#' @usage CFO.oc(nsimu = 5000, design, target, p.true, init.level = 1, ncohort, cohortsize,
#' assess.window = NA, tte.para = NA, accrual.rate = NA, accrual.dist = NA,
#' prior.para = list(alp.prior = target, bet.prior = 1 - target),
#' cutoff.eli = 0.95, early.stop = 0.95, seeds = NULL)
#'
#' @param nsimu the total number of trials to be simulated. The default value is 5000.
#' @param design option for selecting different designs, which can be set as \code{'CFO'}, \code{'aCFO'}, \code{'rCFO'},
#' \code{'TITE-CFO'}, \code{'TITE-aCFO'}, \code{'fCFO'}, \code{'f-aCFO'}, \code{'bCFO'},
#' and \code{'b-aCFO'}. Specifically, \code{'bCFO'} refers to the benchmark CFO design,
#' and \code{'b-aCFO'} denotes the benchmark aCFO design.
#' @param target the target DLT rate.
#' @param p.true the true DLT rates under the different dose levels.
#' @param init.level the dose level assigned to the first cohort. The default value \code{init.level} is 1.
#' @param ncohort the total number of cohorts.
#' @param cohortsize the number of patients of each cohort.
#' @param assess.window the maximal assessment window size. \code{NA} should be assigned if the design without late-oneset outcomes.
#' @param tte.para the parameter related with the distribution of the time to DLT events. The time to DLT is sampled from a Weibull
#' distribution, with \code{tte.para} representing the proportion of DLTs occurring within the first half of the
#' assessment window. \code{NA} should be assigned if the design without late-oneset outcomes.
#' @param accrual.rate the accrual rate, i.e., the number of patients accrued per unit time. \code{NA} should be assigned
#' if the design without late-onset outcomes.
#' @param accrual.dist the distribution of the arrival times of patients. When \code{accrual.dist = 'fix'}, it corresponds to all
#' patients in each cohort arriving simultaneously at a given accrual rate. When \code{accrual.dist = 'unif'},
#' it corresponds to a uniform distribution, and when \code{accrual.dist = 'exp'}, it corresponds to an
#' exponential distribution. \code{NA} should be assigned if the design without late-oneset outcomes.
#' @param prior.para the prior parameters for a beta distribution, where set as \code{list(alp.prior = target, bet.prior = 1 - target)}
#' by default, \code{alp.prior} and \code{bet.prior} represent the parameters of the prior distribution for
#' the true DLT rate at any dose level. This prior distribution is specified as Beta(\code{alpha.prior}, \code{beta.prior}).
#' @param cutoff.eli the cutoff to eliminate overly toxic doses for safety. We recommend
#' the default value of \code{cutoff.eli = 0.95} for general use.
#' @param early.stop the threshold value for early stopping. The default value \code{early.stop = 0.95}
#' generally works well.
#' @param seeds a vector of random seeds for each simulation, for example, \code{seeds = 1:nsimu} (default is \code{NULL}).
#'
#' @note The operating characteristics are generated by simulating multiple single-drug trials under the
#' pre-specified true toxicity probabilities of the investigational doses. The choice of which design to execute
#' is determined by setting the \code{design} argument. Some time-related arguments (\code{assess.window}, \code{accrual.rate},
#' \code{tte.para}, and \code{accrual.dist}) need to be set as values only when running a design that can handle late-onset
#' toxicities; otherwise, they default to \code{NA}.\cr
#' Additionally, in the example, we set \code{nsimu = 5} for testing time considerations. In reality, \code{nsimu}
#' is typically set to 5000 to ensure the accuracy of the results.
#'
#' @return The \code{CFO.oc()} function returns basic setup of ($simu.setup) and the operating
#' characteristics of the design: \cr
#' \itemize{
#' \item p.true: the true DLT rates under the different dose levels.
#' \item selpercent: the selection percentage at each dose level.
#' \item npatients: the averaged number of patients treated at each dose level in one simulation.
#' \item ntox: the averaged number of toxicity observed at each dose level in one simulation.
#' \item MTDsel: the percentage of correct selection of the MTD.
#' \item MTDallo: the percentage of patients allocated to the MTD.
#' \item oversel: the percentage of selecting a dose above the MTD.
#' \item overallo: the percentage of allocating patients at dose levels above the MTD.
#' \item averDLT: the percentage of the patients suffering DLT.
#' \item averdur: the average trial duration if trials with late-onset toxicities.
#' \item percentstop: the percentage of early stopping without selecting the MTD.
#' \item simu.setup: the parameters for the simulation set-up.
#' }
#'
#' @author Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
#'
#' @references Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
#' \emph{Statistical Methods in Medical Research}, 31(6), 1051-1066. \cr
#' Jin H, Yin G (2023). Time‐to‐event calibration‐free odds design: A robust efficient design for
#' phase I trials with late‐onset outcomes. \emph{Pharmaceutical Statistics}. 22(5), 773–783.\cr
#' Yin G, Zheng S, Xu J (2013). Fractional dose-finding methods with late-onset toxicity in
#' phase I clinical trials. \emph{Journal of Biopharmaceutical Statistics}, 23(4), 856-870.\cr
#' Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
#' in phase I clinical trials. \emph{Statistics in Medicine}, 43(17), 3210-3226.
#'
#' @importFrom dplyr transmute
#' @import pbapply
#' @export
#'
#' @examples
#' ## setting
#' nsimu <- 5; target <- 0.2; ncohort <- 10; cohortsize <- 3; init.level <- 1
#' p.true <- c(0.01, 0.07, 0.20, 0.35, 0.50, 0.65, 0.80)
#' prior.para = list(alp.prior = target, bet.prior = 1 - target)
#' assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif'
#'
#'
#' ## get the operating characteristics for 5 simulations using the f-aCFO design
#' faCFOoc <- CFO.oc (nsimu, design='f-aCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window, tte.para, accrual.rate, accrual.dist, seeds = 1:nsimu)
#' summary(faCFOoc)
#' plot(faCFOoc)
#'
#' \donttest{
#' # This test may take longer than 5 seconds to run
#' # It is provided for illustration purposes only
#' # Users can run this code directly
#'
#' ## get the operating characteristics for 5 simulations using the CFO design
#' CFOoc <- CFO.oc (nsimu, design = 'CFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window = NA, tte.para = NA, accrual.rate = NA, accrual.dist = NA, seeds = 1:nsimu)
#' summary(CFOoc)
#' plot(CFOoc)
#'
#' ## get the operating characteristics for 5 simulations using the aCFO design
#' aCFOoc <- CFO.oc (nsimu, design = 'aCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window = NA, tte.para = NA, accrual.rate = NA, accrual.dist = NA, seeds = 1:nsimu)
#' summary(aCFOoc)
#' plot(aCFOoc)
#'
#' ## get the operating characteristics for 5 simulations using the rCFO design
#' rCFOoc <- CFO.oc (nsimu, design = 'rCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window = NA, tte.para = NA, accrual.rate = NA, accrual.dist = NA, seeds = 1:nsimu)
#' summary(rCFOoc)
#' plot(rCFOoc)
#'
#' ## get the operating characteristics for 5 simulations using the pCFO design
#' pCFOoc <- CFO.oc (nsimu, design = 'pCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window = NA, tte.para = NA, accrual.rate = NA, accrual.dist = NA, seeds = 1:nsimu)
#' summary(pCFOoc)
#' plot(pCFOoc)
#'
#' ## get the operating characteristics for 5 simulations using the TITE-CFO design
#' TITECFOoc <- CFO.oc (nsimu, design = 'TITE-CFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window, tte.para, accrual.rate, accrual.dist, seeds = 1:nsimu)
#' summary(TITECFOoc)
#' plot(TITECFOoc)
#' ## get the operating characteristics for 5 simulations using the TITE-aCFO design
#' TITEaCFOoc <- CFO.oc (nsimu, design = 'TITE-aCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window, tte.para, accrual.rate, accrual.dist, seeds = 1:nsimu)
#' summary(TITEaCFOoc)
#' plot(TITEaCFOoc)
#' ## get the operating characteristics for 5 simulations using the fCFO design
#' fCFOoc <- CFO.oc (nsimu, design = 'fCFO', target, p.true, init.level, ncohort, cohortsize,
#' assess.window, tte.para, accrual.rate, accrual.dist, seeds = 1:nsimu)
#' summary(fCFOoc)
#' plot(fCFOoc)
#' }
CFO.oc <- function(nsimu=5000, design, target, p.true, init.level=1, ncohort, cohortsize,
assess.window=NA, tte.para=NA, accrual.rate=NA, accrual.dist=NA,
prior.para=list(alp.prior=target, bet.prior=1-target),
cutoff.eli=0.95, early.stop=0.95, seeds = NULL){
###############################################################################
###############define the functions used for main function#####################
###############################################################################
MTD.level <- function(phi, p.true){
if (p.true[1]>phi+0.1){
MTD <- 99
return(MTD)
}
MTD <- which.min(abs(phi - p.true))
return(MTD)
}
###############################################################################
############################MAIN DUNCTION######################################
###############################################################################
run.fn <- function(i){
if (design == 'CFO' || design == 'aCFO' || design == 'rCFO' || design == 'pCFO'){
res <- CFO.simu(design, target, p.true, init.level, ncohort, cohortsize, prior.para,
cutoff.eli, early.stop, seed = seeds[i])
}else{
res <- lateonset.simu(design, target, p.true, init.level, ncohort, cohortsize,
assess.window, tte.para, accrual.rate, accrual.dist, prior.para = prior.para,
cutoff.eli = cutoff.eli, early.stop = early.stop, seed = seeds[i])
}
ress <- list(
res=res,
paras=list(p.true=p.true,
mtd=tmtd,
prior.para=prior.para,
target=target,
ncohort=ncohort,
cohortsize=cohortsize)
)
return(ress)
}
tmtd <- MTD.level(target, p.true)
results <- pblapply(1:nsimu, run.fn)
results_nopara <- lapply(1:nsimu, function(i)results[[i]]$res)
ndose <- length(results_nopara[[1]]$npatients)
Perc <- rep(0, ndose)
nPatients <- rep(0, ndose); nTox <- rep(0, ndose)
sumPatients <- 0; sumTox <- 0
nonErrStops <- 0
MTDsel <- 0; MTDallo <- 0; oversel <- 0; overallo <- 0
totaltime <- 0
for (res in results_nopara){
if (res$MTD != 99){
nonErrStops <- nonErrStops + 1
Perc[res$MTD] <- Perc[res$MTD] + 1
oversel <- oversel + sum(res$MTD>tmtd)
if (tmtd==ndose){
overallo <- overallo
}else{
overallo <- overallo + sum(res$npatients[(tmtd+1):ndose])
}
}
if (!is.null(res$totaltime)){
totaltime <- totaltime + res$totaltime
}
MTDsel <- MTDsel + sum(res$MTD==tmtd)
MTDallo <- MTDallo + res$npatients[tmtd]
sumTox <- sumTox + sum(res$ntox)
sumPatients <- sumPatients + sum(res$npatients)
nPatients <- nPatients + res$npatients
nTox <- res$ntox + nTox
}
selpercent <- Perc/nsimu
MTDsel <- MTDsel/nsimu
MTDallo <- MTDallo/sumPatients
oversel <- oversel/nsimu
overallo <- overallo/sumPatients
averDLT <- sumTox/sumPatients
errStop <- nsimu-nonErrStops
if (design == 'CFO' || design == 'aCFO' || design == 'rCFO' ){
out <- list(p.true=p.true, selpercent=selpercent, npatients=nPatients/nsimu, ntox=nTox/nsimu,
MTDsel=MTDsel, MTDallo=MTDallo, oversel=oversel,
overallo=overallo, averDLT=averDLT, percentstop=errStop/nsimu,
simu.setup = data.frame(target = target,ncohort = ncohort,
cohortsize = cohortsize, design = design, nsimu = nsimu))
}else{
out <- list(p.true=p.true, selpercent=selpercent, npatients=nPatients/nsimu, ntox=nTox/nsimu,
MTDsel=MTDsel, MTDallo=MTDallo, oversel=oversel,
overallo=overallo, averDLT=averDLT, averdur = totaltime/nsimu, percentstop=errStop/nsimu,
simu.setup = data.frame(target = target,ncohort = ncohort,
cohortsize = cohortsize, design = design, nsimu = nsimu))
}
class(out) <- c("cfo_oc","cfo")
return(out)
}
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.