Time-to-event continual reassessment method (TITE-CRM) example

Examples
This short vignette demonstrates how to implement a time-to-event continual reassessment method (TITE-CRM) for dose escalation using the crmPack package.
Author

Ziwei Liao, Daniel Sabanés Bové

Published

October 22, 2026

Simulation setting

Here the simulation study setting is defined.

id <- 1
onset <- 3
a0 <- 2
a1 <- 3
refDose <- 56

# True dose-DLT relationship
myTruth <- function(dose) {
  StandLogDose <- log(dose / refDose)
  plogis(a0 + a1 * StandLogDose)
}

# The conditional CDF of the PEM
if (onset == 30) {
  onset <- 15
  exp_cond_cdf <- function(x) {
    (pexp(42 - x, 1 / onset, lower.tail = FALSE) - pexp(t_max, 1 / onset, lower.tail = FALSE)) / pexp(t_max, 1 / onset)
  }
} else {
  exp_cond_cdf <- function(x) {
    1 - (pexp(x, 1 / onset, lower.tail = FALSE) - pexp(t_max, 1 / onset, lower.tail = FALSE)) / pexp(t_max, 1 / onset)
  }
}

Design definition

Here the the dose escalation designs are defined: in this example the TITE-CRM is used. Similarly the code can be adapted for the rolling-CRM which is implemented in DALogisticLogNormal. Note that another alternative is TITELogisticLogNormalSub which is a submodel of LogisticLogNormalSub, which uses again the subtraction of the reference dose from the dose level in the regression model.

library(crmPack)
t_max <- 42

model <- TITELogisticLogNormal(
  mean = c(1.33, 1.49),
  cov = matrix(c(1.826, 0.0209, 0.0209, 0.0245), nrow = 2),
  ref_dose = refDose
)

myIncrements <- IncrementsRelative(
  intervals = c(0, 20),
  increments = c(10, 3)
)

myNextBest <- NextBestMTD(
  target = 0.3,
  derive =
    function(mtd_samples) {
      mean(mtd_samples)
    }
)

myStopping <- StoppingMinPatients(nPatients = 48)

mySize <- CohortSizeConst(size = 3)

emptydata <- DataDA(doseGrid = seq(from = 2, to = 50, by = 2), Tmax = t_max)

mysafetywindow <- SafetyWindowConst(c(7, 7), 7, 7)

design <- DADesign(
  model = model,
  increments = myIncrements,
  nextBest = myNextBest,
  stopping = myStopping,
  cohort_size = mySize,
  data = emptydata,
  safetyWindow = mysafetywindow,
  startingDose = 8
)

Simulation run

In order to obtain stable results, increase the simulation parameters appropriately (burnin, step, samples, nsim).

options <- McmcOptions(
  burnin = 20,
  step = 1,
  samples = 50
)
mySims <- simulate(design,
  args = NULL,
  truthTox = myTruth,
  truthSurv = exp_cond_cdf,
  trueTmax = 42,
  nsim = 10,
  seed = 819,
  mcmcOptions = options,
  parallel = FALSE
)

Alternatively we can also use examine() to look at possible trial outcomes. Each cohort is reached assuming no additional DLTs in earlier cohorts. DLTs is the hypothetical number of additional DLTs among the current cohort and patients from earlier cohorts whose DLT windows are still open at the next decision. Thus it can exceed the cohort size.

DLT_scenario identifies the allocation scenario: "no additional DLTs", "late DLTs" (earlier-enrolled eligible patients at their available follow-up times), or "early DLTs" (later-enrolled eligible patients with early event times). See ?examine for the timing details.

cohort indexes the current cohort, continuing any indices already present in the design data. dose is that cohort’s dose. DLT_cohorts lists the cohort indices of the additional hypothetical DLTs, separated by commas and sorted. For example, "1, 2, 2" means one DLT in cohort 1 and two in cohort 2; "" means no additional DLTs. DLT_time lists their corresponding onset times, relative to the start of each patient’s cohort, in the same order. Previously observed DLTs are excluded from both columns.

Each hypothetical scenario requires an MCMC fit. maxNoIncrement limits the number of consecutive unchanged dose recommendations on the zero-DLT path (default: 100); reaching this limit produces a warning.

