# Guiding Oncology Dose-Escalation Trials

## Introduction

The OncoBayes2 package provides flexible functions for Bayesian meta-analytic modeling of the incidence of Dose Limiting Toxicities (DLTs) by dose level, under treatment regimes involving any number of combination partners. Such models may be used to ensure patient safety during trial conduct by supporting dose-escalation decisions. In addition, the model can support estimation of the Maximum Tolerated Dose (MTD) in adaptive Bayesian dose-escalation designs.

Whereas traditional dose escalation designs, such as the 3+3 design, base the dosing decisions on predefined rules about the number of DLTs in the last one or two cohorts at the current dose, model-based designs such as those using Bayesian Logistic Regression Models (BLRMs) endeavor to model the dose-toxicity relationship as a continuous curve, and allow the model to guide dosing decisions. In this way, all available data contributes to the dosing decisions. Furthermore, extensions to the BLRM approach can support inclusion of available historical data on the compound(s) involved.

The package supports incorporation of historical data through a Meta-Analytic-Combined (MAC) framework [1], which stratifies these heterogeneous sources of information through a hierarchical model. Additionally, it allows the use of EXchangeable/Non-EXchangeable (EX/NEX) priors to manage the amount of information-sharing across subgroups of historical and/or concurrent sources of data.

## Load involved packages
library(dplyr)  ## for mutate
library(tidyr)  ## defines expand_grid
library(tibble) ## for tibbles

## Example use-case

Consider the application described in Section 3.2 of [1], in which the risk of DLT is to be studied as a function of dose for two drugs, drug A and drug B. Historical information on the toxicity profiles of these two drugs is available from single agent trials trial_A and trial_B. The historical data for this example is available in an internal data set.

kable(hist_combo2)
group_id drug_A drug_B num_patients num_toxicities cohort_time
trial_A 3.0 0.0 3 0 0
trial_A 4.5 0.0 3 0 0
trial_A 6.0 0.0 6 0 0
trial_A 8.0 0.0 3 2 0
trial_B 0.0 33.3 3 0 0
trial_B 0.0 50.0 3 0 0
trial_B 0.0 100.0 4 0 0
trial_B 0.0 200.0 9 0 0
trial_B 0.0 400.0 15 0 0
trial_B 0.0 800.0 20 2 0
trial_B 0.0 1120.0 17 4 0

The objective is to aid dosing and dose-escalation decisions in a future trial, trial_AB, in which the drugs will be combined. Additionally, another investigator-initiated trial IIT will study the same combination concurrently. Note that these as-yet-unobserved sources of data are included in the input data as unobserved factor levels. This mechanism allows us to specify a joint meta-analytic prior for all four sources of historical and concurrent data.

levels(hist_combo2\$group_id)
## [1] "trial_A"  "trial_B"  "IIT"      "trial_AB"

### Setting up the trial design

The function blrm_trial provides an object-oriented framework for operationalizing the dose-escalation trial design. This framework is intended as a convenient wrapper for the main model-fitting engine of the package, the blrm_exnex() function. The latter allows additional flexibility for specifying the functional form of the model, but blrm_trial covers the most common use-cases. This introductory vignette highlights blrm_trial in lieu of blrm_exnex; the reader is referred to the help-page of the function?blrm_exnex for more details.

One begins with blrm_trial by specifying three key design elements:

• The dose-toxicity data
• Information about the study drugs
• The provisional dose levels to be studied during the escalation trial

Information about the study drugs is encoded through a tibble as below. This includes the names of the study-drugs, the reference doses (see [3] or ?blrm_exnex to understand the role this choice plays in the model specification), the dosing units, and (optionally) the a priori expected DLT rate for each study drug given individually at the respective reference doses.

All design information for the study described in [1] is also included as built-in datasets, which are part of the OncoBayes2 package.

#### Drug info

kable(drug_info_combo2)
drug_name dose_ref dose_unit reference_p_dlt
drug_A 300 mg 0.1
drug_B 960 mg 0.1

#### Dose info

The provisional dose levels are specified as below. For conciseness, we begin by fixing the dose level of drug A in these provisional doses.

dose_info <- filter(dose_info_combo2, group_id == "trial_AB", drug_A == 3)
kable(dose_info)
group_id drug_A drug_B dose_id
trial_AB 3 0 22
trial_AB 3 400 23
trial_AB 3 600 24
trial_AB 3 800 25

#### Initializing a blrm_trial

