An S4 generic method providing a more abstract interface to trial simulation than the simulate_trials function of package escalation. This abstraction is needed to support simulations in which escalation's simple vectors of ‘true toxicity probabilities’ are replaced by precautionary's more realistic toxicity-distribution generators.

simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

# S4 method for selector_factory,numeric,hyper_mtdi_distribution,ANY
simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

# S4 method for selector_factory,numeric,mtdi_distribution,ANY
simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

# S4 method for exact,missing,mtdi_distribution,ANY
simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

# S4 method for exact,numeric,mtdi_distribution,missing
simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

# S4 method for exact,numeric,hyper_mtdi_distribution,missing
simulate_trials(
  selector_factory,
  num_sims,
  true_prob_tox,
  true_prob_eff = NULL,
  ...
)

Arguments

selector_factory

An object of S3 class selector_factory

num_sims

Number of simulations to run

true_prob_tox

A generator of toxicity distributions

true_prob_eff

Provided for compatibility with simulate_trials

...

Passed to subroutines

Details

If invoked interactively with num_sims > 10, then a txtProgressBar is displayed in the console. The condition on num_sims has the useful side effect of allowing this function to be invoked iteratively by extend (with num_sims = 10) without the nuisance of nested progress bars.

Examples

old <- options(dose_levels = c(0.5, 1, 2, 4, 6, 8))
mtdi_gen <- hyper_mtdi_lognormal(CV = 1
                                 , median_mtd = 6, median_sdlog = 0.5
                                 , units="mg/kg")
num_sims <- ifelse(interactive()
, 300
, 15 # avoid taxing CRAN servers
)
hsims <- get_three_plus_three(num_doses = 6,
                              allow_deescalate = TRUE) %>%
  simulate_trials(
    num_sims = num_sims
  , true_prob_tox = mtdi_gen)
summary(hsims, ordinalizer=NULL) # vanilla summary with binary toxicity
#> # A tibble: 7 × 7
#>   dose   `dose (mg/kg)`   tox     n true_prob_tox prob_recommend prob_administer
#>   <ord>           <dbl> <dbl> <dbl>         <dbl>          <dbl>           <dbl>
#> 1 NoDose            0   0       0               0          0              0     
#> 2 1                 0.5 0       3               0          0              0.158 
#> 3 2                 1   0.133   3.4             0          0.133          0.179 
#> 4 3                 2   0.6     4.2             0          0.267          0.221 
#> 5 4                 4   0.933   4.2             0          0.333          0.221 
#> 6 5                 6   1.2     3               0          0              0.158 
#> 7 6                 8   0.133   1.2             0          0.267          0.0632
summary(hsims, ordinalizer = function(dose, r0 = sqrt(2))
  c(Gr1=dose/r0^2, Gr2=dose/r0, Gr3=dose, Gr4=dose*r0, Gr5=dose*r0^2)
)
#> $escalation
#> # A tibble: 7 × 7
#>   dose   `dose (mg/kg)`   tox     n true_prob_tox prob_recommend prob_administer
#>   <ord>           <dbl> <dbl> <dbl>         <dbl>          <dbl>           <dbl>
#> 1 NoDose            0   0       0               0          0              0     
#> 2 1                 0.5 0       3               0          0              0.158 
#> 3 2                 1   0.133   3.4             0          0.133          0.179 
#> 4 3                 2   0.6     4.2             0          0.267          0.221 
#> 5 4                 4   0.933   4.2             0          0.333          0.221 
#> 6 5                 6   1.2     3               0          0              0.158 
#> 7 6                 8   0.133   1.2             0          0.267          0.0632
#> 
#> $safety
#>   None  Gr1  Gr2  Gr3  Gr4  Gr5  Total
#>     13    1    1    2    1    1     19
#> 
#> $toxTab
#>     Tox
#> rep  None Gr1 Gr2 Gr3 Gr4 Gr5 Total
#>   1    16   2   0   0   0   0    18
#>   2    11   0   3   2   2   0    18
#>   3    19   1   2   2   0   0    24
#>   4     9   3   0   2   1   0    15
#>   5    10   1   0   1   3   0    15
#>   6    18   0   0   0   0   0    18
#>   7    10   4   2   3   1   1    21
#>   8    10   1   4   1   1   1    18
#>   9    12   1   1   1   1   2    18
#>   10    9   2   0   3   0   1    15
#>   11   18   0   1   2   0   0    21
#>   12   16   1   0   1   1   2    21
#>   13   18   2   2   1   1   0    24
#>   14   14   1   0   2   1   0    18
#>   15   12   1   3   4   0   1    21
#> 
hsims <- hsims %>% extend(num_sims = num_sims)
summary(hsims, ordinalizer = function(dose, r0 = sqrt(2))
  c(Gr1=dose/r0^2, Gr2=dose/r0, Gr3=dose, Gr4=dose*r0, Gr5=dose*r0^2)
)$safety
#>   None  Gr1  Gr2  Gr3  Gr4  Gr5  Total
#>     12    1    1    2    1    1     18
# Set a CRM skeleton from the average probs in above simulation
num_sims <- ifelse(interactive()
, 16
,  4  # avoid taxing CRAN servers
)
get_dfcrm(skeleton = hsims$avg_prob_tox
         ,target = 0.25
         ) %>% stop_at_n(n = 24) %>%
  simulate_trials(
    num_sims = num_sims
  , true_prob_tox = mtdi_gen
  ) -> crm_hsims
