From a181b11fd646564a960942da19b6a6f2566737da Mon Sep 17 00:00:00 2001 From: Bossert Date: Mon, 4 Dec 2023 16:57:10 +0100 Subject: [PATCH 1/4] Minor update --- vignettes/analysis_normal.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/analysis_normal.Rmd b/vignettes/analysis_normal.Rmd index e84ebac..cdd3535 100644 --- a/vignettes/analysis_normal.Rmd +++ b/vignettes/analysis_normal.Rmd @@ -28,7 +28,7 @@ In this vignette we will show the use of the Bayesian MCPMod package for continu Hereby the focus is on the utilization of an informative prior and the BayesianMCPMod evaluation of a single trial. We will use data that is included in the clinDR package. More specifically trial results for BRINTELLIX will be used to illustrate the specification of an informative prior and the usage of such a prior for the bayesian evaluation of a (hypothetical) new trial. -More information around BRINTELLIX to be added... +More information around BRINTELLIX will be added... # Calculation of a MAP prior From f21d98be374d30cef769fda2d02a7e5da017654e Mon Sep 17 00:00:00 2001 From: Bossert Date: Tue, 5 Dec 2023 12:59:57 +0100 Subject: [PATCH 2/4] minor update --- vignettes/Simulation_Example.Rmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/Simulation_Example.Rmd b/vignettes/Simulation_Example.Rmd index bcd8cef..4891721 100644 --- a/vignettes/Simulation_Example.Rmd +++ b/vignettes/Simulation_Example.Rmd @@ -26,7 +26,7 @@ set.seed(7015) # Background and data In this vignette we will show the use of the Bayesian MCPMod package for trial planning for continuous distributed data. -As in [link other vignette] we focus on the indication MDD and make use of historical data that is included in the clinDR package. +As in [link to other vignette] we focus on the indication MDD and make use of historical data that is included in the clinDR package. More specifically trial results for BRINTELLIX will be utilized to establish an informative prior for the control group. # Calculation of a MAP prior From 7a0dac782237d8d8b3c52ae42c7dfac6bc96fc94 Mon Sep 17 00:00:00 2001 From: Wojciekowski Date: Thu, 7 Dec 2023 10:45:48 +0100 Subject: [PATCH 3/4] - updated getPosterior to handle data = NULL - updated vignette accordingly --- R/posterior.R | 48 ++++++++++++++++++++++------------- vignettes/analysis_normal.Rmd | 11 +++++--- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/R/posterior.R b/R/posterior.R index df37f5e..04a88d4 100644 --- a/R/posterior.R +++ b/R/posterior.R @@ -5,9 +5,8 @@ #' @param dose_names prior_list #' @param robustify_weight tbd #' -#' @export getPriorList <- function ( - + hist_data, dose_levels, dose_names = NULL, @@ -66,21 +65,34 @@ getPriorList <- function ( #' @param data tbd #' @param prior_list prior_list #' @param mu_hat tbd -#' @param sd_hat tbd +#' @param se_hat tbd #' #' @export getPosterior <- function( - data, + prior_list, + data = NULL, mu_hat = NULL, - sd_hat = NULL + se_hat = NULL ) { - posterior_list <- lapply(split(data, data$simulation), getPosteriorI, - prior_list = prior_list, - mu_hat = mu_hat, - sd_hat = sd_hat) + if (!is.null(mu_hat) && !is.null(se_hat) && is.null(data)) { + + posterior_list <- getPosteriorI( + data_i = NULL, + prior_list = prior_list, + mu_hat = mu_hat, + se_hat = se_hat) + + } else { + + posterior_list <- lapply(split(data, data$simulation), getPosteriorI, + prior_list = prior_list, + mu_hat = mu_hat, + se_hat = se_hat) + + } if (length(posterior_list) == 1) { @@ -94,33 +106,33 @@ getPosterior <- function( getPosteriorI <- function( - data_i, + data_i = NULL, prior_list, mu_hat = NULL, - sd_hat = NULL + se_hat = NULL ) { - if (is.null(mu_hat) && is.null(sd_hat)) { + if (is.null(mu_hat) && is.null(se_hat)) { anova_res <- stats::lm(data_i$response ~ factor(data_i$dose) - 1) mu_hat <- summary(anova_res)$coefficients[, 1] - sd_hat <- summary(anova_res)$coefficients[, 2] + se_hat <- summary(anova_res)$coefficients[, 2] - } else if (!is.null(mu_hat) && !is.null(sd_hat)) { + } else if (!is.null(mu_hat) && !is.null(se_hat)) { stopifnot("m_hat length must match number of dose levels" = length(prior_list) == length(mu_hat), - "sd_hat length must match number of dose levels" = - length(prior_list) == length(sd_hat)) + "se_hat length must match number of dose levels" = + length(prior_list) == length(se_hat)) } else { - stop ("Both mu_hat and sd_hat must be provided.") + stop ("Both mu_hat and se_hat must be provided.") } - post_list <- mapply(RBesT::postmix, prior_list, m = mu_hat, se = sd_hat) + post_list <- mapply(RBesT::postmix, prior_list, m = mu_hat, se = se_hat) if (is.null(names(prior_list))) { diff --git a/vignettes/analysis_normal.Rmd b/vignettes/analysis_normal.Rmd index cdd3535..94542e7 100644 --- a/vignettes/analysis_normal.Rmd +++ b/vignettes/analysis_normal.Rmd @@ -101,9 +101,14 @@ data_emax <- simulateData( mods = mods, true_model = "emax") -posterior <- getPosterior(prior=prior_list,data=data_emax, - mu_hat = new_trial$rslt, - sd_hat = new_trial$se) +posterior <- getPosterior(prior = prior_list, + data = data_emax) + +posterior <- getPosterior(prior = prior_list, + mu_hat = new_trial$rslt, + se_hat = new_trial$se) + +summary(posterior) ``` From ff9a940b072d43dcf445d6c6944d4b8bcbc07a8b Mon Sep 17 00:00:00 2001 From: Wojciekowski Date: Thu, 7 Dec 2023 12:41:17 +0100 Subject: [PATCH 4/4] - updated getContr() --- R/BMCPMod.R | 80 +++++++++++++++++++++++++++++------ R/s3methods.R | 6 +++ R/simulation.R | 2 +- man/assessDesign.Rd | 1 + man/getContr.Rd | 31 ++++++++++++++ man/getContrMat.Rd | 20 --------- man/getPosterior.Rd | 8 ++-- man/performBayesianMCP.Rd | 4 +- vignettes/analysis_normal.Rmd | 2 +- 9 files changed, 112 insertions(+), 42 deletions(-) create mode 100644 man/getContr.Rd delete mode 100644 man/getContrMat.Rd diff --git a/R/BMCPMod.R b/R/BMCPMod.R index 0a3f56c..cf46575 100644 --- a/R/BMCPMod.R +++ b/R/BMCPMod.R @@ -14,6 +14,8 @@ assessDesign <- function ( mods, prior_list, + sd = NULL, + n_sim = 1e3, alpha_crit_val = 0.05, simple = TRUE @@ -21,11 +23,16 @@ assessDesign <- function ( ) { dose_levels <- attr(prior_list, "dose_levels") + sd <- ifelse(is.null(sd), attr(prior_list, "sd_tot"), sd) + + stopifnot( + "sd length must coincide with number of dose levels" = + length(sd) == length(dose_levels)) data <- simulateData( n_patients = n_patients, dose_levels = dose_levels, - sd = attr(prior_list, "sd_tot"), + sd = sd, mods = mods, n_sim = n_sim) @@ -43,7 +50,7 @@ assessDesign <- function ( dose_weights = n_patients, alpha_crit_val = alpha_crit_val) - contr_mat_prior <- getContrMat( + contr_mat_prior <- getContr( mods = mods, dose_levels = dose_levels, dose_weights = n_patients, @@ -63,31 +70,75 @@ assessDesign <- function ( } -#' @title getContrMat +#' @title getContr #' #' @param mods tbd #' @param dose_levels tbd #' @param dose_weights tbd #' @param prior_list tbd +#' @param se_new_trial tbd +#' @param sd_posterior tbd #' #' @export -getContrMat <- function ( +getContr <- function ( mods, dose_levels, - dose_weights, - prior_list + dose_weights = NULL, + prior_list = NULL, + se_new_trial = NULL, + sd_posterior = NULL ) { - ess_prior <- suppressMessages(round(unlist(lapply(prior_list, RBesT::ess)))) + if (is.null(prior_list)) { # frequentist + + if (!is.null(se_new_trial)) { # re-estimate, se_new_trial + + w <- NULL + S <- diag((se_new_trial)^2) + + } else { # do not re-estimate, dose_weights + + w <- dose_weights + S <- NULL + + } + + } else { # Bayes + + if (!is.null(sd_posterior)) { # re-estimate, sd_posterior + + w <- NULL + S <- diag((sd_posterior)^2) + + } else { # do not re-estimate, dose_weights + prior_list + + w <- dose_weights + + suppressMessages(round(unlist(lapply(prior_list, RBesT::ess)))) + S <- NULL + + } + + } - contr_mat <- DoseFinding::optContr( - models = mods, - doses = dose_levels, - w = dose_weights + ess_prior) + if (is.null(w)) { + + contr <- DoseFinding::optContr( + models = mods, + doses = dose_levels, + S = S) + + } else { + + contr <- DoseFinding::optContr( + models = mods, + doses = dose_levels, + w = w) + + } - return (contr_mat) + return (contr) } @@ -204,7 +255,7 @@ addSignificance <- function ( } -#' @title BayesianMCP +#' @title performBayesianMCP #' #' @param posteriors_list tbd #' @param contr_mat tbd @@ -270,7 +321,8 @@ BayesMCPi <- function ( res <- c(sign = ifelse(max(post_probs) > crit_prob, 1, 0), p_val = max(post_probs), - post_probs = post_probs) + post_probs = post_probs, + crit_prob = crit_prob) # TODO attr crit_prob?? return (res) diff --git a/R/s3methods.R b/R/s3methods.R index 14aa663..a9bb96f 100644 --- a/R/s3methods.R +++ b/R/s3methods.R @@ -53,6 +53,12 @@ print.BayesianMCP <- function ( cat(" Estimated Success Rate: ", power, "\n") cat(" N Simulations: ", n_sim) + ## TODO if n_nim == 1 + # c(sign = ifelse(max(post_probs) > crit_prob, 1, 0), + # p_val = max(post_probs), + # post_probs = post_probs, + # crit_prob = crit_prob) + } ## ModelFits ---------------------------------------------- diff --git a/R/simulation.R b/R/simulation.R index 7c60082..2bd89b4 100644 --- a/R/simulation.R +++ b/R/simulation.R @@ -61,4 +61,4 @@ getModelData <- function ( return (model_data) -} \ No newline at end of file +} diff --git a/man/assessDesign.Rd b/man/assessDesign.Rd index 6883d23..5233e5b 100644 --- a/man/assessDesign.Rd +++ b/man/assessDesign.Rd @@ -8,6 +8,7 @@ assessDesign( n_patients, mods, prior_list, + sd = NULL, n_sim = 1000, alpha_crit_val = 0.05, simple = TRUE diff --git a/man/getContr.Rd b/man/getContr.Rd new file mode 100644 index 0000000..103d311 --- /dev/null +++ b/man/getContr.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/BMCPMod.R +\name{getContr} +\alias{getContr} +\title{getContr} +\usage{ +getContr( + mods, + dose_levels, + dose_weights = NULL, + prior_list = NULL, + se_new_trial = NULL, + sd_posterior = NULL +) +} +\arguments{ +\item{mods}{tbd} + +\item{dose_levels}{tbd} + +\item{dose_weights}{tbd} + +\item{prior_list}{tbd} + +\item{se_new_trial}{tbd} + +\item{sd_posterior}{tbd} +} +\description{ +getContr +} diff --git a/man/getContrMat.Rd b/man/getContrMat.Rd deleted file mode 100644 index d5393e3..0000000 --- a/man/getContrMat.Rd +++ /dev/null @@ -1,20 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/BMCPMod.R -\name{getContrMat} -\alias{getContrMat} -\title{getContrMat} -\usage{ -getContrMat(mods, dose_levels, dose_weights, prior_list) -} -\arguments{ -\item{mods}{tbd} - -\item{dose_levels}{tbd} - -\item{dose_weights}{tbd} - -\item{prior_list}{tbd} -} -\description{ -getContrMat -} diff --git a/man/getPosterior.Rd b/man/getPosterior.Rd index 501f5de..b404e81 100644 --- a/man/getPosterior.Rd +++ b/man/getPosterior.Rd @@ -4,16 +4,16 @@ \alias{getPosterior} \title{getPosterior} \usage{ -getPosterior(data, prior_list, mu_hat = NULL, sd_hat = NULL) +getPosterior(prior_list, data = NULL, mu_hat = NULL, se_hat = NULL) } \arguments{ -\item{data}{tbd} - \item{prior_list}{prior_list} +\item{data}{tbd} + \item{mu_hat}{tbd} -\item{sd_hat}{tbd} +\item{se_hat}{tbd} } \description{ getPosterior diff --git a/man/performBayesianMCP.Rd b/man/performBayesianMCP.Rd index e6b3543..6493c31 100644 --- a/man/performBayesianMCP.Rd +++ b/man/performBayesianMCP.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/BMCPMod.R \name{performBayesianMCP} \alias{performBayesianMCP} -\title{BayesianMCP} +\title{performBayesianMCP} \usage{ performBayesianMCP(posteriors_list, contr_mat, crit_prob) } @@ -14,5 +14,5 @@ performBayesianMCP(posteriors_list, contr_mat, crit_prob) \item{crit_prob}{tbd} } \description{ -BayesianMCP +performBayesianMCP } diff --git a/vignettes/analysis_normal.Rmd b/vignettes/analysis_normal.Rmd index 94542e7..610fdf0 100644 --- a/vignettes/analysis_normal.Rmd +++ b/vignettes/analysis_normal.Rmd @@ -123,7 +123,7 @@ crit_pval <- getCritProb( dose_weights = n_patients, alpha_crit_val = 0.1) -contr_mat_prior <- getContrMat( +contr_mat_prior <- getContr( mods = mods, dose_levels = dose_levels, dose_weights = n_patients,