Together with the data described in the previous section, these objects can be used to initialize a blrm_trial object.

combo2_trial_setup <- blrm_trial(
data = hist_combo2,
drug_info = drug_info_combo2,
dose_info = dose_info,
simplified_prior = FALSE
)
## No stratum defined - assigning all groups to single stratum "all"
## Please configure blrm_exnex using the update() function.

### Specifying the prior and fitting the model

At this point, the trial design has been initialized. However, in the absence of simplified_prior = TRUE, we have not yet specified the prior distribution for the dose-toxicity model.

OncoBayes2 provides two methods for completing the model specification:

1. Use simplified_prior = TRUE, which employs a package-default prior distribution, subject to a small number of optional arguments controlling the details.

2. Provide a full prior specification to be passed to the main model-fitting engine of OncoBayes2: the blrm_exnex function.

For illustrative purposes, here we highlight method #1. See ?'example-combo2_trial' for an example of #2. The below choice of prior broadly follows the case study in [4], although we slightly deviate from the model in [4] by allowing an EXchangeable/Non-EXchangeable prior for the drug components.

To employ the simplified prior, and fit the model with MCMC:

combo2_trial_start <- blrm_trial(
data = hist_combo2,
drug_info = drug_info_combo2,
dose_info = dose_info,
simplified_prior = TRUE,
EX_prob_comp_hist = 0.8,
EX_prob_comp_new = 1
)

Now, the object combo2_trial_start contains the posterior model fit, in addition to the trial design details. Next we highlight the main methods for extracting relevant information from it.

### Summary of prior specification

The function prior_summary provides a facility for printing, in a readable format, a summary of the prior specification.

prior_summary(combo2_trial_start) # not run here

### Summary of posterior

The main target of inference is generally the probability of DLT at a selection of provisional dose levels. To obtain these summaries for the provisional doses specified previously, we simply write:

kable(summary(combo2_trial_start, "dose_prediction"), digits = 2)
group_id drug_A drug_B dose_id stratum_id mean sd 2.5% 50% 97.5% prob_underdose prob_target prob_overdose ewoc_ok
trial_AB 3 0 22 all 0.08 0.12 0.00 0.04 0.44 0.86 0.10 0.04 TRUE
trial_AB 3 400 23 all 0.14 0.16 0.00 0.09 0.63 0.72 0.18 0.10 TRUE
trial_AB 3 600 24 all 0.16 0.17 0.01 0.11 0.68 0.65 0.23 0.12 TRUE
trial_AB 3 800 25 all 0.20 0.18 0.02 0.15 0.73 0.53 0.31 0.16 TRUE

Such summaries may be used to assess which combination doses have unacceptable high risk of toxicity. For example, according to the escalation with overdose control (EWOC) design criteria [3], one would compute the posterior probability that each dose is excessively toxic (column prob_overdose; note that the definition of “excessively toxic” is encoded in the blrm_trial object through the interval_prob argument), and take as eligible doses only those where this probability does not exceed 25% (column ewoc_ok).

### Posterior predictive summaries

The BLRM allows a principled approach to predicting the number of DLTs that may be observed in a future cohort. This may be a key estimand for understanding and limiting the toxicity risk to patients. For example, suppose a candidate starting dose for the new trial trial_AB is 3 mg of Drug A + 400 mg of Drug B. We may wish to check that at this dose, the estimated probability of 2 or more DLTs out of an initial cohort of 3 to 6 patients is sufficiently low.

candidate_starting_dose <- summary(combo2_trial_start, "dose_info") %>%
filter(drug_A == 3, drug_B == 400) %>%
expand_grid(num_patients = 3:6) %>%
mutate(num_toxicities = 0)

pp_summary <- summary(combo2_trial_start, interval_prob = c(-1, 0, 1, 6), predictive = TRUE,
newdata = candidate_starting_dose)

kable(bind_cols(select(candidate_starting_dose, num_patients),
select(pp_summary, ends_with("]"))), digits = 3)
num_patients (-1,0] (0,1] (1,6]
3 0.698 0.216 0.086
4 0.640 0.233 0.127
5 0.591 0.243 0.166
6 0.550 0.248 0.202

This tells us that for the initial cohort, according to the model, the chance of two or more patients developing DLTs ranges from 8.6% to 20.2%, depending on the number of patients enrolled.

### Updating the model with new data

Dose-escalation designs are adaptive in nature, as dosing decisions are made after each sequential cohort. The model must be updated after each new enrollment. If a new cohort of patients is observed, say:

new_cohort <- tibble(group_id = "trial_AB",
drug_A = 3,
drug_B = 400,
num_patients = 5,
num_toxicities = 1)

One can update the model to incorporate this new information using update() with add_data equal to the new cohort:

combo2_trial_update <- update(combo2_trial_start, add_data = new_cohort)

This yields a new blrm_trial object with updated data and posterior summaries. Below is the method for obtaining posterior estimates at the next highest dose of drug A.

kable(summary(combo2_trial_update, "newdata_prediction",
newdata = tibble(group_id = "trial_AB",
drug_A = 4.5,
drug_B = c(400, 600, 800))), digits = 2)
## stratum_id not given, but only one stratum defined. Assigning first stratum.
group_id drug_A drug_B stratum_id dose_id mean sd 2.5% 50% 97.5% prob_underdose prob_target prob_overdose ewoc_ok
trial_AB 4.5 400 all NA 0.16 0.12 0.02 0.13 0.47 0.59 0.31 0.10 TRUE
trial_AB 4.5 600 all NA 0.19 0.13 0.04 0.17 0.52 0.48 0.39 0.13 TRUE
trial_AB 4.5 800 all NA 0.23 0.14 0.05 0.20 0.58 0.35 0.45 0.20 TRUE

### Data scenarios

It may be of interest to test prospectively how this model responds in various scenarios for upcoming cohorts.

This can be done easily by again using update() with the add_data argument. In the code below, we explore 3 possible outcomes for a subsequent cohort enrolled at 3 mg Drug A + 800 mg Drug B, and review the model’s inference at adjacent doses.

# set up two scenarios at the starting dose level
# store them as data frames in a named list
scenarios <- expand_grid(
group_id  = "trial_AB",
drug_A = 3,
drug_B = 800,
num_patients = 3,
num_toxicities = 0:2
) %>% split(1:3) %>% setNames(paste(0:2, "DLTs"))

candidate_doses <- expand_grid(
group_id = "trial_AB",
drug_A = c(3, 4.5),
drug_B = c(600, 800)
)

scenario_inference <- lapply(scenarios, function(scenario_newdata) {

# refit the model with each scenario's additional data
scenario_fit <- update(combo2_trial_update, add_data = scenario_newdata)

# summarize posterior at candidate doses
summary(scenario_fit, "newdata_prediction", newdata = candidate_doses)

})
Model inference when 0 DLTs are observed in the next cohort
group_id drug_A drug_B stratum_id dose_id mean sd 2.5% 50% 97.5% prob_underdose prob_target prob_overdose ewoc_ok
trial_AB 3.0 600 all 24 0.14 0.09 0.02 0.12 0.35 0.68 0.29 0.03 TRUE
trial_AB 3.0 800 all 25 0.17 0.10 0.04 0.15 0.40 0.54 0.40 0.06 TRUE
trial_AB 4.5 600 all NA 0.15 0.09 0.03 0.13 0.37 0.63 0.32 0.05 TRUE
trial_AB 4.5 800 all NA 0.18 0.10 0.04 0.16 0.42 0.49 0.43 0.08 TRUE
Model inference when 1 DLT is observed in the next cohort
group_id drug_A drug_B stratum_id dose_id mean sd 2.5% 50% 97.5% prob_underdose prob_target prob_overdose ewoc_ok
trial_AB 3.0 600 all 24 0.20 0.11 0.05 0.18 0.47 0.42 0.46 0.12 TRUE
trial_AB 3.0 800 all 25 0.24 0.12 0.07 0.22 0.53 0.28 0.52 0.21 TRUE
trial_AB 4.5 600 all NA 0.21 0.11 0.05 0.19 0.49 0.37 0.48 0.14 TRUE
trial_AB 4.5 800 all NA 0.25 0.12 0.07 0.23 0.54 0.23 0.53 0.24 TRUE
Model inference when 2 DLTs are observed in the next cohort
group_id drug_A drug_B stratum_id dose_id mean sd 2.5% 50% 97.5% prob_underdose prob_target prob_overdose ewoc_ok
trial_AB 3.0 600 all 24 0.28 0.14 0.07 0.25 0.60 0.21 0.48 0.31 FALSE
trial_AB 3.0 800 all 25 0.34 0.15 0.11 0.31 0.71 0.10 0.45 0.45 FALSE
trial_AB 4.5 600 all NA 0.29 0.14 0.08 0.27 0.62 0.18 0.47 0.35 FALSE
trial_AB 4.5 800 all NA 0.35 0.15 0.12 0.33 0.71 0.09 0.42 0.50 FALSE

## Continuation of example

In the example of [1], at the time of completion of trial_AB, the following additional data was observed.

kable(filter(codata_combo2, cohort_time > 0))
group_id drug_A drug_B num_patients num_toxicities cohort_time
trial_A 4.5 0 3 0 1
trial_A 6.0 0 5 0 1
IIT 3.0 400 3 0 1
IIT 3.0 800 7 5 1
IIT 4.5 400 3 0 1
IIT 6.0 400 6 0 1
IIT 6.0 600 3 2 1
trial_AB 3.0 400 3 0 1
trial_AB 3.0 800 6 2 1
trial_AB 4.5 600 10 2 1
trial_AB 6.0 400 10 3 1

Numerous toxicities were observed in the concurrent IIT study. Through the MAC framework, these data can influence the model summaries for trial_AB. Note that we use the update function differently than before, since we specify the entire data-set now we use the data argument.

final_fit <- update(combo2_trial_start, data = codata_combo2)

Model results can be visualized using package functions. See ?plot_toxicity_curve for details.

plot_toxicity_curve(final_fit, x = vars(drug_B), group = vars(group_id, drug_A),
facet_args = list(ncol = 1))

## References

[1] Neuenschwander, B., Roychoudhury, S., & Schmidli, H. (2016). On the use of co-data in clinical trials. Statistics in Biopharmaceutical Research, 8(3), 345-354.

[2] Neuenschwander, B., Wandel, S., Roychoudhury, S., & Bailey, S. (2016). Robust exchangeability designs for early phase clinical trials with multiple strata. Pharmaceutical statistics, 15(2), 123-134.

[3] Neuenschwander, B., Branson, M., & Gsponer, T. (2008). Critical aspects of the Bayesian approach to phase I cancer trials. Statistics in medicine, 27(13), 2420-2439.

[4] Neuenschwander, B., Matano, A., Tang, Z., Roychoudhury, S., Wandel, S. Bailey, Stuart. (2014). A Bayesian Industry Approach to Phase I Combination Trials in Oncology. In Statistical methods in drug combination studies (Vol. 69). CRC Press.

## Session Info

sessionInfo()
## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.6 LTS
##
## Matrix products: default
## BLAS:   /usr/lib/libblas/libblas.so.3.6.0
## LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
##
## locale:
## [1] C
##
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base
##
## other attached packages:
## [1] tibble_2.1.3     tidyr_1.0.0      dplyr_0.8.3      ggplot2_3.2.1
## [5] knitr_1.25       OncoBayes2_0.7-0 Rcpp_1.0.2
##
## loaded via a namespace (and not attached):
##  [1] rstan_2.19.3       tidyselect_0.2.5   xfun_0.10
##  [4] purrr_0.3.3        colorspace_1.4-1   vctrs_0.2.0
##  [7] htmltools_0.4.0    stats4_3.6.1       loo_2.1.0
## [10] yaml_2.2.0         rlang_0.4.0        pkgbuild_1.0.6
## [13] pillar_1.4.2       glue_1.3.1         withr_2.1.2
## [16] matrixStats_0.55.0 lifecycle_0.1.0    plyr_1.8.4
## [19] stringr_1.4.0      munsell_0.5.0      gtable_0.3.0
## [22] codetools_0.2-16   evaluate_0.14      labeling_0.3
## [25] inline_0.3.15      callr_3.3.2        ps_1.3.0
## [28] parallel_3.6.1     bayesplot_1.7.0    rstantools_2.0.0
## [31] highr_0.8          scales_1.0.0       backports_1.1.5
## [34] checkmate_1.9.4    StanHeaders_2.19.2 abind_1.4-5
## [37] gridExtra_2.3      digest_0.6.21      stringi_1.4.3
## [40] processx_3.4.1     grid_3.6.1         cli_1.1.0
## [43] tools_3.6.1        magrittr_1.5       lazyeval_0.2.2
## [46] Formula_1.2-3      crayon_1.3.4       pkgconfig_2.0.3
## [49] zeallot_0.1.0      prettyunits_1.0.2  ggridges_0.5.1
## [52] assertthat_0.2.1   rmarkdown_1.16     R6_2.4.0
## [55] compiler_3.6.1