Title: | CFO-Type Designs in Phase I/II Clinical Trials |
---|---|
Description: | In phase I clinical trials, the primary objective is to ascertain the maximum tolerated dose (MTD) corresponding to a specified target toxicity rate. The subsequent phase II trials are designed to examine the potential efficacy of the drug based on the MTD obtained from the phase I trials, with the aim of identifying the optimal biological dose (OBD). The 'CFO' package facilitates the implementation of dose-finding trials by utilizing calibration-free odds type (CFO-type) designs. Specifically, it encompasses the calibration-free odds (CFO) (Jin and Yin (2022) <doi:10.1177/09622802221079353>), randomized CFO (rCFO), precision CFO (pCFO), two-dimensional CFO (2dCFO) (Wang et al. (2023) <doi:10.3389/fonc.2023.1294258>), time-to-event CFO (TITE-CFO) (Jin and Yin (2023) <doi:10.1002/pst.2304>), fractional CFO (fCFO), accumulative CFO (aCFO), TITE-aCFO, and f-aCFO (Fang and Yin (2024) <doi: 10.1002/sim.10127>). It supports phase I/II trials for the CFO design and only phase I trials for the other CFO-type designs. The ‘CFO' package accommodates diverse CFO-type designs, allowing users to tailor the approach based on factors such as dose information inclusion, handling of late-onset toxicity, and the nature of the target drug (single-drug or drug-combination). The functionalities embedded in 'CFO' package include the determination of the dose level for the next cohort, the selection of the MTD for a real trial, and the execution of single or multiple simulations to obtain operating characteristics. Moreover, these functions are equipped with early stopping and dose elimination rules to address safety considerations. Users have the flexibility to choose different distributions, thresholds, and cohort sizes among others for their specific needs. The output of the 'CFO' package can be summary statistics as well as various plots for better visualization. An interactive web application for CFO is available at the provided URL. |
Authors: | Jialu Fang [aut, cre], Ninghao Zhang [aut], Wenliang Wang [aut], Guosheng Yin [aut] |
Maintainer: | Jialu Fang <[email protected]> |
License: | GPL-2 |
Version: | 2.2.0 |
Built: | 2024-11-16 12:46:10 UTC |
Source: | CRAN |
In the aCFO design for phase I trials, the function is used to determine the dose movement based on the toxicity outcomes of the enrolled cohorts.
aCFO.next(target, ays, ans, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
aCFO.next(target, ays, ans, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
target |
the target DLT rate. |
ays |
the cumulative numbers of DLTs observed in patients for all dose levels. |
ans |
the cumulative numbers of patients for all dose levels. |
currdose |
the current dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
The aCFO design is an extension of the CFO design. It integrates dose information from all positions (ranging from the lowest to the highest dose levels) into the decision-making process of the trial. Before assigning the dose level for a new cohort, aCFO compares the evidence from the current dose level with all doses to its left and right. In contrast, the original CFO design makes dose allocation by examining one dose level above and one below the current dose level. Consequently, the aCFO design enhances the utilization of information while maintaining the characteristics of the CFO design (model-free and calibration-free). Additionally, the aCFO design preserves the same early stopping and dose elimination criteria as the CFO design.
The aCFO.next()
function returns a list object comprising the following elements:
target: the target DLT rate.
ays: the cumulative counts of DLTs observed at all dose levels.
ans: the cumulative counts of patients treated at all dose levels.
decision: the decision in the aCFO design, where left
, stay
, and right
represent the
movement directions, and stop
indicates stopping the experiment.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort. nextdose = 99
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which position experiences over-toxicity. The dose level indicated by
overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that the
occurrence of over-toxicity did not happen.
toxprob: the expected toxicity probability, , at all dose
levels, where
,
, and
is the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
NA
indicates that there
are no patients at the corresponding dose level.
The dose level indicated by overtox
and all the dose levels above experience over-toxicity, and these dose levels will be eliminated.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine, 43(17), 3210-3226.
## determine the dose level for the next cohort of new patients ays <- c(0, 0, 1, 0, 0, 0, 0); ans <- c(3, 3, 6, 0, 0, 0, 0) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 3, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision) ays <- c(3, 0, 0, 0, 0, 0, 0); ans <- c(3, 0, 0, 0, 0, 0, 0) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 1, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision) ays <- c(0, 0, 0, 0, 0, 0, 3); ans <- c(3, 3, 3, 3, 3, 3, 3) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 7, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision)
## determine the dose level for the next cohort of new patients ays <- c(0, 0, 1, 0, 0, 0, 0); ans <- c(3, 3, 6, 0, 0, 0, 0) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 3, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision) ays <- c(3, 0, 0, 0, 0, 0, 0); ans <- c(3, 0, 0, 0, 0, 0, 0) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 1, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision) ays <- c(0, 0, 0, 0, 0, 0, 3); ans <- c(3, 3, 3, 3, 3, 3, 3) decision <- aCFO.next(target = 0.2, ays = ays, ans = ans, currdose = 7, prior.para = list(alp.prior = 0.2, bet.prior = 0.8)) summary(decision)
In the CFO design for phase I trials, the function is used to determine the dose movement based on the toxicity outcomes of the enrolled cohorts.
CFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
CFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
target |
the target DLT rate. |
cys |
the cumulative numbers of DLTs observed at the left, current, and right dose levels. |
cns |
the cumulative numbers of patients treated at the left, current, and right dose levels. |
currdose |
the current dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
The CFO design determines the dose level for the next cohort by assessing evidence from the current
dose level and its adjacent levels. This evaluation is based on odds ratios denoted as , where
represents left, current (central), and right dose levels. Additionally, we define
.
The ratio
indicates the inclination for de-escalation, while
quantifies the tendency for escalation. Threshold values
and
are chosen to
minimize the probability of making incorrect decisions. The decision process is summarized in Table 1
of Jin and Yin (2022).
The early stopping and dose elimination rules are implemented to ensure patient safety. If the data suggest excessive
toxicity at the current dose level, we exclude that dose level and those higher levels. If the lowest dose level is overly toxic,
the trial will be terminated according to the early stopping rule.
The CFO.next()
function returns a list object comprising the following elements:
target: the target DLT rate.
cys: the cumulative counts of DLTs observed at the left, current, and right dose levels.
cns: the cumulative counts of patients treated at the left, current, and right dose levels.
decision: the decision in the CFO design, where left
, stay
, and right
represent the
movement directions, and stop
indicates stopping the experiment.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort. nextdose = 99
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which positions experience over-toxicity. The dose level indicated
by overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that
the occurrence of over-toxicity did not happen.
toxprob: the expected toxicity probability, , at the left, current, and
right dose levels, where
,
, and
is the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
NA
indicates that there
are no patients at the corresponding dose level.
When the current dose level is the lowest or highest (i.e., at the boundary), the parts in cys
and
cns
where there is no data are filled with NA
.
The dose level indicated by overtox
and all the dose levels above experience over-toxicity, and these dose levels will be eliminated.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials. Statistical Methods in Medical Research, 31(6), 1051-1066.
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- CFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
Based on the toxicity outcomes, this function is used to perform multiple simulations for phase I single-drug trials and obtain relevant operating characteristics.
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)
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)
nsimu |
the total number of trials to be simulated. The default value is 5000. |
design |
option for selecting different designs, which can be set as |
target |
the target DLT rate. |
p.true |
the true DLT rates under the different dose levels. |
init.level |
the dose level assigned to the first cohort. The default value |
ncohort |
the total number of cohorts. |
cohortsize |
the number of patients of each cohort. |
assess.window |
the maximal assessment window size. |
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 |
accrual.rate |
the accrual rate, i.e., the number of patients accrued per unit time. |
accrual.dist |
the distribution of the arrival times of patients. When |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
seeds |
a vector of random seeds for each simulation, for example, |
The CFO.oc()
function returns basic setup of ($simu.setup) and the operating
characteristics of the design:
p.true: the true DLT rates under the different dose levels.
selpercent: the selection percentage at each dose level.
npatients: the averaged number of patients treated at each dose level in one simulation.
ntox: the averaged number of toxicity observed at each dose level in one simulation.
MTDsel: the percentage of correct selection of the MTD.
MTDallo: the percentage of patients allocated to the MTD.
oversel: the percentage of selecting a dose above the MTD.
overallo: the percentage of allocating patients at dose levels above the MTD.
averDLT: the percentage of the patients suffering DLT.
averdur: the average trial duration if trials with late-onset toxicities.
percentstop: the percentage of early stopping without selecting the MTD.
simu.setup: the parameters for the simulation set-up.
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 design
argument. Some time-related arguments (assess.window
, accrual.rate
,
tte.para
, and accrual.dist
) need to be set as values only when running a design that can handle late-onset
toxicities; otherwise, they default to NA
.
Additionally, in the example, we set nsimu = 5
for testing time considerations. In reality, nsimu
is typically set to 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Jin H, Yin G (2023). Time‐to‐event calibration‐free odds design: A robust efficient design for
phase I trials with late‐onset outcomes. Pharmaceutical Statistics. 22(5), 773–783.
Yin G, Zheng S, Xu J (2013). Fractional dose-finding methods with late-onset toxicity in
phase I clinical trials. Journal of Biopharmaceutical Statistics, 23(4), 856-870.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine, 43(17), 3210-3226.
## 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) # 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)
## 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) # 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)
Select the maximum tolerated dose (MTD) when the real single-drug trials is completed
CFO.selectmtd(target, npts, ntox, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, verbose = TRUE)
CFO.selectmtd(target, npts, ntox, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, verbose = TRUE)
target |
the target DLT rate. |
npts |
a vector containing the number of patients treated at each dose level. |
ntox |
a vector containing the number of patients who experienced DLT at each dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
verbose |
set |
CFO.selectmtd()
selects the MTD based on isotonic estimates of toxicity
probabilities. CFO.selectmtd()
selects as the MTD dose , for which the
isotonic estimate of the DLT rate is closest to the target. If there
are ties, we select from the ties the highest dose level when the estimate
of the DLT rate is smaller than the target, or the lowest dose level
when the estimate of the DLT rate is greater than the target. The
isotonic estimates are obtained by the pooled-adjacent-violators algorithm
(PAVA).
CFO.selectmtd()
returns
target: the target DLT rate.
MTD: the selected MTD. MTD = 99
indicates that all tested doses are overly toxic.
p_est: the isotonic estimate of the DLT probablity at each dose and associated credible interval.
p_est = NA
if all tested doses are overly toxic.
p_overdose: the probability of overdosing defined as .
p_overdose = NA
if all tested doses are overly toxic.
The MTD selection and dose escalation/de-escalation rule are two independent components of the trial design. Isotonic regression is employed to select the MTD after the completion of the trial. When appropriate, another dose selection procedure (e.g., based on a fitted logistic model) can be used to select the MTD after the completion of the trial using the CFO-type design.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Bril G, Dykstra R, Pillers C, Robertson T (1984). Algorithm AS 206: Isotonic regression in two independent variables.
Journal of the Royal Statistical Society. Series C (Applied Statistics), 33(3), 352–357.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine.
### select the MTD for the CFO-type single-drug trial n <- c(3,3,27,3,0,0,0) y <- c(0,0,4,2,0,0,0) selmtd <- CFO.selectmtd(target=0.2, npts=n, ntox=y) summary(selmtd) plot(selmtd)
### select the MTD for the CFO-type single-drug trial n <- c(3,3,27,3,0,0,0) y <- c(0,0,4,2,0,0,0) selmtd <- CFO.selectmtd(target=0.2, npts=n, ntox=y) summary(selmtd) plot(selmtd)
In the CFO, aCFO, rCFO, and pCFO designs for phase I trials, the function is used to conduct one single simulation and find the maximum tolerated dose (MTD).
CFO.simu(design, target, p.true, init.level = 1, ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
CFO.simu(design, target, p.true, init.level = 1, ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
design |
option for selecting different designs, which can be set as |
target |
the target DLT rate. |
p.true |
the true DLT rates under the different dose levels. |
init.level |
the dose level assigned to the first cohort. The default value |
ncohort |
the total number of cohorts. |
cohortsize |
the number of patients of each cohort. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
seed |
an integer to be set as the seed of the random number generator for reproducible results. The default value is set to |
The CFO.simu
function returns a list object comprising the following components:
target: the target DLT rate.
MTD: the selected MTD. MTD = 99
indicates that the simulation is terminated due to early stopping.
correct: a binary indicator of whether the recommended dose level matches the correct MTD (1 for yes). The correct MTD is the dose level at which the true DLT rate is closest to the target DLT rate.
npatients: the total number of patients allocated to all dose levels.
ntox: the total number of DLTs observed for all dose levels.
over.doses: a vector indicating whether each dose is overdosed or not (1 for yes).
cohortdose: a vector including the dose level assigned to each cohort.
ptoxic: the percentage of subjects assigned to dose levels with a DLT rate greater than the target.
patientDLT: a vector including the DLT outcome observed for each patient.
sumDLT: the total number of DLT observed.
earlystop: a binary indicator of whether the trial is early stopped (1 for yes).
p_est: the isotonic estimate of the DLT probablity at each dose and associated credible interval.
p_est = NA
if all tested doses are overly toxic.
p_overdose: p_overdose: the probability of overdosing defined as .
p_overdose = NA
if all tested doses are overly toxic.
The CFO.simu()
function is designed to conduct a single CFO, aCFO, rCFO or pCFO simulation. If design = 'CFO'
, it corresponds
to the CFO design. If design = 'aCFO'
, it corresponds to the aCFO design. If design = 'rCFO'
, it corresponds to the
rCFO design. If design = 'pCFO'
, it corresponds to the pCFO design.
The early stopping and dose elimination rules are incorporated into designs
to ensure patient safety and benefit. If there is substantial evidence indicating that the current dose level
exhibits excessive toxicity, we exclude the current dose level as well as higher dose levels from the trial. If the lowest dose level is overly toxic, the trial will be terminated
according to the early stopping rule. Upon the predefined maximum sample size is reached or the lowest dose
level is over-toxicity, the experiment is concluded, and the MTD is determined using isotonic regression.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine, 43(17), 3210-3226.
target <- 0.2; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.01, 0.07, 0.20, 0.35, 0.50, 0.65, 0.80) ### find the MTD for a single CFO simulation CFOtrial <- CFO.simu(design = 'CFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(CFOtrial) plot(CFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ### find the MTD for a single aCFO simulation aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(aCFOtrial) plot(aCFOtrial) ### find the MTD for a single rCFO simulation rCFOtrial <- CFO.simu(design = 'rCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(rCFOtrial) plot(rCFOtrial) #' ### find the MTD for a single pCFO simulation pCFOtrial <- CFO.simu(design = 'pCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(pCFOtrial) plot(pCFOtrial)
target <- 0.2; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.01, 0.07, 0.20, 0.35, 0.50, 0.65, 0.80) ### find the MTD for a single CFO simulation CFOtrial <- CFO.simu(design = 'CFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(CFOtrial) plot(CFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ### find the MTD for a single aCFO simulation aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(aCFOtrial) plot(aCFOtrial) ### find the MTD for a single rCFO simulation rCFOtrial <- CFO.simu(design = 'rCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(rCFOtrial) plot(rCFOtrial) #' ### find the MTD for a single pCFO simulation pCFOtrial <- CFO.simu(design = 'pCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(pCFOtrial) plot(pCFOtrial)
In the 2dCFO design for phase I trials, the function is used to determine the dose movement based on the toxicity outcomes of the enrolled cohorts.
CFO2d.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
CFO2d.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
target |
the target DLT rate. |
cys |
a matrix of the number of DLTs observed for each dose combination. |
cns |
a matrix of the number of patients allocated to each dose combination. |
currdose |
a vector of the current dose indices in the horizontal and vertical direction. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
seed |
an integer to be set as the seed of the random number generator for reproducible results. The default value is set to |
In the 2dCFO design, decision-making within the two-dimensional toxicity probability space is conducted by performing two independent one-dimensional CFO analyses along both the horizontal and vertical axes (Wang et al. 2023).
The CFO2d.next()
function returns a list with the following components:
target: the target DLT rate.
cys: a 3 by 3 matrix of the number of DLT observed for each dose combination at and around the current dose.
cns: a 3 by 3 matrix of the number of patients allocated to each dose combination at and around the current dose.
decision: a vector of length 2 representing the recommended decisions for vertical and horizontal
directions, and stop
indicates stopping the experiment.
currdose: the current dose combination.
nextdose: the recommended dose combination for the next cohort. nextdose = (99, 99)
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which positions experience over-toxicity. The dose level indicated
by overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that the
occurrence of over-toxicity did not happen.
When the current dose level is the lowest or highest (i.e., at the boundary), the parts in cys
and
cns
where there is no data are filled with NA
.
The dose level indicated by overtox
and all the dose levels above experience over-toxicity, and these dose levels will be eliminated.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Wang W, Jin H, Zhang Y, Yin G (2023). Two-dimensional calibration-free odds (2dCFO)
design for phase I drug-combination trials. Frontiers in Oncology, 13, 1294258.
cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3) decision <- CFO2d.next(target = 0.3, cys, cns, currdose = currdose, seed = 1) summary(decision) cns <- matrix(c(NA, NA, NA, NA, 6, 0, NA, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(NA, NA, NA, NA, 6, 0, NA, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(1,1) decision <- CFO2d.next(target = 0.3, cys, cns, currdose = currdose, seed = 1) summary(decision)
cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3) decision <- CFO2d.next(target = 0.3, cys, cns, currdose = currdose, seed = 1) summary(decision) cns <- matrix(c(NA, NA, NA, NA, 6, 0, NA, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(NA, NA, NA, NA, 6, 0, NA, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(1,1) decision <- CFO2d.next(target = 0.3, cys, cns, currdose = currdose, seed = 1) summary(decision)
Based on the toxicity outcomes, this function is used to conduct multiple simulations of phase I drug-combination trials and obtain relevant the operating characteristics.
CFO2d.oc(nsimu = 1000, target, p.true, init.level = c(1,1), ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seeds = NULL)
CFO2d.oc(nsimu = 1000, target, p.true, init.level = c(1,1), ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seeds = NULL)
nsimu |
the total number of trials to be simulated. The default value is 1000. |
target |
the target DLT rate. |
p.true |
a matrix representing the true DIL rates under the different dose levels. |
init.level |
a numeric vector of length 2 representing the initial dose level (default is |
ncohort |
the total number of cohorts. |
cohortsize |
the number of patients of each cohort. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of ( |
early.stop |
the threshold value for early stopping. The default value |
seeds |
A vector of random seeds for each simulation, for example, |
The CFO.oc()
function returns basic setup of ($simu.setup) and the operating
characteristics of the design:
p.true: the matrix of the true DLT rates under the different dose levels.
selpercent: the matrix of the selection percentage of each dose level.
npatients: a matrix of the averaged number of patients allocated to different doses in one simulation.
ntox: a matrix of the averaged number of DLT observed for different doses in one simulation.
MTDsel: the percentage of the correct selection of the MTD.
MTDallo: the averaged percentage of patients assigned to the target DLT rate.
oversel: the percentage of selecting a dose above the MTD.
overallo: the averaged percentage of patients assigned to dose levels with a DLT rate greater than the target.
averDLT: the averaged total number of DLTs observed.
percentstop: the percentage of early stopping without selecting the MTD.
simu.setup: the parameters for the simulation set-up.
In the example, we set nsimu = 10
for testing time considerations. In reality, nsimu
is typically set to 1000 or 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Wang W, Jin H, Zhang Y, Yin G (2023). Two-dimensional calibration-free odds (2dCFO)
design for phase I drug-combination trials. Frontiers in Oncology, 13, 1294258.
## Simulate a two-dimensional dose-finding trial with 20 cohorts of size 3 for 10 replications. p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 12; cohortsize <- 3 CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) summary(CFO2doc) plot(CFO2doc)
## Simulate a two-dimensional dose-finding trial with 20 cohorts of size 3 for 10 replications. p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 12; cohortsize <- 3 CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) summary(CFO2doc) plot(CFO2doc)
Select the maximum tolerated dose (MTD) when the real drug combination trials is completed
CFO2d.selectmtd(target, npts, ntox, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, verbose = TRUE)
CFO2d.selectmtd(target, npts, ntox, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, verbose = TRUE)
target |
the target DLT rate. |
npts |
a matrix containing the number of patients treated at each dose level. |
ntox |
a matrix containing the number of patients who experienced DLT at each dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
verbose |
set |
CFO2d.selectmtd()
selects the MTD based on isotonic estimates of toxicity
probabilities. CFO2d.selectmtd()
selects as the MTD dose , for which the
isotonic estimate of the DLT rate is closest to the target. If there
are ties, we select from the ties the highest dose level when the estimate
of the DLT rate is smaller than the target, or the lowest dose level
when the estimate of the DLT rate is greater than the target. The
isotonic estimates are obtained by the pooled-adjacent-violators algorithm
(PAVA).
CFO2d.selectmtd()
returns
target: the target DLT rate.
MTD: the selected MTD. MTD = (99, 99)
indicates that all tested doses are overly toxic.
p_est: the isotonic estimate of the DLT probablity at each dose and associated credible interval.
p_est = NA
if all tested doses are overly toxic.
p_est_CI: the credible interval for the isotonic estimate.
p_est_CI = NA
if all tested doses are overly toxic.
The MTD selection and dose escalation/deescalation rule are two independent components of the trial design. Isotonic regression is employed to select the MTD after the completion of the trial. When appropriate, another dose selection procedure (e.g., based on a fitted logistic model) can be used to select the MTD after the completion of the trial using the 2dCFO design.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Wang W, Jin H, Zhang Y, Yin G (2023). Two-dimensional calibration-free odds (2dCFO)
design for phase I drug-combination trials. Frontiers in Oncology, 13, 1294258.
Bril G, Dykstra R, Pillers C, Robertson T (1984). Algorithm AS 206: Isotonic regression in two independent variables.
Journal of the Royal Statistical Society. Series C (Applied Statistics), 33(3), 352–357.
ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) summary(selmtd) plot(selmtd)
ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) summary(selmtd) plot(selmtd)
In the 2dCFO design for phase I trials, the function is used to conduct one single simulation and find the maximum tolerated dose (MTD).
CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
target |
the target DLT rate. |
p.true |
a matrix representing the true DIL rates under the different dose levels. |
init.level |
the dose level assigned to the first cohort. The default value |
ncohort |
the total number of cohorts. |
cohortsize |
the number of patients of each cohort. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of ( |
early.stop |
the threshold value for early stopping. The default value |
seed |
an integer to be set as the seed of the random number generator for reproducible results. The default is set to |
The CFO2d.simu()
function simulates the operating characteristics of the 2dCFO design
in a dose-combination trial.
The early stopping and dose elimination rules are incorporated into the 2dCFO design
to ensure patient safety and benefit.
The CFO2d.simu()
function returns a list with the following components:
target: the target DLT rate.
MTD: a vector of length 2 representing the recommended dose level. MTD = (99, 99)
indicates that this trial is terminated due to early stopping.
correct: a binary indicator of whether the recommended dose level matches the correct MTD (1 for yes). The correct MTD is the dose level at which the true DLT rate is closest to the target DLT rate.
npatients: a matrix of the number of patients allocated to different doses.
ntox: a matrix of the number of DLT observed for different doses.
npercent: the percentage of patients assigned to the correct MTD.
over.doses: a matrix indicating whether each dose is overdosed or not (1 for yes).
cohortdose: the dose combination assigned to each cohort.
ptoxic: the percentage of subjects assigned to dose levels with a DLT rate greater than the target.
patientDLT: the DLT observed at each cohort.
sumDLT: the total number of DLT observed.
earlystop: a binary indicator of whether the trial is early stopped (1 for yes).
p_est: the isotonic estimate of the DLT probablity at each dose and associated credible interval.
p_est = NA
if all tested doses are overly toxic.
p_est_CI: the credible interval for the isotonic estimate.
p_est_CI = NA
if all tested doses are overly toxic.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Wang W, Jin H, Zhang Y, Yin G (2023). Two-dimensional calibration-free odds (2dCFO)
design for phase I drug-combination trials. Frontiers in Oncology, 13, 1294258.
## Simulate a two-dimensional dose-finding trial with 20 cohorts of size 3. p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 20; cohortsize <- 3 CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) summary(CFO2dtrial) plot(CFO2dtrial)
## Simulate a two-dimensional dose-finding trial with 20 cohorts of size 3. p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 20; cohortsize <- 3 CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) summary(CFO2dtrial) plot(CFO2dtrial)
In the CFO design for phase I/II trials, the function is used to determine the dose movement based on the toxicity outcomes and efficacy outcomes of the enrolled cohorts.
CFOeff.next(target, axs, ays, ans, currdose, prior.para=list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), cutoff.eli=0.95, early.stop=0.95, effearly.stop = 0.9, mineff)
CFOeff.next(target, axs, ays, ans, currdose, prior.para=list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), cutoff.eli=0.95, early.stop=0.95, effearly.stop = 0.9, mineff)
target |
the target DLT rate. |
axs |
the cumulative counts of efficacy outcomes at all dose levels. |
ays |
the cumulative counts of DLTs observed at all dose levels. |
ans |
the cumulative counts of patients treated at all dose levels. |
currdose |
the current dose level. |
prior.para |
the prior parameters for two beta distributions, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping due to overly toxic. The default value |
effearly.stop |
the threshold value for early stopping due to low efficacy. The trial would be terminated
early if |
mineff |
the lowest acceptable efficacy rate. |
The CFO design for phase I/II trials will determine admissible set through the dose escalation rules for the MTD. The current dose is set as
. If the decision is to de-escalate the dose, the set
will be
. If the decision is to stay at the
current dose, then the admissible set
will be
. If the decision is to escalate the dose, then
will be
. The dose level
for the next cohort will be selected from
by using the rule:
where
and
are the current data and the
efficacy probability for dose level
.
The CFOeff.next()
function returns a list object comprising the following elements:
target: the target DLT rate.
axs: the cumulative counts of efficacy outcomes at all dose levels.
ays: the cumulative counts of DLTs observed at all dose levels.
ans: the cumulative counts of patients treated at all dose levels.
decision: the decision in the CFO design, where de-escalation
, stay
, and escalation
represent the
movement directions of the dose level, stop_for_tox
indicates stopping the experiment because the lowest dose level
is overly toxic and stop_for_low_eff
indicates that all dose level in the admissible set shows low efficacy.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort. nextdose = 99
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which positions experience over-toxicity. The dose level indicated
by overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that
the occurrence of over-toxicity did not happen.
toxprob: the expected toxicity probability, , for doses in admissible set,
where
,
, and
are the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
effprob: the empirical probability of for doses in admissible set,
where
is efficacy probability at dose level
.
is the admissible set determined through
the dose escalation rules for the MTD and
is the current cumulative dataset.
admset: the admissible set . The dose level for the next cohort will be selected from
.
class: the phase of the trial.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
axs = c(3, 1, 7, 11, 26); ays = c(0, 0, 0, 0, 6); ans = c(6, 3, 12, 17, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 3, mineff = 0.3) summary(decision) #early stop for overly toxic axs = c(13, 11, 7, 11, 26); ays = c(25, 18, 12, 17, 26); ans = c(36, 23, 22, 27, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 1, mineff = 0.3) summary(decision) #early stop for low efficacy axs = c(0, 0, 0, 0, 0); ays = c(2, 1, 1, 1, 6); ans = c(36, 23, 22, 27, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 1, mineff = 0.3) summary(decision)
axs = c(3, 1, 7, 11, 26); ays = c(0, 0, 0, 0, 6); ans = c(6, 3, 12, 17, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 3, mineff = 0.3) summary(decision) #early stop for overly toxic axs = c(13, 11, 7, 11, 26); ays = c(25, 18, 12, 17, 26); ans = c(36, 23, 22, 27, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 1, mineff = 0.3) summary(decision) #early stop for low efficacy axs = c(0, 0, 0, 0, 0); ays = c(2, 1, 1, 1, 6); ans = c(36, 23, 22, 27, 36) target <- 0.4 decision <- CFOeff.next(target,axs,ays,ans,currdose = 1, mineff = 0.3) summary(decision)
Based on the toxicity outcomes and efficacy outcomes, this function is used to perform multiple simulations for phase I/II single-drug trials and obtain relevant operating characteristics.
CFOeff.oc(target, p.true=p.true, pE.true=pE.true, prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), init.level = 1, cohortsize=cohortsize, ncohort=ncohort, nsimu, cutoff.eli=0.95, early.stop=0.95, effearly.stop = 0.9, mineff, seeds = NULL)
CFOeff.oc(target, p.true=p.true, pE.true=pE.true, prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), init.level = 1, cohortsize=cohortsize, ncohort=ncohort, nsimu, cutoff.eli=0.95, early.stop=0.95, effearly.stop = 0.9, mineff, seeds = NULL)
target |
the target DLT rate. |
p.true |
the true DLT rates under the different dose levels. |
pE.true |
the true efficacy rates under the different dose levels. |
prior.para |
the prior parameters for two beta distributions, where set as |
init.level |
the dose level assigned to the first cohort. The default value |
cohortsize |
the number of patients in each cohort. |
ncohort |
the total number of cohorts. |
nsimu |
the total number of trials to be simulated. |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping due to overly toxic. The default value |
effearly.stop |
the threshold value for early stopping due to low efficacy. The trial would be terminated
early if |
mineff |
the lowest acceptable efficacy rate. |
seeds |
a vector of random seeds for each simulation, for example, |
The CFOeff.oc()
function returns a list object, which includes the basic setup (simu.setup
), comprising the following components:
p.true: the true DLT rates under the different dose levels.
pE.true: the true efficacy rates under the different dose levels.
selpercent: the selection percentage at each dose level.
npatients: the averaged number of patients treated at each dose level in one simulation.
ntox: the averaged number of toxicity observed at each dose level in one simulation.
neff: the averaged number of efficacy outcome at each dose level in one simulation.
OBDsel: the percentage of correct selection of the OBD.
OBDallo: the percentage of patients allocated to the OBD.
averDLT: the percentage of the patients suffering DLT.
avereff: the percentage of the patients with efficacy outcomes.
percentstop: the percentage of early stopping without selecting the OBD.
simu.setup: the parameters for the simulation set-up.
class: the phase of the trial.
In the example, we set nsimu = 3
for testing time considerations.
In reality, nsimu
is typically set as 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 12; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result) #earlystop for overly tox target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 12; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.75, 0.77, 0.81, 0.82, 0.86) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result) #earlystop for lower efficacy target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.001, 0.001, 0.001, 0.002, 0.003) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result)
target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 12; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result) #earlystop for overly tox target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 12; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.75, 0.77, 0.81, 0.82, 0.86) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result) #earlystop for lower efficacy target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; nsimu = 3; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.001, 0.001, 0.001, 0.002, 0.003) result <- CFOeff.oc (target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result) plot(result)
Select the optimal biological dose (OBD) when the real single-drug trials is completed
CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop)
CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop)
target |
the target DLT rate. |
txs |
the cumulative counts of efficacy outcomes at all dose levels. |
tys |
the cumulative counts of DLTs observed at all dose levels. |
tns |
the cumulative counts of patients treated at all dose levels. |
prior.para |
the prior parameters for two beta distributions, where set as |
mineff |
the lowest acceptable efficacy rate. |
effearly.stop |
the threshold value for early stopping due to low efficacy. The trial would be terminated
early if |
The CFOeff.selectobd()
function returns a list object comprising the following elements:
OBD: the selected OBD. OBD = 99
indicates that all tested doses are overly toxic or having low efficacy.
MTD: MTD here is get by using function CFO.selectmtd
. MTD is used as the upper bound of the admissible set.
OBD.probs: the probability that each dose level would be selected as OBD. The probability indicates that corresponds
to dose level
being the highest in the admissible set.
is efficacy probability correspond to dose level k here.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
target <- 0.3; mineff<- 0.3 txs <- c(3, 1, 7, 11, 26); tys <- c(0, 0, 0, 0, 6); tns <- c(6, 3, 12, 17, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result) ##Low efficacy target <- 0.3; mineff<- 0.3 txs = c(0, 0, 0, 0, 0); tys = c(2, 1, 1, 1, 6); tns = c(36, 23, 22, 27, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result) ##High toxicity target <- 0.3; mineff<- 0.3 txs = c(3, 1, 7, 11, 26); tys = c(36, 23, 22, 27, 36); tns = c(36, 23, 22, 27, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result)
target <- 0.3; mineff<- 0.3 txs <- c(3, 1, 7, 11, 26); tys <- c(0, 0, 0, 0, 6); tns <- c(6, 3, 12, 17, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result) ##Low efficacy target <- 0.3; mineff<- 0.3 txs = c(0, 0, 0, 0, 0); tys = c(2, 1, 1, 1, 6); tns = c(36, 23, 22, 27, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result) ##High toxicity target <- 0.3; mineff<- 0.3 txs = c(3, 1, 7, 11, 26); tys = c(36, 23, 22, 27, 36); tns = c(36, 23, 22, 27, 36) prior.para = list(alp.prior.eff = 0.5, bet.prior.eff = 0.5) effearly.stop <- 0.95 result <- CFOeff.selectobd(target, txs, tys, tns, prior.para, mineff, effearly.stop) summary(result)
In the CFO design for phase I/II trials, the function is used to conduct one single simulation and find the optimal biological dose (OBD).
CFOeff.simu(target, p.true, pE.true, ncohort=10, init.level=1, cohortsize=3, prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), cutoff.eli = 0.95, early.stop = 0.95, effearly.stop = 0.9, mineff, seed = NULL)
CFOeff.simu(target, p.true, pE.true, ncohort=10, init.level=1, cohortsize=3, prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5), cutoff.eli = 0.95, early.stop = 0.95, effearly.stop = 0.9, mineff, seed = NULL)
target |
the target DLT rate. |
p.true |
the true DLT rates under the different dose levels. |
pE.true |
the true efficacy rates under the different dose levels. |
ncohort |
the total number of cohorts. |
init.level |
the dose level assigned to the first cohort. The default value of |
cohortsize |
the number of patients of each cohort. |
prior.para |
the prior parameters for two beta distributions, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping due to overly toxic. The default value |
effearly.stop |
the threshold value for early stopping due to low efficacy. The trial would be terminated
early if |
mineff |
the lowest acceptable efficacy rate. |
seed |
an integer to be set as the seed of the random number generator for reproducible results. The default value is set to |
The CFOeff.simu
function returns a list object comprising the following components:
OBD: the selected OBD. OBD = 99
indicates that the simulation is terminated due to early stopping.
target: the target DLT rate.
npatients: the total number of patients allocated to all dose levels.
neff: the total number of efficacy outcomes for all dose levels.
ntox: the total number of DLTs observed for all dose levels.
pE.true: the true efficacy rates under the different dose levels.
p.true: the true DLT rates under the different dose levels.
cohortdose: a vector including the dose level assigned to each cohort.
ptoxic: the percentage of subjects assigned to dose levels with a DLT rate greater than the target.
patientDLT: a vector including the DLT outcome observed for each patient.
patienteff: a vector including the efficacy outcome observed for each patient.
over.doses: a vector indicating whether each dose is overdosed or not (1 for yes).
under.eff: a vector indicating whether the efficacy of each dose is lower than acceptable efficacy rate (1 for yes).
correct: a binary indicator of whether the recommended dose level matches the correct OBD (1 for yes). The correct OBD is the dose level in the admissible set with the upper bound being the correct MTD, which has the highest true efficacy probability.
OBDprob: the probability that each dose level would be selected as OBD. The probability indicates that corresponds
to dose level
being the highest in the admissible set.
is efficacy probability correspond to dose level k here.
sumDLT: the total number of DLT observed.
sumeff: the total number of efficacy outcome observed.
earlystop: a binary indicator of whether the trial is early stopped (1 for yes).
stopreason: the reason for earlystop. overly_toxic
represents the trial was terminated
beacuse all tested doses were overly toxic. low_efficacy
represents the trial was terminated
because all tested doses show low efficacy.
class: the phase of the trial.
The CFOeff.simu
function is designed to conduct a single CFO simulation for phase I/II trials. The dose elimination rule is the
same as the case in phase I (refer to the function CFO.simu
). As for early stopping rule, compared to the case of phase I, the rule
in this case further considers the efficacy data to terminate the trial early if none of the admissible dose levels show adequate
efficacious effect.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result) ### overly toxic target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.55, 0.57, 0.61, 0.62, 0.66) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result) ### low efficacy target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.001, 0.003, 0.004, 0.005, 0.006) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result)
target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result) ### overly toxic target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.55, 0.57, 0.61, 0.62, 0.66) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result) ### low efficacy target <- 0.30; mineff <- 0.30; cohortsize = 3; ncohort = 20; init.level = 1 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.001, 0.003, 0.004, 0.005, 0.006) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) plot(result)
and
in the calibration-free odds (CFO) designGenerate all the possible thresholds under different ,
and
gammatable(npatient, target, para.prior = list(alp.prior = target, bet.prior = 1 - target))
gammatable(npatient, target, para.prior = list(alp.prior = target, bet.prior = 1 - target))
npatient |
the numbers of patients involved in the trial. |
target |
the target DLT rate. |
para.prior |
the prior parameters for a beta distribution, where set as |
The gammatable()
function returns a list object comprising the following elements:
gammatb.left: the table of threshold under different
and
where
and
represent the number of patients at current dose level and left dose level.
gammatb.right: the table of threshold under different
and
where
and
represent the number of patients at current dose level and right dose level.
This function generate two matrices. gammatb.left
contains the threshold ,
and
gammatb.right
contains the threhold . For matrix
gammatb.left
, the row index represent the number of patients
at left dose level, and the column index represent the number of patients at current dose level. For matrix gammatb.right
, the row index represent the number of patients
at right dose level, and the column index represent the number of patients at current dose level.
For example, if you want to get the threshold in the case of
, you can reach it by
result$gammatb.left[13,12]
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials. Statistical Methods in Medical Research, 31(6), 1051-1066.
npatient <- 3; target <- 0.3 para.prior = list(alp.prior = target, bet.prior = 1 - target) result <- gammatable(npatient, target, para.prior) plot(result) #This example may cost you a long time to run npatient <- 30; target <- 0.3 para.prior = list(alp.prior = target, bet.prior = 1 - target) result <- gammatable(npatient, target, para.prior) plot(result)
npatient <- 3; target <- 0.3 para.prior = list(alp.prior = target, bet.prior = 1 - target) result <- gammatable(npatient, target, para.prior) plot(result) #This example may cost you a long time to run npatient <- 30; target <- 0.3 para.prior = list(alp.prior = target, bet.prior = 1 - target) result <- gammatable(npatient, target, para.prior) plot(result)
Based on the toxicity outcomes of the enrolled cohorts, the function is used to determine the next dose level in the CFO-type designs with late-onset toxicity for phase I trials, specifically, including time-to-event CFO (TITE-CFO) design, fractional CFO (fCFO) design, benchmark CFO design, time-to-event accumulative CFO (TITE-aCFO) design, fractional aCFO (f-aCFO) design, and benchmark aCFO design.
lateonset.next(design, target, ndose, currdose, assess.window, enter.times, dlt.times, current.t, doses, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
lateonset.next(design, target, ndose, currdose, assess.window, enter.times, dlt.times, current.t, doses, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
design |
option for selecting different designs, which can be set as |
target |
the target DLT rate. |
ndose |
the number of dose levels. |
currdose |
the current dose level. |
assess.window |
the maximal assessment window size. |
enter.times |
the time that each participant enters the trial. |
dlt.times |
the time to DLT for each subject in the trial. If no DLT occurs for a subject,
|
current.t |
the current time. |
doses |
the dose level for each subject in the trial. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
Late-onset outcomes commonly occur in phase I trials involving targeted agents or immunotherapies. The TITE
framework and fractional framework serve as two imputation methods to handle pending data
related to late-onset outcomes. This approach extends the CFO, and aCFO designs to integrate time information
for delayed outcomes, leading to the development of TITE-CFO, fCFO, TITE-aCFO, and f-aCFO designs.
In the TITE framework context, an assumption about the distribution of time to DLT must be pre-specified,
whereas the fractional framework does not require justification for a specific distribution of the time to
DLT. Consequently, fCFO, and f-aCFO adapt to a more diverse range of scenarios.
The function lateonset.next()
also provides the option to execute
the benchmark CFO and aCFO designs. These three methods await complete observation of toxicity outcomes for
the previous cohorts before determining the next dose assignment. This enhances precision but comes at the
expense of a prolonged trial duration.
The lateonset.next()
function returns
target: the target DLT rate.
decision: the decision in the CFO design, where left
, stay
, and right
represent the
movement directions, and stop
indicates stopping the experiment.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort.
overtox: the situation regarding which position experiences over-toxicity. The dose level indicated by
overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that the
occurrence of over-toxicity did not happen.
over.doses: a vector indicating whether the dose level (from the first to last dose level) is over-toxic or not (1 for yes).
toxprob: the expected toxicity probability, , at all dose
levels, where
,
, and
is the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
NA
indicates that there
are no patients at the corresponding dose level.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Jin H, Yin G (2023). Time‐to‐event calibration‐free odds design: A robust efficient design for
phase I trials with late‐onset outcomes. Pharmaceutical Statistics, 22(5), 773–783.
Yin G, Zheng S, Xu J (2013). Fractional dose-finding methods with late-onset toxicity in
phase I clinical trials. Journal of Biopharmaceutical Statistics, 23(4), 856-870.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine.
target <- 0.2; ndose <- 7 enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.66, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.610, 0, 2.98, 0, 0, 1.95, 0, 0, 1.48) current.t<- 9.41 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) ## determine the dose level for the next cohort using the TITE-CFO design decision <- lateonset.next(design = 'TITE-CFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the TITE-aCFO design decision <- lateonset.next(design = 'TITE-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the f-CFO design decision <- lateonset.next(design = 'fCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the f-aCFO design decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the benchmark CFO design decision <- lateonset.next(design = 'bCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the benchmark aCFO design decision <- lateonset.next(design='b-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision)
target <- 0.2; ndose <- 7 enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.66, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.610, 0, 2.98, 0, 0, 1.95, 0, 0, 1.48) current.t<- 9.41 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) ## determine the dose level for the next cohort using the TITE-CFO design decision <- lateonset.next(design = 'TITE-CFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the TITE-aCFO design decision <- lateonset.next(design = 'TITE-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the f-CFO design decision <- lateonset.next(design = 'fCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the f-aCFO design decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the benchmark CFO design decision <- lateonset.next(design = 'bCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision) ## determine the dose level for the next cohort using the benchmark aCFO design decision <- lateonset.next(design='b-aCFO', target, ndose, currdose = 4, assess.window = 3, enter.times, dlt.times, current.t, doses) summary(decision)
Based on the toxicity outcomes of the enrolled cohorts, the function is used to conduct one single simulation and find the maximum tolerated dose (MTD) for the CFO-type designs with late-onset toxicities for phase I trials, specifically, including time-to-event CFO (TITE-CFO) design, fractional CFO (fCFO) design, benchmark CFO design, time-to-event accumulative CFO (TITE-aCFO) design, fractional aCFO (f-aCFO) design, and benchmark aCFO design.
lateonset.simu(design, target, p.true, init.level = 1, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
lateonset.simu(design, target, p.true, init.level = 1, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed = NULL)
design |
option for selecting different designs, which can be set as |
target |
the target DLT rate. |
p.true |
the true DLT rates under the different dose levels. |
init.level |
the dose level assigned to the first cohort. The default value |
ncohort |
the total number of cohorts. |
cohortsize |
the number of patients of each cohort. |
assess.window |
the maximal assessment window size. |
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 |
accrual.rate |
the accrual.rate rate, i.e., the number of patients accrued per unit time. |
accrual.dist |
the distribution of the arrival times of patients. When |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
seed |
an integer to set as the seed of the random number generator for reproducible results. The default value is set to NULL. |
The lateonset.simu()
function returns a list object comprising the following components:
target: the target DLT rate.
MTD: the selected MTD. MTD = 99
indicates that this trial is terminated due to early stopping.
correct: a binary indicator of whether the recommended dose level matches the correct MTD (1 for yes). The correct MTD is the dose level at which the true DLT rate is closest to the target DLT rate.
npatients: the total number of patients allocated to all dose levels
ntox: the total number of DLTs observed for all dose levels.
over.doses: a vector indicating whether each dose is overdosed or not (1 for yes).
cohortdose: a vector including the dose level assigned to each cohort.
ptoxic: the percentage of subjects assigned to dose levels with a DLT rate greater than the target.
patientDLT: a vector including the DLT outcome observed for each patient.
sumDLT: the total number of DLT observed.
earlystop: a binary indicator of whether the trial is early stopped (1 for yes).
p_est: the isotonic estimate of the DLT probablity at each dose and associated credible interval.
p_est = NA
if all tested doses are overly toxic.
p_overdose: p_overdose: the probability of overdosing defined as .
p_overdose = NA
if all tested doses are overly toxic.
totaltime: the duration of the trial.
entertimes: the time that each participant enters the trial.
DLT.times: the time to DLT for each subject in the trial. If no DLT occurs for a certain subject,
DLT.times
is 0.
The early stopping and dose elimination rules are incorporated into the design to ensure patient safety and benefit.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials.
Statistical Methods in Medical Research, 31(6), 1051-1066.
Jin H, Yin G (2023). Time‐to‐event calibration‐free odds design: A robust efficient design for
phase I trials with late‐onset outcomes. Pharmaceutical Statistics. 22(5), 773–783.
Yin G, Zheng S, Xu J (2013). Fractional dose-finding methods with late-onset toxicity in
phase I clinical trials. Journal of Biopharmaceutical Statistics, 23(4), 856-870.
Fang J, Yin G (2024). Fractional accumulative calibration‐free odds (f‐aCFO) design for delayed toxicity
in phase I clinical trials. Statistics in Medicine.
target <- 0.2; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.01, 0.07, 0.20, 0.35, 0.50, 0.65, 0.80) assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## find the MTD for a single TITE-CFO simulation TITECFOtrial <- lateonset.simu (design = 'TITE-CFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(TITECFOtrial) plot(TITECFOtrial) ## find the MTD for a single TITE-aCFO simulation TITEaCFOtrial <- lateonset.simu (design = 'TITE-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(TITEaCFOtrial) plot(TITEaCFOtrial) ## find the MTD for a single fCFO simulation fCFOtrial <- lateonset.simu (design = 'fCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(fCFOtrial) plot(fCFOtrial) ## find the MTD for a single f-aCFO simulation faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(faCFOtrial) plot(faCFOtrial)
target <- 0.2; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.01, 0.07, 0.20, 0.35, 0.50, 0.65, 0.80) assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## find the MTD for a single TITE-CFO simulation TITECFOtrial <- lateonset.simu (design = 'TITE-CFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(TITECFOtrial) plot(TITECFOtrial) ## find the MTD for a single TITE-aCFO simulation TITEaCFOtrial <- lateonset.simu (design = 'TITE-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(TITEaCFOtrial) plot(TITEaCFOtrial) ## find the MTD for a single fCFO simulation fCFOtrial <- lateonset.simu (design = 'fCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(fCFOtrial) plot(fCFOtrial) ## find the MTD for a single f-aCFO simulation faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(faCFOtrial) plot(faCFOtrial)
In the pCFO design for phase I trials, the function is used to determine the dose movement based on the toxicity outcomes of the enrolled cohorts.
pCFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
pCFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95)
target |
the target DLT rate. |
cys |
the cumulative numbers of DLTs observed at the left, current, and right dose levels. |
cns |
the cumulative numbers of patients treated at the left, current, and right dose levels. |
currdose |
the current dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
The pCFO.next()
function returns a list object comprising the following elements:
target: the target DLT rate.
cys: the cumulative counts of DLTs observed at the left, current, and right dose levels.
cns: the cumulative counts of patients treated at the left, current, and right dose levels.
decision: the decision in the pCFO design, where left
, stay
, and right
represent the
movement directions, and stop
indicates stopping the experiment.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort. nextdose = 99
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which positions experience over-toxicity. The dose level indicated
by overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that
the occurrence of over-toxicity did not happen.
toxprob: the expected toxicity probability, , at the left, current, and
right dose levels, where
,
, and
is the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
NA
indicates that there
are no patients at the corresponding dose level.
When the current dose level is the lowest or highest (i.e., at the boundary), the parts in cys
and
cns
where there is no data are filled with NA
.
The dose level indicated by overtox
and all the dose levels above experience over-toxicity, and these dose levels will be eliminated.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials. Statistical Methods in Medical Research, 31(6), 1051-1066.
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- pCFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
Plot the objects returned by other functions, including (1) dose allocation of a single trial; (2) the estimate of toxicity probability for each dose and corresponding 95% credible interval; (3) operating characteristics of multiple simulations, including MTD selection percentage, the averaged number of patients allocated to different doses in one simulation and the averaged number of DLT observed for different doses in one simulation.
## S3 method for class 'cfo' plot(x, ..., name = deparse(substitute(x)))
## S3 method for class 'cfo' plot(x, ..., name = deparse(substitute(x)))
x |
the object returned by other functions |
... |
ignored arguments |
name |
the name of the object to be plotted. User does not need to input this parameter. |
plot()
returns a figure or a series of figures depending on the object entered.
In the example, we set nsimu = 5
for testing time considerations. In reality, nsimu
is typically set to 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## plot the object returned by CFO.simu() CFOtrial <- CFO.simu(design = 'CFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) plot(CFOtrial) ## plot the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) plot(selmtd) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## plot the object returned by lateonset.simu() ## f-aCFO design faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) plot(faCFOtrial) ## summarize the object returned by CFO.oc() 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) plot(faCFOoc) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 12; cohortsize <- 3 ## plot the single simulation returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) plot(CFO2dtrial) ## plot the multiple simulation returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) plot(CFO2doc) ## select a MTD based on the trial data ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) plot(selmtd) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) plot(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) plot(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) plot(result)
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## plot the object returned by CFO.simu() CFOtrial <- CFO.simu(design = 'CFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) plot(CFOtrial) ## plot the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) plot(selmtd) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## plot the object returned by lateonset.simu() ## f-aCFO design faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) plot(faCFOtrial) ## summarize the object returned by CFO.oc() 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) plot(faCFOoc) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) target <- 0.3; ncohort <- 12; cohortsize <- 3 ## plot the single simulation returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) plot(CFO2dtrial) ## plot the multiple simulation returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) plot(CFO2doc) ## select a MTD based on the trial data ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) plot(selmtd) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) plot(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) plot(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) plot(result)
Generate descriptive summary for objects returned by other functions.
## S3 method for class 'cfo' print(x, ...)
## S3 method for class 'cfo' print(x, ...)
x |
the object returned by other functions |
... |
ignored arguments |
print()
prints the objects returned by other functions.
print()
prints the objects returned by other functions.
In the example, we set nsimu = 5
for testing time considerations. In reality, nsimu
is typically set to 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## summarize the object returned by CFO.next() decision <- CFO.next(target = 0.2, cys = c(0, 1, 0), cns = c(3, 6, 0), currdose = 3) print(decision) ## summarize the object returned by lateonset.next() enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.65, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 0, 0, 0, 2.58) current.t<- 9.41; ndose = 7 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window, enter.times, dlt.times, current.t, doses) print(decision) ## summarize the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) print(selmtd) ## summarize the object returned by CFO.simu() aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) print(aCFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## summarize the object returned by lateonset.simu() faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) print(faCFOtrial) ## summarize the object returned by CFO.oc() 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) print(faCFOoc) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3); target <- 0.3; ncohort <- 12; cohortsize <- 3 ## summarize the object returned by CFO2d.next() decision <- CFO2d.next(target, cys, cns, currdose = currdose, seed = 1) print(decision) ## summarize the object returned by CFO2d.selectmtd() ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) print(selmtd) ## summarize the object returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) print(CFO2dtrial) ## summarize the object returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) print(CFO2doc) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) print(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) print(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) print(result)
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## summarize the object returned by CFO.next() decision <- CFO.next(target = 0.2, cys = c(0, 1, 0), cns = c(3, 6, 0), currdose = 3) print(decision) ## summarize the object returned by lateonset.next() enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.65, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 0, 0, 0, 2.58) current.t<- 9.41; ndose = 7 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window, enter.times, dlt.times, current.t, doses) print(decision) ## summarize the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) print(selmtd) ## summarize the object returned by CFO.simu() aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) print(aCFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## summarize the object returned by lateonset.simu() faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) print(faCFOtrial) ## summarize the object returned by CFO.oc() 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) print(faCFOoc) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3); target <- 0.3; ncohort <- 12; cohortsize <- 3 ## summarize the object returned by CFO2d.next() decision <- CFO2d.next(target, cys, cns, currdose = currdose, seed = 1) print(decision) ## summarize the object returned by CFO2d.selectmtd() ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) print(selmtd) ## summarize the object returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) print(CFO2dtrial) ## summarize the object returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) print(CFO2doc) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) print(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) print(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) print(result)
In the rCFO design for phase I trials, the function is used to determine the dose movement based on the toxicity outcomes of the enrolled cohorts.
rCFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed)
rCFO.next(target, cys, cns, currdose, prior.para = list(alp.prior = target, bet.prior = 1 - target), cutoff.eli = 0.95, early.stop = 0.95, seed)
target |
the target DLT rate. |
cys |
the cumulative numbers of DLTs observed at the left, current, and right dose levels. |
cns |
the cumulative numbers of patients treated at the left, current, and right dose levels. |
currdose |
the current dose level. |
prior.para |
the prior parameters for a beta distribution, where set as |
cutoff.eli |
the cutoff to eliminate overly toxic doses for safety. We recommend
the default value of |
early.stop |
the threshold value for early stopping. The default value |
seed |
an integer to be set as the seed of the random number generator for reproducible results. The default value is set to |
The original CFO design makes deterministic dose movement by constructing two odds ratios,
and
, and comparing them against thresholds
and
, respectively.
The rCFO design introduces a randomization scheme, normalizes odds ratios,
, and
into probabilities, and constructs
probabilities for dose escalation, de-escalation, and staying at the same dose.
The rCFO.next()
function returns a list object comprising the following elements:
target: the target DLT rate.
cys: the cumulative counts of DLTs observed at the left, current, and right dose levels.
cns: the cumulative counts of patients treated at the left, current, and right dose levels.
decision: the decision in the CFO design, where left
, stay
, and right
represent the
movement directions, and stop
indicates stopping the experiment.
currdose: the current dose level.
nextdose: the recommended dose level for the next cohort. nextdose = 99
indicates that the trial is
terminated due to early stopping.
overtox: the situation regarding which positions experience over-toxicity. The dose level indicated
by overtox
and all the dose levels above experience over-toxicity. overtox = NA
signifies that
the occurrence of over-toxicity did not happen.
toxprob: the expected toxicity probability, , at the left, current, and
right dose levels, where
,
, and
is the dose-limiting toxicity (DLT) rate, the
numbers of observed DLTs, and the numbers of patients at dose level
.
NA
indicates that there
are no patients at the corresponding dose level.
When the current dose level is the lowest or highest (i.e., at the boundary), the parts in cys
and
cns
where there is no data are filled with NA
.
The dose level indicated by overtox
and all the dose levels above experience over-toxicity, and these dose levels will be eliminated.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
Jin H, Yin G (2022). CFO: Calibration-free odds design for phase I/II clinical trials. Statistical Methods in Medical Research, 31(6), 1051-1066.
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
## determine the dose level for the next cohort of new patients cys <- c(0, 1, 0); cns <- c(3, 6, 0) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=3) summary(decision) cys <- c(NA, 3, 0); cns <- c(NA, 3, 0) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=1) summary(decision) cys <- c(0, 3, NA); cns <- c(3, 3, NA) decision <- rCFO.next(target=0.2, cys=cys, cns=cns, currdose=7) summary(decision)
Generate descriptive summary for objects returned by other functions.
## S3 method for class 'cfo' summary(object, ...)
## S3 method for class 'cfo' summary(object, ...)
object |
the object returned by other functions. |
... |
ignored arguments |
summary()
prints the objects returned by other functions.
In the example, we set nsimu = 5
for testing time considerations. In reality, nsimu
is typically set to 5000 to ensure the accuracy of the results.
Jialu Fang, Ninghao Zhang, Wenliang Wang, and Guosheng Yin
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## summarize the object returned by CFO.next() decision <- CFO.next(target = 0.2, cys = c(0, 1, 0), cns = c(3, 6, 0), currdose = 3) summary(decision) ## summarize the object returned by lateonset.next() enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.65, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 0, 0, 0, 2.58) current.t<- 9.41; ndose<-7 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window, enter.times, dlt.times, current.t, doses) summary(decision) ## summarize the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) summary(selmtd) ## summarize the object returned by CFO.simu() aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(aCFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## summarize the object returned by lateonset.simu() faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(faCFOtrial) ## summarize the object returned by CFO.oc() 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) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3); target <- 0.3; ncohort <- 12; cohortsize <- 3 ## summarize the object returned by CFO2d.next() decision <- CFO2d.next(target, cys, cns, currdose = currdose, seed = 1) summary(decision) ## summarize the object returned by CFO2d.selectmtd() ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) summary(selmtd) ## summarize the object returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) summary(CFO2dtrial) ## summarize the object returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) summary(CFO2doc) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) summary(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result)
## settings for 1dCFO nsimu <- 5; ncohort <- 12; cohortsize <- 3; init.level <- 1 p.true <- c(0.02, 0.05, 0.20, 0.28, 0.34, 0.40, 0.44); target <- 0.2 assess.window <- 3; accrual.rate <- 2; tte.para <- 0.5; accrual.dist <- 'unif' ## summarize the object returned by CFO.next() decision <- CFO.next(target = 0.2, cys = c(0, 1, 0), cns = c(3, 6, 0), currdose = 3) summary(decision) ## summarize the object returned by lateonset.next() enter.times<- c(0, 0.266, 0.638, 1.54, 2.48, 3.14, 3.32, 4.01, 4.39, 5.38, 5.76, 6.54, 6.66, 6.93, 7.32, 7.65, 8.14, 8.74) dlt.times<- c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0.995, 0, 0, 0, 0, 0, 0, 0, 2.58) current.t<- 9.41; ndose<-7 doses<-c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4, 4) decision <- lateonset.next(design = 'f-aCFO', target, ndose, currdose = 4, assess.window, enter.times, dlt.times, current.t, doses) summary(decision) ## summarize the object returned by CFO.selectmtd() selmtd <- CFO.selectmtd(target=0.2, npts=c(3,3,27,3,0,0,0), ntox=c(0,0,4,2,0,0,0)) summary(selmtd) ## summarize the object returned by CFO.simu() aCFOtrial <- CFO.simu(design = 'aCFO', target, p.true, init.level, ncohort, cohortsize, seed = 1) summary(aCFOtrial) # This test may take longer than 5 seconds to run # It is provided for illustration purposes only # Users can run this code directly ## summarize the object returned by lateonset.simu() faCFOtrial <- lateonset.simu (design = 'f-aCFO', target, p.true, init.level, ncohort, cohortsize, assess.window, tte.para, accrual.rate, accrual.dist, seed = 1) summary(faCFOtrial) ## summarize the object returned by CFO.oc() 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) ## settings for 2dCFO p.true <- matrix(c(0.05, 0.10, 0.15, 0.30, 0.45, 0.10, 0.15, 0.30, 0.45, 0.55, 0.15, 0.30, 0.45, 0.50, 0.60), nrow = 3, ncol = 5, byrow = TRUE) cns <- matrix(c(3, 3, 0, 0, 6, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) cys <- matrix(c(0, 1, 0, 0, 2, 0, 0, 0, 0), nrow = 3, ncol = 3, byrow = TRUE) currdose <- c(2,3); target <- 0.3; ncohort <- 12; cohortsize <- 3 ## summarize the object returned by CFO2d.next() decision <- CFO2d.next(target, cys, cns, currdose = currdose, seed = 1) summary(decision) ## summarize the object returned by CFO2d.selectmtd() ntox <- matrix(c(0, 0, 2, 0, 0, 0, 2, 7, 0, 0, 0, 2, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) npts <- matrix(c(3, 0, 12, 0, 0, 3, 12, 24, 0, 0, 3, 3, 0, 0, 0), nrow = 3, ncol = 5, byrow = TRUE) selmtd <- CFO2d.selectmtd(target=0.3, npts=npts, ntox=ntox) summary(selmtd) ## summarize the object returned by CFO2d.simu() CFO2dtrial <- CFO2d.simu(target, p.true, init.level = c(1,1), ncohort, cohortsize, seed = 1) summary(CFO2dtrial) ## summarize the object returned by CFO2d.oc() CFO2doc <- CFO2d.oc(nsimu = 5, target, p.true, init.level = c(1,1), ncohort, cohortsize, seeds = 1:5) summary(CFO2doc) ## summarize the object returned by CFOeff.next() decision <- CFOeff.next(target=0.4,axs=c(3,1,7,11,26),ays=c(0,0,0,0,6), ans= c(6, 3, 12, 17, 36), currdose = 3, mineff = 0.3) summary(decision) ## summarize the object returned by CFOeff.simu() target <- 0.30; mineff <- 0.30 prior.para = list(alp.prior = target, bet.prior = 1 - target, alp.prior.eff = 0.5, bet.prior.eff = 0.5) p.true=c(0.05, 0.07, 0.1, 0.12, 0.16) pE.true=c(0.35, 0.45, 0.5, 0.55, 0.75) result <- CFOeff.simu(target, p.true, pE.true, ncohort, init.level, cohortsize, prior.para, mineff = mineff, seed = 1) summary(result) ## summarize the object returned by CFOeff.oc() nsimu = 10 result <- CFOeff.oc(target, p.true, pE.true, prior.para, init.level,cohortsize, ncohort, nsimu, mineff = mineff, seeds = 1:nsimu) summary(result)