diff --git a/DESCRIPTION b/DESCRIPTION index d10eb9f..86b91fd 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,12 +5,11 @@ Version: 0.2.0 Author: Jan Meis Maintainer: Jan Meis Description: This package contains methods to calculate optimal design parameters - for one- two-stage three-arm group-sequential gold-standard - non-inferiority designs + for one- and two-stage three-arm group-sequential gold-standard + non-inferiority trial designs with or without binding or nonbinding futility boundaries. License: GPL (>= 3) Encoding: UTF-8 -LazyData: true Depends: R (>= 3.5) Imports: @@ -28,12 +27,9 @@ Suggests: covr, fpCompare, mnormt, - future, - doFuture, - foreach, - doRNG, + future.apply Config/testthat/edition: 3 -RoxygenNote: 7.2.0 +RoxygenNote: 7.2.3 Collate: 'pmv_upper_smaller_slower_fix.R' 'conditional_probability_functions.R' diff --git a/NAMESPACE b/NAMESPACE index 7cd0c52..a6859bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,8 +2,6 @@ S3method(print,OneStageGoldStandardDesign) S3method(print,TwoStageGoldStandardDesign) -export(calc_conditional_local_rejection_probs) -export(calc_conditional_power) export(optimize_design_onestage) export(optimize_design_twostage) importFrom(cli,console_width) diff --git a/R/conditional_probability_functions.R b/R/conditional_probability_functions.R index f85d1eb..5a1fa2b 100644 --- a/R/conditional_probability_functions.R +++ b/R/conditional_probability_functions.R @@ -47,12 +47,8 @@ conditional_Sigma <- function(x_a, mu_a, mu_b, Sigma) { #' @template D #' #' @return numeric value of the conditional power. -#' @export #' @importFrom stats qnorm #' -#' @examples -#' D <- optimize_design_twostage(nloptr_opts = list(maxeval = 1, algorithm = "NLOPT_LN_SBPLX")) -#' calc_conditional_power(.2, .3, D) calc_conditional_power <- function(Z_TP1, Z_TC1, D) { b <- D$b mu <- D$mu_vec[["H1"]] @@ -136,12 +132,8 @@ calc_conditional_power <- function(Z_TP1, Z_TC1, D) { #' @template mu_vec #' #' @return named numeric vector with both conditional type I errors. -#' @export #' @importFrom stats qnorm #' -#' @examples -#' D <- optimize_design_twostage(nloptr_opts = list(maxeval = 1, algorithm = "NLOPT_LN_SBPLX")) -#' calc_conditional_local_rejection_probs(.2, .3, D) calc_conditional_local_rejection_probs <- function(Z_TP1, Z_TC1, D, mu_vec = D$mu_vec$H0) { if (!D$always_both_futility_tests){ warning("Testing procedure not closed. Changing design characteristics at interim based on the conditional rejection probability princple may lead to inflated family-wise type I error if only local type I error rates are considered.") diff --git a/README.Rmd b/README.Rmd index 132345f..9179026 100644 --- a/README.Rmd +++ b/README.Rmd @@ -18,6 +18,7 @@ knitr::opts_chunk$set( # OptimalGoldstandardDesigns +[![doi](https://img.shields.io/badge/doi-10.1002%2Fsim.9630-blue)](https://doi.org/10.1002/sim.9630) [![Codecov test coverage](https://codecov.io/gh/jan-imbi/OptimalGoldstandardDesigns/branch/master/graph/badge.svg)](https://app.codecov.io/gh/jan-imbi/OptimalGoldstandardDesigns?branch=master) [![R-CMD-check](https://github.com/jan-imbi/OptimalGoldstandardDesigns/workflows/R-CMD-check/badge.svg)](https://github.com/jan-imbi/OptimalGoldstandardDesigns/actions) [![License](https://img.shields.io/github/license/jan-imbi/OptimalGoldstandardDesigns)](https://github.com/jan-imbi/OptimalGoldstandardDesigns/blob/master/LICENSE.md) diff --git a/README.md b/README.md index 0893a01..716ea6a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ +[![doi](https://img.shields.io/badge/doi-10.1002%2Fsim.9630-blue)](https://doi.org/10.1002/sim.9630) [![Codecov test coverage](https://codecov.io/gh/jan-imbi/OptimalGoldstandardDesigns/branch/master/graph/badge.svg)](https://app.codecov.io/gh/jan-imbi/OptimalGoldstandardDesigns?branch=master) [![R-CMD-check](https://github.com/jan-imbi/OptimalGoldstandardDesigns/workflows/R-CMD-check/badge.svg)](https://github.com/jan-imbi/OptimalGoldstandardDesigns/actions) diff --git a/inst/CITATION b/inst/CITATION new file mode 100644 index 0000000..68695df --- /dev/null +++ b/inst/CITATION @@ -0,0 +1,17 @@ +citHeader("To cite OptimalGoldstandardDesigns in publications use:") + +citEntry( +entry = "Article", +author = as.person("Jan Meis, Maximilian Pilz, Carolin Herrmann, Björn Bokelmann, Geraldine Rauch, Meinhard Kieser"), +title = "Optimization of the two-stage group sequential three-arm gold-standard design for non-inferiority trials", +journal = "Statistics in Medicine", +volume = "42", +number = "4", +pages = "536-558", +keywords = "gold-standard design, group sequential, hierarchical testing, non-inferiority, optimal design", +doi = "https://doi.org/10.1002/sim.9630", +year = {2023}, + textVersion = paste( + "Meis, J, Pilz, M, Herrmann, C, Bokelmann, B, Rauch, G, Kieser, M. Optimization of the two-stage group sequential three-arm gold-standard design for non-inferiority trials. Statistics in Medicine. 2023; 42( 4): 536– 558. doi:10.1002/sim.9630" + ) +) diff --git a/man/calc_conditional_local_rejection_probs.Rd b/man/calc_conditional_local_rejection_probs.Rd index b5942a4..e11c445 100644 --- a/man/calc_conditional_local_rejection_probs.Rd +++ b/man/calc_conditional_local_rejection_probs.Rd @@ -21,7 +21,3 @@ named numeric vector with both conditional type I errors. \description{ Calculate the (local) conditional type I errors of both hypothesis given both interim test statistics. } -\examples{ -D <- optimize_design_twostage(nloptr_opts = list(maxeval = 1, algorithm = "NLOPT_LN_SBPLX")) -calc_conditional_local_rejection_probs(.2, .3, D) -} diff --git a/man/calc_conditional_power.Rd b/man/calc_conditional_power.Rd index 2d25c0d..649c3e5 100644 --- a/man/calc_conditional_power.Rd +++ b/man/calc_conditional_power.Rd @@ -19,7 +19,3 @@ numeric value of the conditional power. \description{ Calculate the conditional power to reject both hypothesis given both interim test statistics. } -\examples{ -D <- optimize_design_twostage(nloptr_opts = list(maxeval = 1, algorithm = "NLOPT_LN_SBPLX")) -calc_conditional_power(.2, .3, D) -} diff --git a/vignettes/Comparison_with_other_software.Rmd b/vignettes/Comparison_with_other_software.Rmd deleted file mode 100644 index 730cbbe..0000000 --- a/vignettes/Comparison_with_other_software.Rmd +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Comparison_with_other_software" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{Comparison_with_other_software} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -```{r setup} -library(OptimalGoldstandardDesigns) -``` - -TODO: Work in progress. diff --git a/vignettes/Design_adaptations_at_interim.Rmd b/vignettes/Design_adaptations_at_interim.Rmd deleted file mode 100644 index 4c7fafb..0000000 --- a/vignettes/Design_adaptations_at_interim.Rmd +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Design_adaptations_at_interim" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{Design_adaptations_at_interim} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -```{r setup} -library(OptimalGoldstandardDesigns) -``` - - -TODO: Work in progress. diff --git a/vignettes/Introduction.Rmd b/vignettes/Introduction.Rmd index 26ed994..b62b00d 100644 --- a/vignettes/Introduction.Rmd +++ b/vignettes/Introduction.Rmd @@ -1,5 +1,5 @@ --- -title: "Introduction" +title: "Usage guidance" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction} @@ -18,5 +18,213 @@ knitr::opts_chunk$set( library(OptimalGoldstandardDesigns) ``` +# Introduction +This package assumes that a hierarchical testing procedure +for the three-arm gold-standard non-inferiority design is applied. +The first test aims to establish assay sensitivity of the trial. It is a test of +superiority of the experimental treatment (T) against the placebo treatment (P). +If assay sensitivity is successfully established, the treatment is tested +for non-inferiority against the control treatment (C). +Individual observations are assumed to be normally distributed, where higher values +correspond to better treatment effects. Testing is assumed to be done via +Z test statistics. + +We highly recommend reading our open-access article +[(Meis et al., 2022)](https://doi.org/10.1002/sim.9630) +where the theoretical background of this package is explained. + +# Some examples from the paper +To showcase the capabilities of this package, we will reproduce some results +from the paper in the following. + +It should be noted that the results will not completely agree with the +results from the paper, as the calculations in the paper used much +lower error tolerances and more function evaluations. + +To achieve results closer to the results from the paper, you can +supply the following options, though this will significantly increase +computation times: + +```{r, eval=FALSE} + mvnorm_algorithm = mvtnorm::Miwa( + # steps = 128, + steps = 4097, + checkCorr = FALSE, + maxval = 1000), + nloptr_opts = list(algorithm = "NLOPT_LN_SBPLX", + # xtol_abs = 1e-3, + # xtol_rel = 1e-2, + # maxeval = 2000, + xtol_abs = 1e-10, + xtol_rel = 1e-9, + maxeval = 2000, + print_level = 0) +``` + +You may also want to put + +```{r} +print_progress = TRUE +``` + +when running code interactively to see the progress of the optimization. + +## Design from Table 2 +The designs from in Table 2 from the paper are optimized to minimize the +expected sample size under the alternative hypothesis. + +### Design 1, $\beta = 0.2$ +This is (approximately) the first line in Table 2 from the paper: +```{r} +tab1_D1 <- optimize_design_onestage( + alpha = .025, + beta = .2, + alternative_TP = .4, + alternative_TC = 0, + Delta = .2, + print_progress = FALSE +) +tab1_D1 +``` + +### Design 2, $\beta = 0.2$ +This is (approximately) the second line in Table 2 from the paper: + +```{r} +optimize_design_twostage( + cP1 = tab1_D1$stagec[[1]]$P, # The allocation ratios are enforced to be + cC1 = tab1_D1$stagec[[1]]$C, # the same as in the optimal single-stage design. + cT2 = 1, + cP2 = tab1_D1$stagec[[1]]$P, + cC2 = tab1_D1$stagec[[1]]$C, + + bTP1f = -Inf, # These two boundary conditions enforce no futility stops. + bTC1f = -Inf, + + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE +) +``` + +### Design 3, $\beta = 0.2$ +This is (approximately) the third line in Table 2 from the paper: + +```{r} +optimize_design_twostage( + bTP1f = -Inf, # These two boundary conditions enforce no futility stops. + bTC1f = -Inf, + + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE +) +``` + +### Design 4, $\beta = 0.2$ +This is (approximately) the fourth line in Table 2 from the paper: + +```{r} +optimize_design_twostage( + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE, + binding_futility = FALSE +) +``` + +### Design 5, $\beta = 0.2$ +This is (approximately) the fourth line in Table 2 from the paper: + +```{r} +optimize_design_twostage( + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE, + binding_futility = TRUE +) +``` + + +## Design from Table 3 +Next, we will optimize a design under a combination of null and alternative +hypothesis. + +### Design 5, $\beta = 0.2$, $\lambda = 0.9$ +This is (approximately) the third line in Table 3 from the paper: + +```{r} +optimize_design_twostage( + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE, + binding_futility = TRUE, + lambda = 0.9 +) +``` + +## Design from Table 4 +Now we will optimize a design under the alternative while putting an +extra penalty on placebo group sample size. + +### Design 5, $\beta = 0.2$, $\kappa = 0.5$ +This is (approximately) the fourth line in Table 2 from the paper: + +```{r} +optimize_design_twostage( + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE, + binding_futility = TRUE, + kappa = 0.5 +) +``` + +## Design from Table 5 +Next, we will optimize a design under a combination of null and +alternative hypothesis while including a penalty on the placebo group +sample size. + +### Design 5, $\beta = 0.2$, $\lambda = 0.9$, $\kappa = 1$ +This is (approximately) the seventh line in Table 2 from the paper: + +## Other options +### Optimizing between group allocation with enforced between stage allocation at 1 + +```{r} +optimize_design_twostage( + cP1 = tab1_D1$stagec[[1]]$P, # The allocation ratios are enforced to be + cC1 = tab1_D1$stagec[[1]]$C, # the same as in the optimal single-stage design. + cT2 = 1, + cP2 = tab1_D1$stagec[[1]]$P, + cC2 = tab1_D1$stagec[[1]]$C, + + bTP1f = -Inf, # These two boundary conditions enforce no futility stops. + bTC1f = -Inf, + + beta = 0.2, + alternative_TP = 0.4, + alternative_TC = 0, + Delta = 0.2, + print_progress = FALSE +) +``` + + +# References +Meis, J, Pilz, M, Herrmann, C, Bokelmann, B, Rauch, G, Kieser, M. Optimization of the two-stage group +sequential three-arm gold-standard design for non-inferiority trials. *Statistics in Medicine.* 2023; 42( +4): 536– 558. [doi:10.1002/sim.9630](https://doi.org/10.1002/sim.9630). -TODO: Work in progress. diff --git a/vignettes/mathematical_details.Rmd b/vignettes/mathematical_details.Rmd deleted file mode 100644 index 2b3bfe3..0000000 --- a/vignettes/mathematical_details.Rmd +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: "Mathematical details" -output: rmarkdown::html_vignette -vignette: > - %\VignetteIndexEntry{mathematical_details} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteEncoding{UTF-8} ---- - -```{r, include = FALSE} -knitr::opts_chunk$set( - collapse = TRUE, - comment = "#>" -) -``` - -```{r setup} -library(OptimalGoldstandardDesigns) -``` - -The version of the three arm gold-standard non-inferiority design used in this package assumes a -hierarchical testing procedure is applied. -The first test aims to establish assay sensitivity of the trial. It is a test of -superiority of the experimental treatment (T) against the placebo treatment (P). -If assay sensitivity is successfully established, the treatment is tested for non-inferiority -to the control treatment (C). - -Individual observations are assumed to be normally distributed, where higher values -correspond to better treatment effects. We denote the test statistics for the -two hypothesis by Z_TP1 and Z_TC1, where Z_TC1 already incorporates -the non-inferiority margin \eqn{\Delta}. The respective critical values are given by -bTP1e, bTC1e, bTP2e and bTC2e. (The optimizer searches for the optimal values of bTP1e and -bTC1e, while bTP2e and bTC2e are implicitly defined.) - -TODO: Work in progress. -