set.seed(321)
examineTable <- examine(
  design,
  mcmcOptions = options
)
examineTable
#>    cohort       DLT_scenario dose DLTs   DLT_cohorts           DLT_time
#> 1       1 no additional DLTs    8    0                                 
#> 2       1          late DLTs    8    1             1                 21
#> 3       1         early DLTs    8    1             1                 15
#> 4       1          late DLTs    8    2          1, 1             21, 21
#> 5       1         early DLTs    8    2          1, 1              8, 15
#> 6       1          late DLTs    8    3       1, 1, 1         21, 21, 21
#> 7       1         early DLTs    8    3       1, 1, 1           1, 8, 15
#> 8       2 no additional DLTs   40    0                                 
#> 9       2          late DLTs   40    1             1                 42
#> 10      2         early DLTs   40    1             2                 15
#> 11      2          late DLTs   40    2          1, 1             42, 42
#> 12      2         early DLTs   40    2          2, 2              8, 15
#> 13      2          late DLTs   40    3       1, 1, 2         42, 42, 21
#> 14      2         early DLTs   40    3       2, 2, 2           1, 8, 15
#> 15      2          late DLTs   40    4    1, 1, 2, 2     42, 42, 21, 21
#> 16      2         early DLTs   40    4    1, 2, 2, 2       22, 1, 8, 15
#> 17      2          late DLTs   40    5 1, 1, 2, 2, 2 42, 42, 21, 21, 21
#> 18      2         early DLTs   40    5 1, 1, 2, 2, 2   22, 22, 1, 8, 15
#> 19      3 no additional DLTs   36    0                                 
#> 20      3          late DLTs   36    1             2                 42
#> 21      3         early DLTs   36    1             3                 15
#> 22      3          late DLTs   36    2          2, 2             42, 42
#> 23      3         early DLTs   36    2          3, 3              8, 15
#> 24      3          late DLTs   36    3       2, 2, 3         42, 42, 21
#> 25      3         early DLTs   36    3       3, 3, 3           1, 8, 15
#> 26      3          late DLTs   36    4    2, 2, 3, 3     42, 42, 21, 21
#> 27      3         early DLTs   36    4    2, 3, 3, 3       22, 1, 8, 15
#> 28      3          late DLTs   36    5 2, 2, 3, 3, 3 42, 42, 21, 21, 21
#> 29      3         early DLTs   36    5 2, 2, 3, 3, 3   22, 22, 1, 8, 15
#> 30      4 no additional DLTs   26    0                                 
#> 31      4          late DLTs   26    1             3                 42
#> 32      4         early DLTs   26    1             4                 15
#> 33      4          late DLTs   26    2          3, 3             42, 42
#> 34      4         early DLTs   26    2          4, 4              8, 15
#> 35      4          late DLTs   26    3       3, 3, 4         42, 42, 21
#> 36      4         early DLTs   26    3       4, 4, 4           1, 8, 15
#> 37      4          late DLTs   26    4    3, 3, 4, 4     42, 42, 21, 21
#> 38      4         early DLTs   26    4    3, 4, 4, 4       22, 1, 8, 15
#> 39      4          late DLTs   26    5 3, 3, 4, 4, 4 42, 42, 21, 21, 21
#> 40      4         early DLTs   26    5 3, 3, 4, 4, 4   22, 22, 1, 8, 15
#> 41      5 no additional DLTs   46    0                                 
#> 42      5          late DLTs   46    1             4                 42
#> 43      5         early DLTs   46    1             5                 15
#> 44      5          late DLTs   46    2          4, 4             42, 42
#> 45      5         early DLTs   46    2          5, 5              8, 15
#> 46      5          late DLTs   46    3       4, 4, 5         42, 42, 21
#> 47      5         early DLTs   46    3       5, 5, 5           1, 8, 15
#> 48      5          late DLTs   46    4    4, 4, 5, 5     42, 42, 21, 21
#> 49      5         early DLTs   46    4    4, 5, 5, 5       22, 1, 8, 15
#> 50      5          late DLTs   46    5 4, 4, 5, 5, 5 42, 42, 21, 21, 21
#> 51      5         early DLTs   46    5 4, 4, 5, 5, 5   22, 22, 1, 8, 15
#>    nextDose  stop increment
#> 1        40 FALSE       400
#> 2        20 FALSE       150
#> 3        24 FALSE       200
#> 4        22 FALSE       175
#> 5        20 FALSE       150
#> 6        24 FALSE       200
#> 7        16 FALSE       100
#> 8        36 FALSE       -10
#> 9        28 FALSE       -30
#> 10       44 FALSE        10
#> 11       12 FALSE       -70
#> 12       28 FALSE       -30
#> 13       16 FALSE       -60
#> 14       32 FALSE       -20
#> 15       12 FALSE       -70
#> 16       22 FALSE       -45
#> 17       24 FALSE       -40
#> 18       14 FALSE       -65
#> 19       26 FALSE       -28
#> 20       34 FALSE        -6
#> 21       44 FALSE        22
#> 22       40 FALSE        11
#> 23       36 FALSE         0
#> 24       26 FALSE       -28
#> 25       42 FALSE        17
#> 26       26 FALSE       -28
#> 27       30 FALSE       -17
#> 28       26 FALSE       -28
#> 29       24 FALSE       -33
#> 30       46 FALSE        77
#> 31       42 FALSE        62
#> 32       36 FALSE        38
#> 33       38 FALSE        46
#> 34       32 FALSE        23
#> 35       34 FALSE        31
#> 36       32 FALSE        23
#> 37       30 FALSE        15
#> 38       30 FALSE        15
#> 39       24 FALSE        -8
#> 40       26 FALSE         0
#> 41       50 FALSE         9
#> 42       40 FALSE       -13
#> 43       50 FALSE         9
#> 44       36 FALSE       -22
#> 45       38 FALSE       -17
#> 46       38 FALSE       -17
#> 47       42 FALSE        -9
#> 48       32 FALSE       -30
#> 49       36 FALSE       -22
#> 50       36 FALSE       -22
#> 51       36 FALSE       -22