-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'release-0.1.4' into github-main
- Loading branch information
Showing
65 changed files
with
17,150 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
^renv$ | ||
^renv\.lock$ | ||
^.*\.Rproj$ | ||
^\.Rproj\.user$ | ||
^LICENSE\.md$ | ||
^\.gitlab-ci\.yml$ | ||
^cran-comments\.md$ | ||
^CRAN-SUBMISSION$ | ||
^app\.R$ | ||
^R/rsconnect$ | ||
^rsconnect$ | ||
^\.covrignore$ | ||
^public$ | ||
^_pkgdown\.yml$ | ||
^docs$ | ||
^pkgdown$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
source("renv/activate.R") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
R/runApp.R | ||
R/server.R | ||
R/ui.R |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
Version: 0.1.4 | ||
Date: 2024-03-05 15:50:18 UTC | ||
SHA: 1c522f9d25643b3a09c626ef648e0b56dc08c27a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
Package: monitOS | ||
Title: Monitoring Overall Survival in Pivotal Trials in Indolent Cancers | ||
Version: 0.1.4 | ||
Authors@R: c( | ||
person("Thomas", "Fleming", email = "[email protected]", role ="ctb"), | ||
person("Lisa", "Hampson", email = "[email protected]", role ="aut"), | ||
person("Bharani", "Bharani-Dharan", email = "[email protected]", role ="ctb"), | ||
person("Frank", "Bretz", email = "[email protected]", role = "ctb"), | ||
person("Arunava", "Chakravartty", email = "[email protected]", role = "ctb"), | ||
person("Thibaud", "Coroller", email = "[email protected]", role = c("aut", "cre")), | ||
person("Evanthia", "Koukouli", email = "[email protected]", role = "aut"), | ||
person("Janet", "Wittes", email = "[email protected]", role = "ctb"), | ||
person("Nigel", "Yateman", email = "[email protected]", role = "ctb"), | ||
person("Emmanuel", "Zuber", email = "[email protected]", role = "ctb"), | ||
person("Novartis", "Pharma AG", role = "cph") | ||
) | ||
Description: These guidelines are meant to provide a pragmatic, yet rigorous, help to drug developers and decision makers, since they are shaped by three fundamental ingredients: the clinically determined margin of detriment on OS that is unacceptably high (delta null); the benefit on OS that is plausible given the mechanism of action of the novel intervention (delta alt); and the quantity of information (i.e. survival events) it is feasible to accrue given the clinical and drug development setting. The proposed guidelines facilitate transparent discussions between stakeholders focusing on the risks of erroneous decisions and what might be an acceptable trade-off between power and the false positive error rate. | ||
License: GPL (>= 3) | ||
Maintainer: Thibaud Coroller <[email protected]> | ||
Encoding: UTF-8 | ||
Roxygen: list(markdown = TRUE) | ||
RoxygenNote: 7.2.3 | ||
Imports: | ||
stats, | ||
glue, | ||
shiny, | ||
shinydashboard, | ||
Suggests: | ||
testthat (>= 3.0.0), | ||
covr, | ||
knitr, | ||
rmarkdown, | ||
pkgdown | ||
VignetteBuilder: knitr |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Generated by roxygen2: do not edit by hand | ||
|
||
export(bounds) | ||
export(run_app) | ||
import(shiny) | ||
import(shinydashboard) | ||
importFrom(glue,glue) | ||
importFrom(stats,pnorm) | ||
importFrom(stats,qnorm) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# monitOS 0.1.4 | ||
|
||
- Added a `NEWS.md` file to track changes to the package. | ||
- Added `Shiny` section in `README.md` file. | ||
- Improved `monitOS::run_app()`: new layout, new descriptions, new use case. | ||
- Created `pkgdown` public website. | ||
|
||
# monitOS 0.1.3 | `2023-10-31` | ||
|
||
- Initial CRAN submission. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#' @title Bounds | ||
#' | ||
#' @description OS monitoring guidelines as proposed in manuscript "Monitoring Overall Survival in Pivotal Trials in Indolent Cancers". | ||
#' Calculate thresholds for positivity that can be used at an analysis to judge whether emerging | ||
#' evidence about the effect of treatment on OS is concerning or not. The threshold for positivity at any given analysis | ||
#' is the value below which the observed hazard ratio must be in order to provide sufficient reassurance that the effect | ||
#' on OS does not reach the selected unacceptable level of detriment (the margin hr_null). | ||
#' Terminology follows the manuscript "Monitoring Overall Survival in Pivotal Trials in Indolent Cancers", publication submitted | ||
#' @details Monitoring guidelines assume that the hazard ratio (HR) can adequately summarize the size of the benefits and harms of the experimental | ||
#' intervention vs control on overall survival (OS). Furthermore, guidelines assume that an OS HR < 1 is consistent with a beneficial effect of the | ||
#' intervention on OS (and smaller OS HRs <1 indicate increased efficacy). | ||
#' @param events Vector. Target number of deaths at each analysis | ||
#' @param power_int Scalar. Marginal power required at the Primary Analysis when true hazard ratio (HR) is hr_alt. | ||
#' @param falsepos Scalar. Marginal one-sided false positive error rate we are prepared to tolerate at the Final Analysis. Determines the positivity threshold at Final Analysis | ||
#' @param hr_null Scalar. The unacceptably large detrimental effect of treatment on OS we want to rule out (on HR scale) | ||
#' @param hr_alt Scalar. Plausible clinically relevant beneficial effect of treatment on OS (on HR scale) | ||
#' @param rand_ratio Integer. If patients are randomized k:1 between experimental intervention and control, rand_ratio should be inputted as k. | ||
#' Example: if patients are randomized 1:1 between experimental and control, k=1. If patients are randomized 2:1 between experimental and control, k=2. | ||
#' @param hr_marg_benefit Scalar. We may be uncertain about what a plausible beneficial effect of treatment on OS is. User can enter a second plausible OS benefit (on HR scale) | ||
#' and function will evaluate the probability we meet the positivity threshold at each analysis under this HR. This second OS benefit will usually be closer to 1 than hr_alt. | ||
#' @importFrom stats pnorm qnorm | ||
#' @return List that contains: | ||
#' * `lhr_null`: Scalar, unacceptable OS log-HR, | ||
#' * `lhr_alt`: Scalar, plausible clinically relevant log-HR, | ||
#' * `lhr_pos`: Scalar, positivity thresholds for log-HR estimates, | ||
#' * `summary`: Dataframe, which contains: | ||
#' * `OS HR threshold for positivity`, | ||
#' * `One sided false positive error rate`, | ||
#' * `Level of 2 sided CI needed to rule out hr_null`, | ||
#' * `Probability of meeting positivity threshold under hr_alt`, | ||
#' * `Positivity_Thres_Posterior`: Pr(true OS HR >= minimum unacceptable OS HR | current data), | ||
#' * `Positivity_Thres_PredProb`: Pr(OS HR estimate at Final Analysis <= Final Analysis positivity threshold | current data) | ||
#' @export | ||
#' @examples | ||
#' # Example 01: OS monitoring guideline retrospectively applied to Motivating Example 1 | ||
#' # with delta null = 1.3, delta alt = 0.80, gamma_FA = 0.025 and beta_PA = 0.10. | ||
#' bounds(events=c(60, 89, 110, 131, 178), | ||
#' power_int=0.9, # beta_PA | ||
#' falsepos=0.025, # gamma_FA | ||
#' hr_null = 1.3, # delta_null | ||
#' hr_alt = 0.8, # delta_alt | ||
#' rand_ratio = 1, # rand_ratio | ||
#' hr_marg_benefit = NULL) | ||
#' # Example 02: OS monitoring guideline applied to Motivating Example 2 | ||
#' # with delta null = 4/3, delta alt = 0.7, gamma_FA = 0.20 and beta_PA = 0.1. | ||
#' bounds(events=c(60, 89, 110, 131, 178), | ||
#' power_int=0.9, # beta_PA | ||
#' falsepos=0.025, # gamma_FA | ||
#' hr_null = 1.3, # delta_null | ||
#' hr_alt = 0.8, # delta_alt | ||
#' rand_ratio = 1, # rand_ratio | ||
#' hr_marg_benefit = 0.95) | ||
bounds <- function(events, | ||
# OS events at each analysis | ||
power_int = 0.9, | ||
# 1-Beta PA, what power do we want to not flag a safety concern at an interim analysis if the true OS HR equals our target alternative? | ||
falsepos = 0.025, | ||
# Gamme FA, What is the (one-sided) type I error rate that we will accept at the final analysis? | ||
hr_null = 1.3, | ||
# Delta null, what is the minimum unacceptable OS HR? | ||
hr_alt = 0.9, | ||
# Delta alt, what is a plausible alternative OS HR consistent with OS benefit? | ||
rand_ratio = 1, | ||
# for every patient randomized to control, rand_ratio patients are allocated to experimental intervention | ||
hr_marg_benefit = NULL | ||
# evaluate probability of meeting positivity thresholds under a second plausible beneficial effect of treatment on OS (HR = hr_marg_benefit) | ||
) { | ||
|
||
# Log scale | ||
lhr_null <- log(hr_null) | ||
lhr_alt <- log(hr_alt) | ||
|
||
# Init variables | ||
nstage <- length(events) # total number of analyses planned | ||
info <- | ||
rand_ratio*events / ((rand_ratio + 1)^2) # Fisher's information for log-HR at each analysis | ||
se <- | ||
sqrt(1 / info) # asymptotic standard error for log-HR at each analysis | ||
|
||
# Calculate the attained power when true HR = hr_alt at Final Analysis | ||
power_final <- | ||
pnorm((lhr_null - qnorm(1 - falsepos) * se[nstage] - lhr_alt) / se[nstage]) | ||
|
||
# calculate the levels of the two-sided CIs used to monitor the OS log-HR | ||
# at each interim analysis and the corresponding one-sided false positive error rate | ||
# assuming we want marginal power = power_int to 'rule out' hr_Lnull at required | ||
# evidentiary level when true OS HR = hr_alt | ||
gamma <- | ||
2 * (1 - pnorm((( | ||
lhr_null - lhr_alt | ||
) / se[1:(nstage - 1)]) - qnorm(power_int))) | ||
falsepos_all <- c(gamma / 2, falsepos) | ||
CI_level_monit_null <- 100 * (1 - 2 * falsepos_all) | ||
power_all <- | ||
c(rep(power_int, times = (nstage - 1)), power_final) | ||
|
||
lhr_pos <- lhr_null - qnorm(1 - falsepos_all) * se | ||
|
||
# Given the positivity thresholds, re-express these via Bayesian metrics | ||
post_pos <- calc_posterior(lhr_pos, lhr_null, events) | ||
pred_pos <- calc_predictive(lhr_pos, events) | ||
|
||
summary <- data.frame('Deaths' = events) | ||
|
||
# OS HR thresholds for positivity | ||
summary$'OS HR threshold for positivity' <- round(exp(lhr_pos), 3) | ||
|
||
# One sided false positive error_rate at each analysis | ||
summary$'One-sided false positive error rate' <- round(falsepos_all, 3) | ||
|
||
# Level of 2-sided CI needed to rule out δnull at given analysis (%) | ||
summary$'Level of 2-sided CI needed to rule out delta null' <- round(pmax(0, CI_level_monit_null), 0) | ||
|
||
# Probability of meeting positivity threshold under plausible OS benefit | ||
summary$'Probability of meeting positivity threshold under delta alt' <- round(power_all, 3) | ||
|
||
# Pr(true OS HR >= detrimental OS HR | current data) | ||
summary$'Posterior probability the true OS HR exceeds delta null given the data' <- round(post_pos, 3) | ||
summary$'Predictive probability the OS HR estimate at Final Analysis does not exceed the positivity threshold' <- c(round(pred_pos * 100, 3), NA) | ||
|
||
if (!is.null(hr_marg_benefit)) { | ||
# calculate the probability of meeting positivity thresholds under lhr_marg_benefit | ||
summary$'Probability of meeting positivity threshold under incremental benefit' <- | ||
round(meeting_probs( | ||
summary = summary, | ||
lhr_pos = lhr_pos, | ||
lhr_target = log(hr_marg_benefit), | ||
rand_ratio = rand_ratio | ||
), | ||
3) | ||
} | ||
|
||
return(list( | ||
lhr_null = lhr_null, | ||
lhr_alt = lhr_alt, | ||
lhr_pos = lhr_pos, | ||
summary = summary | ||
)) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#' Function which calculates for k=1, ..., K, Pr(log-HR >= lhr_null | theta.hat.k = lhr_con.k) | ||
#' i.e. the posterior probability the true OS log-hr exceeds the minimum unacceptable | ||
#' OS log-HR given the estimate of the log-hr at analysis k equals lhr_con.k (i.e. the estimate | ||
#' is equal to the stage k 'continuation threshold'). | ||
#' | ||
#' @param lhr_con vector of length K (# number of looks at OS data) containing 'continuation' thresholds on log-HR scale | ||
#' @param lhr_null scalar - minumum unacceptable OS log-HR | ||
#' @param events vector length K - number of OS events at each look at the data | ||
#' @importFrom stats pnorm | ||
#' @return vector of length K - continuation thresholds expressed on posterior probability scale | ||
calc_posterior <- function(lhr_con, lhr_null, events) { | ||
info <- | ||
events / 4 # Fisher's information for log-HR at each analysis | ||
se <- | ||
sqrt(1 / info) # asymptotic standard error for log-HR at each analysis | ||
|
||
# calculating Pr(log-hr >= lhr_null | theta.hat.k = lk) | ||
# where lk is the threshold (for the partial likelihood estimate of the OS log-HR) for 'continuation' | ||
post <- 1 - pnorm((lhr_null - lhr_con) / se) | ||
return(post) | ||
} | ||
|
||
#' Title" | ||
#' @description Calculates the posterior predictive probability of 'ruling out' lhr_null at final OS analysis | ||
#' given current estimate of OS log-HR is lhr_cont_k, for k=1, ..., K-1 | ||
#' @param lhr_con vector of length K (# number of looks at OS data) containing 'continuation' thresholds on log-HR scale | ||
#' @param events vector length K - number of OS events at each look at the data | ||
#' @return vector of length K-1: continuation thresholds at analyses k=1, ..., K-1 expressed on scale of | ||
#' posterior predictive probability of ruling out lhr_null at final OS analysis | ||
#' @importFrom stats pnorm | ||
calc_predictive <- function(lhr_con, events) { | ||
nstage <- length(events) | ||
info <- | ||
events / 4 # Fisher's information for log-HR at each analysis | ||
se <- | ||
sqrt(1 / info) # asymptotic standard error for log-HR at each analysis | ||
|
||
# calculating Pr(ZK <= lK*sqrt(info.K) | Z.k = sqrt(info.k)*lk) | ||
# where lk is the OS log-HR threshold for 'continuation' at analysis k | ||
pred_pos <- vector(mode = "numeric", length = (nstage - 1)) | ||
for (i in 1:(nstage - 1)) { | ||
pred_pos[i] <- pnorm( | ||
lhr_con[nstage] * sqrt(info[nstage]), | ||
mean = lhr_con[i] * sqrt(info[i]) * sqrt(info[nstage] / | ||
info[i]), | ||
sd = sqrt((info[nstage] - info[i]) / info[i]) | ||
) | ||
} | ||
return(pred_pos) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#' Probabilities of meeting positivity threshold under target HR | ||
#' | ||
#' @param lhr_pos List. Log HRs for positive threshold | ||
#' @param summary DataFrame. Summary dataframe from bounds.R | ||
#' @param lhr_target Scalar. Target log HR to calculate the probability of meeting positivity thresholds | ||
#' @param rand_ratio Integer. If patients are randomized k:1 between experimental intervention and control, rand_ratio should be inputted as k. | ||
#' Example: if patients are randomized 1:1 between experimental and control, k=1. If patients are randomized 2:1 between experimental and control, k=2. | ||
#' | ||
#' @return Array. Probabilities of meeting positivity threshold under target HR | ||
meeting_probs <- | ||
function(summary, | ||
lhr_pos, | ||
lhr_target = 1, | ||
rand_ratio = 1) { | ||
events <- summary$Deaths | ||
info <- | ||
rand_ratio * events / ((rand_ratio + 1) ^ 2) # Fisher's information for log-HR at each analysis | ||
se <- | ||
sqrt(1 / info) # asymptotic standard error for log-HR at each analysis | ||
prob <- list() | ||
for (i in 1:length(events)) { | ||
prob[i] <- | ||
pnorm(lhr_pos[i], | ||
mean = lhr_target, | ||
sd = se[i], | ||
lower.tail = TRUE) | ||
} | ||
return(as.numeric(prob)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
#' @title monitOS app | ||
#' | ||
#' @description Runs the shiny app to guide user choice adequate settings to calculate | ||
#' the positivity thresholds to monitor overall survival (OS) | ||
#' @import shiny | ||
#' @export | ||
#' @return No return value, runs shiny app | ||
run_app <- function() { | ||
shinyApp( | ||
ui = app_ui, | ||
server = app_server, | ||
# onStart = onStart, | ||
# options = options, | ||
# enableBookmarking = enableBookmarking, | ||
# uiPattern = uiPattern | ||
) | ||
} | ||
|
Oops, something went wrong.