summary(crm_hsims
, ordinalizer = function(MTDi, r0 = sqrt(2))
    MTDi * r0^c(Gr1=-2, Gr2=-1, Gr3=0, Gr4=1, Gr5=2)
)
#> $escalation
#> # A tibble: 7 × 7
#>   dose   `dose (mg/kg)`   tox     n true_prob_tox prob_recommend prob_administer
#>   <ord>           <dbl> <dbl> <dbl>         <dbl>          <dbl>           <dbl>
#> 1 NoDose            0    0     0                0           0             0     
#> 2 1                 0.5  0.25  3.75             0           0             0.156 
#> 3 2                 1    0     0.75             0           0             0.0312
#> 4 3                 2    1.25  6                0           0.5           0.25  
#> 5 4                 4    2.5  12                0           0.25          0.5   
#> 6 5                 6    0     0                0           0.25          0     
#> 7 6                 8    1.25  1.5              0           0             0.0625
#> 
#> $safety
#>   None  Gr1  Gr2  Gr3  Gr4  Gr5  Total
#>     15    2    2    2    2    1   24.0
#> 
#> $toxTab
#>    Tox
#> rep None Gr1 Gr2 Gr3 Gr4 Gr5 Total
#>   1   14   2   3   3   2   0    24
#>   2   12   1   3   3   1   4    24
#>   3   18   1   1   1   3   0    24
#>   4   16   2   2   3   0   1    24
#> 
options(old)
old <- options(dose_levels = c(2, 6, 20, 60, 180, 400))
mtdi_dist <- mtdi_lognormal(CV = 0.5
                           ,median = 140
                           ,units = "ng/kg/week")
num_sims <- ifelse(interactive()
, 100
,  10  # avoid taxing CRAN servers
)
sims <- get_three_plus_three(num_doses = 6) %>%
  simulate_trials(
    num_sims = num_sims
  , true_prob_tox = mtdi_dist)
# Now set a proper ordinalizer via options():
options(ordinalizer = function(dose, r0) {
  c(Gr1=dose/r0^2, Gr2=dose/r0, Gr3=dose, Gr4=dose*r0, Gr5=dose*r0^2)
})
summary(sims, r0=2)
#> $escalation
#> # A tibble: 7 × 7
#>   dose   `dose (ng/kg/week)`   tox     n true_prob_tox prob_recommend
#>   <ord>                <dbl> <dbl> <dbl>         <dbl>          <dbl>
#> 1 NoDose                   0   0     0        0                   0  
#> 2 1                        2   0     3        1.19e-19            0  
#> 3 2                        6   0     3        1.30e-11            0  
#> 4 3                       20   0     3        1.90e- 5            0  
#> 5 4                       60   0.2   3.6      3.64e- 2            0.9
#> 6 5                      180   2.2   3.3      7.03e- 1            0.1
#> 7 6                      400   0.3   0.3      9.87e- 1            0  
#> # … with 1 more variable: prob_administer <dbl>
#> 
#> $safety
#>   None  Gr1  Gr2  Gr3  Gr4  Gr5  Total
#>      9    2    2    2    1    0     16
#> 
#> $toxTab
#>     Tox
#> rep  None Gr1 Gr2 Gr3 Gr4 Gr5 Total
#>   1     9   1   3   1   1   0    15
#>   2     9   3   1   0   2   0    15
#>   3     9   3   2   4   0   0    18
#>   4     9   2   2   1   1   0    15
#>   5    10   2   3   0   1   2    18
#>   6     9   3   1   1   1   0    15
#>   7     8   1   3   1   2   0    15
#>   8    10   4   3   3   1   0    21
#>   9     8   2   2   3   0   0    15
#>   10    9   1   3   2   0   0    15
#> 
# Set a CRM skeleton from the average probs in above simulation
get_dfcrm(skeleton = sims$true_prob_tox
         ,target = 0.25
         ) %>% stop_at_n(n = 24) %>%
  simulate_trials(
    num_sims = 20
  , true_prob_tox = mtdi_dist
  ) -> crm_sims
