library(crmPack)
dose_grid <- c(1, 5, 10, seq(from = 20, to = 200, by = 10))Basic Training
March 31, 2026

Part of this training material is based on the crmPack training materials developed by John Kirkpatrick (Roche, now at Astellas). Thanks John for sharing!
Figure taken from “Principles of dose finding studies in cancer: A comparison of trial designs”
| 3+3 | CRM | |
|---|---|---|
| Definition of a DLT | Study specific | Study specific |
| The target toxicity rate | 0.33 | Any |
| The dose grid | Study specific | Study specific |
| The cohort size | 3 | Any |
| The stopping rule(s) | 2 DLTs at same dose | Any |
| The eligibility rule | One dose up | Any |
| The escalation rule | +1 if 0/3 or 1/6 | Any |
| The definition of the MTD | Max dose with <2 DLTs | Any |
| The dose-toxicity model | None | Any |
Table taken from “Moving Beyond 3+3: The Future of Clinical Trial Design”
With crmPack we aim to make it easy for everyone to use model-based designs in their dose escalation studies. The package provides:
Generic flow chart for model-based dose escalation design
crmPack package structure parallels the flow chart
crmPack package framework
We first need to decide what the possible doses could be, i.e. the so-called dose grid:
This we use to initialize our (still empty, i.e. without patients) Data object, which will be used to store the data of our trial as it progresses:
We can “update” the Data object with the information of a patient treated at dose 10, who did not experience a DLT, and a patient at dose 20 with a DLT:
And plot it:
Next we need to specify the dose-toxicity model we want to use.
Often used is this logistic model with reference dose , which assigns the following probability of DLT to a dose :
Then we also use a prior distribution for the parameters and . Typically, we want to be positive, so we can assign a bivariate normal distribution to .
For example, let’s use the following model:
In Quarto/Rmarkdown, we will get the nice textual description of the model by just printing it:
We use MCMC, in particular Gibbs sampling implemented in JAGS, to generate (approximate) samples from the posterior distribution of the model parameters. The settings are controlled by the McmcOptions object. Note that in order to get reproducible results, we also need to set the random seed:
Now we can generate the prior and posterior samples with the mcmc method:
We usually need additional safety rules for our model-based dose escalation design. For example, we might restrict the maximum allowed dose increment to 100% (i.e. doubling the dose) if no DLTs have been observed, and to 50% if one DLT has been observed. This can be implemented with an Increments object:
Together with the regression model, the definition of how to obtain the recommendation for the dose of the next cohort, are the key components of the model-based dose escalation design.
For example, we can maximize the posterior probability of being in the target toxicity interval (e.g. 20–30% DLTs) while restricting the maximum overdosing (e.g. 40-100% DLTs) probability to less than 25%:
The dose recommended for the next cohort will be chosen in the following way. First, doses that are ineligible according to the increments rule will be discarded. Next, any dose for which the mean posterior probability of toxicity being in the overdose range - (0.4, 1] - is 0.25 or more will also be discarded. Finally, the dose amongst those remaining which has the highest chance that the mean posterior probability of toxicity is in the target toxicity range of 0.2 to 0.3 (inclusive) will be selected.
In the simplest case, we just always have the same constant number of patients in each cohort, e.g. 3 patients per cohort:
As with all components, other options are available, see ?CohortSize for details.
Typically there are stopping rules for a dose escalation study. In the simplest case, this is just the number of patients treated, e.g. 30 patients:
But we can also combine this with logical & and | operators with other stopping rules, e.g. to also stop if the target probability is high, or if the model would not recommend any dose at all because of safety concerns:
If any of the following rules are TRUE:
≥ 30 patients dosed: If 30 or more participants have been treated.
P(0.2 ≤ prob(DLE | NBD) ≤ 0.3) ≥ 0.7: If the probability of toxicity at the next best dose is in the range [0.20, 0.30] is at least 0.70.
Stopped because of missing dose: If the dose returned by nextBest() is NA, or if the trial includes a placebo dose, the placebo dose.
So in our data example from above, what would be the recommended dose for the next cohort?
First, the maximum increment is calculated using the maxDose method:
Here it is only 30, because we observed one DLT at dose 20, so the maximum allowed increment is 50%.
Then the next best dose is calculated with the nextBest method:
The plot is in the $plot element of the result:
And the value is in the $value element:
So due to the high probability of overdosing at dose 30, the recommended dose for the next cohort is dose 20, which is the same as the previous cohort.
First we need to put all the components of our model-based dose escalation design together in a Design object - here we also need to define a starting dose:
A logistic log normal model will describe the relationship between dose and toxicity: where dref denotes a reference dose.
The prior for θ is given by
The reference dose will be 20.00.
If any of the following rules are TRUE:
≥ 30 patients dosed: If 30 or more participants have been treated.
P(0.2 ≤ prob(DLE | NBD) ≤ 0.3) ≥ 0.7: If the probability of toxicity at the next best dose is in the range [0.20, 0.30] is at least 0.70.
Stopped because of missing dose: If the dose returned by nextBest() is NA, or if the trial includes a placebo dose, the placebo dose.
|
No DLTs
|
||
|---|---|---|
| Min | Max | Increment |
| 0 | 1 | 1.0 |
| 1 | Inf | 0.5 |
Placebo will not be administered in the trial.
No backfill cohorts at all will be opened.
The dose recommended for the next cohort will be chosen in the following way. First, doses that are ineligible according to the increments rule will be discarded. Next, any dose for which the mean posterior probability of toxicity being in the overdose range - (0.4, 1] - is 0.25 or more will also be discarded. Finally, the dose amongst those remaining which has the highest chance that the mean posterior probability of toxicity is in the target toxicity range of 0.2 to 0.3 (inclusive) will be selected.
A constant size of 3 participants.
No participants are yet evaluable.
The dose grid is 1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190 and 200.
The starting dose is 5.
The first “quick check” we should run on our design is how it behaves if we don’t see any DLTs at all - can we even reach the higher doses? This can be done with the examine method:
dose DLTs nextDose stop increment
1 5 0 10 FALSE 100
2 5 1 5 FALSE 0
3 5 2 5 FALSE 0
4 5 3 5 FALSE 0
5 10 0 20 FALSE 100
6 10 1 10 FALSE 0
7 10 2 10 FALSE 0
8 10 3 10 FALSE 0
9 20 0 30 FALSE 50
10 20 1 20 FALSE 0
11 20 2 20 FALSE 0
12 20 3 10 FALSE -50
13 30 0 40 FALSE 33
14 30 1 30 FALSE 0
15 30 2 20 FALSE -33
16 30 3 20 FALSE -33
17 40 0 80 FALSE 100
18 40 1 40 FALSE 0
19 40 2 30 FALSE -25
20 40 3 20 FALSE -50
21 80 0 150 FALSE 88
22 80 1 80 FALSE 0
23 80 2 50 FALSE -38
24 80 3 40 FALSE -50
25 150 0 200 FALSE 33
26 150 1 140 FALSE -7
27 150 2 90 FALSE -40
28 150 3 60 FALSE -60
Here it could be also concerning that if we observe 3 DLTs at the starting dose of 5, we still continue with the same dose 5 for the next cohort. The reason here is that the prior is “too confident” that at low doses we have a low DLT probability.
So we need to adjust the prior to be less confident, e.g. by increasing the standard deviations of the parameters:
dose DLTs nextDose stop increment
1 5 0 10 FALSE 100
2 5 1 5 FALSE 0
3 5 2 1 FALSE -80
4 5 3 NA TRUE NA
5 10 0 20 FALSE 100
6 10 1 10 FALSE 0
7 10 2 10 FALSE 0
8 10 3 5 FALSE -50
9 20 0 20 FALSE 0
10 20 1 20 FALSE 0
11 20 2 10 FALSE -50
12 20 3 10 FALSE -50
13 20 0 20 FALSE 0
14 20 1 20 FALSE 0
15 20 2 20 FALSE 0
16 20 3 10 FALSE -50
17 20 0 30 FALSE 50
18 20 1 20 FALSE 0
19 20 2 20 FALSE 0
20 20 3 20 FALSE 0
21 30 0 60 FALSE 100
22 30 1 30 FALSE 0
23 30 2 20 FALSE -33
24 30 3 20 FALSE -33
25 60 0 120 FALSE 100
26 60 1 50 FALSE -17
27 60 2 40 FALSE -33
28 60 3 30 FALSE -50
29 120 0 200 FALSE 67
30 120 1 130 FALSE 8
31 120 2 70 FALSE -42
32 120 3 50 FALSE -58
In order to evaluate the operating characteristics of our design, we need to define some toxicity scenarios, i.e. the true dose-toxicity relationship in the population. This needs to be a function mapping a dose vector to a vector of DLT probabilities. This could be:
For example:
Now given the design and the toxicity scenario, we can run simulations with the simulate method:
Especially in oncology trials, it is meanwhile common to open backfill cohorts at lower dose levels while the escalation cohorts are still ongoing at higher dose levels. Recently this was implemented in crmPack with the Backfill objects.
For example:
Cohort size: A constant size of 3 participants.
Opening rule: If 1 or more cohorts have been treated in total.
Recruitment: Unlimited recruitment of backfill patients is allowed.
Total number of backfill patients: 12 backfill patients.
Priority of higher vs. lower dose backfill cohorts: lowest dose.
This can then be added in the corresponding backfill slot of the Design object:
Please note that the examine method does not yet take the backfilling into account, so it will still show the same results as before. To see the effect of the backfilling, we need to run simulations.
We can get basic summaries of the simulation results with the summary method:
Summary of 100 simulations
Target toxicity interval was 20, 35 %
Target dose interval corresponding to this was 43.1, 112.4
Intervals are corresponding to 10 and 90 % quantiles
Number of patients overall : mean 30 (30, 30)
Number of patients treated above target tox interval : mean 0 (0, 0)
Proportions of DLTs in the trials : mean 10 % (3 %, 17 %)
Mean toxicity risks for the patients on active : mean 10 % (4 %, 14 %)
Doses selected as MTD : mean 25.8 (5, 41)
True toxicity at doses selected : mean 12 % (4 %, 19 %)
Proportion of trials selecting target MTD: 6 %
Dose most often selected as MTD: 20
Observed toxicity rate at dose most often selected: 12 %
Fitted toxicity rate at dose most often selected : mean 12 % (3 %, 23 %)
Stop reason triggered:
≥ 30 patients dosed : 100 %
P(0.2 ≤ prob(DLE | NBD) ≤ 0.3) ≥ 0.7 : 0 %
Stopped because of missing dose : 0 %
And we can also get more detailed plots of the simulation results with the plot method:
The summary result can also be plotted:
Lots of documentation is available on the crmPack website: crmPack.org It includes: