Fast and efficient simulation tools for Bayesian Optimal Interval (BOIN) designs in Phase I clinical trials.
Overview
simFastBOIN provides comprehensive functions for simulating Phase I dose-finding trials using the BOIN design methodology. The package enables researchers to evaluate operating characteristics and design performance across different dose-toxicity scenarios, essential for protocol development and regulatory submissions.
Key Features:
- High Performance: Vectorized implementation and optimized algorithms
- BOIN Compatible: Results match BOIN package within <0.5% across all scenarios
- User-Friendly: Simplified API with automatic decision table generation
- Flexible: Multiple safety stopping rules and customizable design parameters
- Multi-Scenario Support: Evaluate multiple dose-toxicity scenarios simultaneously
- Conservative MTD Selection: Optional boundMTD constraint for enhanced safety
- Publication-Ready Output: Professional table formatting with HTML, LaTeX, and Markdown options
Installation
You can install the development version from GitHub:
# Install if not already installed # install.packages("devtools") devtools::install_github("gosukehommaEX/simFastBOIN")
Quick Start
Basic Usage
library(simFastBOIN) # Define design parameters target <- 0.30 # Target DLT rate (30%) p_true <- seq(0.05, 0.45, by = 0.05) # True toxicity probabilities # Run simulation (runs silently by default) result <- sim_boin( n_trials = 10000, target = target, p_true = p_true, n_cohort = 20, cohort_size = 3, seed = 123 ) # Display results print(result$summary) # To see progress messages, use verbose = TRUE result_verbose <- sim_boin( n_trials = 10000, target = target, p_true = p_true, n_cohort = 20, cohort_size = 3, verbose = TRUE, # Show progress seed = 123 )
Enhanced Output Formatting
# Display with percentages instead of absolute numbers print(result$summary, percent = TRUE) # Display in Markdown pipe format for R Markdown documents print(result$summary, kable = TRUE, kable_format = "pipe") # LaTeX format for publication print(result$summary, kable = TRUE, kable_format = "latex", scenario_name = "My Scenario") # HTML format for web display print(result$summary, kable = TRUE, kable_format = "html")
Multi-Scenario Simulations
# Define multiple dose-toxicity scenarios scenarios <- list( list(name = "Scenario 1: Linear Increase", p_true = c(0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45)), list(name = "Scenario 2: Steep Early", p_true = c(0.01, 0.025, 0.05, 0.075, 0.10, 0.125, 0.15, 0.20, 0.30)), list(name = "Scenario 3: Plateau", p_true = c(0.15, 0.20, 0.25, 0.30, 0.45, 0.50, 0.50, 0.50, 0.50)) ) # Run simulations across all scenarios result <- sim_boin_multi( scenarios = scenarios, target = 0.30, n_trials = 10000, n_cohort = 48, cohort_size = 3, seed = 123 ) # View aggregated results print(result) # View as HTML table print(result, kable = TRUE, kable_format = "html") # Access scenario-specific results result$results_by_scenario[["Scenario 1: Linear Increase"]]
Main Functions
Simulation
-
sim_boin(): Run BOIN trial simulations with automatic decision table generation- Automatically generates BOIN boundaries and decision tables
- Optional safety stopping rules (
extrasafe,boundMTD) - Flexible stopping criteria (
n_earlystop_rule) - Returns detailed trial-level results and summary statistics
-
sim_boin_multi(): Run simulations across multiple scenarios- Orchestrates
sim_boin()for each scenario automatically - Aggregates results into a unified comparison table
- Ideal for protocol development evaluating multiple dose-toxicity relationships
- Orchestrates
Design Setup
get_boin_boundary(): Calculate BOIN interval boundaries (lambda_e, lambda_d)get_boin_decision(): Generate decision table for dose escalation/de-escalationget_boin_stopping_boundaries(): Generate safety stopping boundaries
MTD Selection
isotonic_regression(): Apply isotonic regression to estimate dose-toxicity curveselect_mtd(): Select MTD with optional boundMTD constraint
Utilities
print.boin_summary(): Print formatted summary tables with flexible optionsprint.boin_multi_summary(): Print multi-scenario summary tables
Performance
simFastBOIN uses vectorized operations and efficient algorithms for superior performance:
Benchmark (5 doses, 20 cohorts, cohort_size=3, all safety features enabled):
| Number of Trials | simFastBOIN | BOIN Package | Speedup |
|---|---|---|---|
| 1,000 | 0.02 sec | 0.63 sec | 31.5x |
| 10,000 | 0.17 sec | 6.74 sec | 39.6x |
| 100,000 | 2.0 sec | 80.2 sec | 40.1x |
Results validated against the BOIN package using comprehensive test scenarios. All operating characteristics (MTD selection rates, sample sizes, toxicity counts) matched within <0.5%.
BOIN Package Compatibility
simFastBOIN produces results identical to the original BOIN package while offering significantly improved performance. This makes it ideal as a drop-in replacement for large-scale simulations where speed is critical.
Validation Against BOIN Package
Comprehensive validation was conducted comparing simFastBOIN with BOIN::get.oc() across multiple configurations:
Test Design:
-
Test Scenarios: 5 dose-toxicity scenarios (5 doses each)
- scenario1: c(0.05, 0.10, 0.20, 0.30, 0.45) - MTD at dose 4
- scenario2: c(0.30, 0.40, 0.50, 0.60, 0.70) - All doses ≥ target
- scenario3: c(0.05, 0.10, 0.15, 0.20, 0.25) - All doses < target
- scenario4: c(0.15, 0.30, 0.45, 0.60, 0.75) - MTD at dose 2
- scenario5: c(0.01, 0.03, 0.08, 0.15, 0.30) - MTD at dose 5
-
Parameter Combinations: 8 configurations per scenario
- extrasafe = TRUE/FALSE
- boundMTD = TRUE/FALSE
- titration = TRUE/FALSE
-
Total Configurations: 40 (5 scenarios × 8 parameter combinations)
-
Trials per Configuration: 10,000
Validation Results:
| Metric | Match Rate | Maximum Difference |
|---|---|---|
| PCS (MTD Selection %) | 100% (40/40) | 1.29% |
| Avg Patients per Dose | 100% (40/40) | 0.29 patients |
| Avg DLTs per Dose | 100% (40/40) | 0.10 DLTs |
| No MTD Selection Rate | 100% (40/40) | 0.76% |
Conclusion: All 40 configurations showed perfect metric match (all_match = TRUE) with simFastBOIN and BOIN package results. Maximum differences across all metrics were well within acceptable tolerance levels, confirming full compatibility.
Implementation Details
- Results validated across all scenario types (favorable, unfavorable, balanced)
- Testing included all major design options:
- Safety stopping rules (extrasafe TRUE/FALSE)
- MTD selection constraints (boundMTD TRUE/FALSE)
- Titration phase options (titration TRUE/FALSE)
- Same random number generation (when seed is fixed)
- Full compatibility with BOIN methodology
Features
1. boundMTD: Conservative MTD Selection
The boundMTD option provides an additional safety constraint during MTD selection:
# Without boundMTD: may select doses near toxicity boundary result1 <- sim_boin( n_trials = 1000, target = 0.30, p_true = c(0.10, 0.20, 0.28, 0.36, 0.50, 0.65), n_cohort = 20, cohort_size = 3, boundMTD = FALSE, seed = 123 ) # With boundMTD: more conservative selection result2 <- sim_boin( n_trials = 1000, target = 0.30, p_true = c(0.10, 0.20, 0.28, 0.36, 0.50, 0.65), n_cohort = 20, cohort_size = 3, boundMTD = TRUE, seed = 123 )
Selected MTD must have isotonic-estimated toxicity rate below the de-escalation boundary (lambda_d), preventing selection of doses too close to overly toxic doses.
2. n_earlystop_rule: Stopping Criteria
Two stopping rules are available:
"simple" (Backward Compatible)
- Stop when sample size at current dose reaches
n_earlystop - Faster trials, fewer patients
"with_stay" (BOIN Standard)
- Stop when sample size reaches
n_earlystopAND next decision is "Stay" - Ensures algorithm convergence before stopping
- More thorough dose evaluation
# Simple rule: Stop immediately at n_earlystop result_simple <- sim_boin( n_trials = 1000, target = 0.30, p_true = c(0.05, 0.10, 0.20, 0.30, 0.45, 0.60), n_cohort = 20, cohort_size = 3, n_earlystop_rule = "simple", seed = 123 ) # With stay: Wait for convergence result_with_stay <- sim_boin( n_trials = 1000, target = 0.30, p_true = c(0.05, 0.10, 0.20, 0.30, 0.45, 0.60), n_cohort = 20, cohort_size = 3, n_earlystop_rule = "with_stay", seed = 123 )
3. extrasafe: Safety Stopping at Lowest Dose
Additional safety rule to stop the entire trial if the lowest dose is overly toxic:
result <- sim_boin( n_trials = 10000, target = 0.30, p_true = seq(0.05, 0.45, by = 0.05), n_cohort = 48, cohort_size = 3, extrasafe = TRUE, # Enable safety stopping offset = 0.05, # Cutoff = cutoff_eli - offset seed = 123 )
4. Output Formatting
Multiple output format options for different use cases:
# Plain text (default) print(result$summary) # With percentages print(result$summary, percent = TRUE) # Markdown pipe format (for RMarkdown) print(result$summary, kable = TRUE, kable_format = "pipe") # LaTeX format (for publications) print(result$summary, kable = TRUE, kable_format = "latex") # HTML format (for web display) print(result$summary, kable = TRUE, kable_format = "html") # Simple format (minimal formatting) print(result$summary, kable = TRUE, kable_format = "simple") # Combine options print(result$summary, scenario_name = "My Analysis", percent = TRUE, kable = TRUE)
BOIN Standard Implementation
Recommended settings for BOIN standard compliance:
result <- sim_boin( n_trials = 10000, target = 0.30, p_true = c(0.10, 0.25, 0.40, 0.55, 0.70), n_cohort = 10, cohort_size = 3, boundMTD = TRUE, # Conservative MTD selection n_earlystop_rule = "with_stay", # Stop when converged extrasafe = TRUE, # Safety monitoring seed = 123 ) print(result$summary, scenario_name = "BOIN Standard")
Complete Workflow Example
library(simFastBOIN) # Step 1: Define scenario target <- 0.30 p_true <- c(0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45) # Step 2: Run simulation result <- sim_boin( n_trials = 10000, target = target, p_true = p_true, n_cohort = 48, cohort_size = 3, boundMTD = TRUE, n_earlystop_rule = "with_stay", extrasafe = TRUE, return_details = TRUE, # Enable detailed trial-level results seed = 123 ) # Step 3: Display results print(result$summary, scenario_name = "Primary Analysis") # Step 4: Export for RMarkdown print(result$summary, kable = TRUE, kable_format = "pipe") # Step 5: Check stopping reasons table(sapply(result$detailed_results, function(x) x$reason))
Stopping Reasons
The package tracks why each trial terminated:
"trial_completed": Normal completion"n_earlystop_reached": Reached sample size limit (simple rule)"n_earlystop_with_stay": Converged at sample size limit (with_stay rule)"lowest_dose_too_toxic": Safety stopping at lowest dose (extrasafe)"lowest_dose_eliminated": Lowest dose eliminated during trial"no_dose_below_lambda_d": No dose satisfies boundMTD constraint"max_cohorts_reached": Maximum number of cohorts completed
References
Liu, S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507–523.
Version History
See NEWS.md for detailed version history and changelog.
License
MIT © Gosuke Homma