summary(crm_sims
, ordinalizer = function(MTDi, r0 = sqrt(2))
    MTDi * r0^c(Gr1=-2, Gr2=-1, Gr3=0, Gr4=1, Gr5=2)
)
#> $escalation
#> # A tibble: 7 × 7
#>   dose   `dose (ng/kg/week)`   tox     n true_prob_tox prob_recommend
#>   <ord>                <dbl> <dbl> <dbl>         <dbl>          <dbl>
#> 1 NoDose                   0  0     0         0                  0   
#> 2 1                        2  0     3         1.19e-19           0   
#> 3 2                        6  0     0         1.30e-11           0   
#> 4 3                       20  0     0         1.90e- 5           0   
#> 5 4                       60  0.6  17.0       3.64e- 2           0.95
#> 6 5                      180  2.55  4.05      7.03e- 1           0.05
#> 7 6                      400  0     0         9.87e- 1           0   
#> # … with 1 more variable: prob_administer <dbl>
#> 
#> $safety
#>   None  Gr1  Gr2  Gr3  Gr4  Gr5  Total
#>     14    4    3    2    1    1   24.0
#> 
#> $toxTab
#>     Tox
#> rep  None Gr1 Gr2 Gr3 Gr4 Gr5 Total
#>   1    13   8   2   0   1   0    24
#>   2    13   2   4   3   1   1    24
#>   3    14   6   1   2   1   0    24
#>   4    15   4   3   1   0   1    24
#>   5    16   3   2   2   1   0    24
#>   6    14   3   3   2   1   1    24
#>   7    14   3   4   1   1   1    24
#>   8    16   3   1   2   1   1    24
#>   9    15   3   3   2   0   1    24
#>   10    9   6   4   2   1   2    24
#>   11   14   5   3   0   1   1    24
#>   12   12   4   6   1   1   0    24
#>   13   16   5   1   2   0   0    24
#>   14   14   5   3   2   0   0    24
#>   15   16   4   1   2   1   0    24
#>   16   17   5   1   1   0   0    24
#>   17    9   4   5   2   2   2    24
#>   18   10   2   6   2   1   3    24
#>   19   17   4   1   0   2   0    24
#>   20   13   3   4   1   3   0    24
#> 
if (interactive()) { # don't overtax CRAN servers
crm_sims <- crm_sims %>% extend(target_mcse = 0.1)
summary(crm_sims
, ordinalizer = function(MTDi, r0 = sqrt(2))
    MTDi * r0^c(Gr1=-2, Gr2=-1, Gr3=0, Gr4=1, Gr5=2)
)$safety
}
options(old)
old <- options(
  dose_levels = c(0.5, 1, 2, 4, 6),
  ordinalizer = function(MTDi, r0 = 1.5) {
    MTDi * r0 ^ c(Gr1=-2, Gr2=-1, Gr3=0, Gr4=1, Gr5=2)
  })
mtdi_dist <- mtdi_lognormal(CV = 2
                            ,median = 5
                            ,units = "mg/kg")
design <- get_three_plus_three(num_doses = 5, allow_deescalate = TRUE)
# Note use of wrapper function 'exact'; see ?precautionary::exact.
exact(design) %>% simulate_trials(true_prob_tox = mtdi_dist) -> EXACT
stopifnot(all.equal(1, sum(exp(EXACT$log_pi))))
summary(EXACT)$safety
#>       
#>            None      Gr1      Gr2      Gr3       Gr4      Gr5    Total
#>   [1,] 10.04956 1.591247 1.364949 1.088902 0.8066095 1.317687 16.21896
if (interactive()) { # don't overtax CRAN servers
# Compare with result of discrete-event simulation
design %>% simulate_trials(
  num_sims = 200
  , true_prob_tox = mtdi_dist
) -> SIMS
summary(SIMS)$safety
}
options(old)
old <- options(dose_levels = c(0.5, 1, 2, 4, 6, 8))
mtdi_gen <- hyper_mtdi_lognormal(CV = 1
                                 , median_mtd = 6, median_sdlog = 0.5
                                 , units="mg/kg")
options(ordinalizer = function(dose, r0 = sqrt(2))
  c(Gr1=dose/r0^2, Gr2=dose/r0, Gr3=dose, Gr4=dose*r0, Gr5=dose*r0^2)
)
design <- get_three_plus_three(num_doses = 6, allow_deescalate = TRUE)
ehsims <- simulate_trials(
  exact(design)
  , num_sims = 50
  , true_prob_tox = mtdi_gen
)
summary(ehsims)$safety
#>                             None      Gr1       Gr2        Gr3        Gr4
#> Expected participants 11.8616115 2.086239 1.7305842 1.20890367 0.73808846
#> MCSE                   0.3243027 0.115837 0.1030522 0.05547655 0.02814529
#>                              Gr5      Total
#> Expected participants 0.93582514 18.5612521
#> MCSE                  0.07391789  0.3542685
options(old)