From a47b0c3cd76641c2f3edc57b5441a92fd0f9ad77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 21 May 2026 00:34:45 +0000 Subject: [PATCH 1/3] Initial plan From 86fab6f5301adaa74eacde9fc702de87fc2d4c15 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 21 May 2026 00:36:16 +0000 Subject: [PATCH 2/3] Allow ve=0 in simBinomialSeasonalExact validation Agent-Logs-Url: https://github.com/keaven/gsDesign/sessions/d77f3741-a13e-4226-87bd-bd433f829e02 Co-authored-by: keaven <1045995+keaven@users.noreply.github.com> --- R/simBinomialSeasonalExact.R | 4 ++-- .../test-independent-test-simBinomialSeasonalExact.R | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/R/simBinomialSeasonalExact.R b/R/simBinomialSeasonalExact.R index 20659218..f81f1412 100644 --- a/R/simBinomialSeasonalExact.R +++ b/R/simBinomialSeasonalExact.R @@ -105,8 +105,8 @@ simBinomialSeasonalExact <- function( if (!(gsD$test.type %in% c(1, 4))) { stop("gsD$test.type must be 1 or 4", call. = FALSE) } - if (!is.numeric(ve) || length(ve) < 1 || any(!is.finite(ve)) || any(ve <= 0) || any(ve >= 1)) { - stop("ve must be a numeric vector with values strictly between 0 and 1", call. = FALSE) + if (!is.numeric(ve) || length(ve) < 1 || any(!is.finite(ve)) || any(ve < 0) || any(ve >= 1)) { + stop("ve must be a numeric vector with values in [0, 1)", call. = FALSE) } if (!is.numeric(season_length) || length(season_length) != 1 || !is.finite(season_length) || season_length <= 0) { stop("season_length must be a positive scalar", call. = FALSE) diff --git a/tests/testthat/test-independent-test-simBinomialSeasonalExact.R b/tests/testthat/test-independent-test-simBinomialSeasonalExact.R index 99d58040..5472ab88 100644 --- a/tests/testthat/test-independent-test-simBinomialSeasonalExact.R +++ b/tests/testthat/test-independent-test-simBinomialSeasonalExact.R @@ -54,7 +54,10 @@ test_that("simBinomialSeasonalExact validates core inputs", { expect_error( simBinomialSeasonalExact(gsD = design, ve = c(0.3, 1)), - "strictly between 0 and 1" + "values in \\[0, 1\\)" + ) + expect_no_error( + simBinomialSeasonalExact(gsD = design, ve = c(0, 0.3), nsim = c(1, 1)) ) expect_error( From cb3289b201831721afff42d715928dd7e817b803 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 21 May 2026 01:03:09 +0000 Subject: [PATCH 3/3] Allow ve < 0 in simBinomialSeasonalExact, add feasibility check, update docs and tests Agent-Logs-Url: https://github.com/keaven/gsDesign/sessions/0b5ded8f-ec2a-4f3c-9ccb-7ee66c119a2b Co-authored-by: keaven <1045995+keaven@users.noreply.github.com> --- DESCRIPTION | 2 +- NEWS.md | 5 +++++ R/simBinomialSeasonalExact.R | 13 ++++++++++--- ...test-independent-test-simBinomialSeasonalExact.R | 9 ++++++++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 12df7565..789c64dc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: gsDesign -Version: 3.9.0.9005 +Version: 3.9.0.9006 Title: Group Sequential Design Authors@R: c( person("Keaven", "Anderson", email = "keaven_anderson@merck.com", role = c("aut", "cre")), diff --git a/NEWS.md b/NEWS.md index 3e5ced6d..f1a13961 100644 --- a/NEWS.md +++ b/NEWS.md @@ -62,6 +62,11 @@ - `simBinomialSeasonalExact()` now supports `usTime`/`lsTime` inputs and reports futility stopping probabilities (`futility_stop_rate` with `futility_mc_se`) in scenario summaries. +- `simBinomialSeasonalExact()` now accepts `ve = 0` and `ve < 0`, allowing + null-hypothesis (`ve = 0`) and non-inferiority margin (`ve < 0`) scenarios. + Validation now requires only that `ve` values are finite and less than 1. + A feasibility check verifies that the implied experimental-arm event rates + (`control_event_rate * (1 - ve)`) remain in `[0, 1)` (#267). ## Bug fixes diff --git a/R/simBinomialSeasonalExact.R b/R/simBinomialSeasonalExact.R index f81f1412..7b826cb9 100644 --- a/R/simBinomialSeasonalExact.R +++ b/R/simBinomialSeasonalExact.R @@ -13,7 +13,10 @@ #' #' @param gsD A `gsSurv` object with `test.type` 1 or 4. #' @param ve Numeric vector of vaccine efficacy (or prevention efficacy) -#' scenarios to simulate. +#' scenarios to simulate. Each value must be finite and less than 1. +#' `ve = 0` corresponds to equal event rates (superiority null); `ve < 0` +#' corresponds to experimental-arm event rates above control (non-inferiority +#' margin or harmful scenarios). #' @param nsim Integer scalar or vector giving the number of simulations per #' element of `ve`. #' @param control_event_rate Numeric scalar or vector with control seasonal @@ -105,8 +108,8 @@ simBinomialSeasonalExact <- function( if (!(gsD$test.type %in% c(1, 4))) { stop("gsD$test.type must be 1 or 4", call. = FALSE) } - if (!is.numeric(ve) || length(ve) < 1 || any(!is.finite(ve)) || any(ve < 0) || any(ve >= 1)) { - stop("ve must be a numeric vector with values in [0, 1)", call. = FALSE) + if (!is.numeric(ve) || length(ve) < 1 || any(!is.finite(ve)) || any(ve >= 1)) { + stop("ve must be a numeric vector with finite values less than 1", call. = FALSE) } if (!is.numeric(season_length) || length(season_length) != 1 || !is.finite(season_length) || season_length <= 0) { stop("season_length must be a positive scalar", call. = FALSE) @@ -146,6 +149,10 @@ simBinomialSeasonalExact <- function( any(!is.finite(control_event_rate)) || any(control_event_rate <= 0) || any(control_event_rate >= 1)) { stop("control_event_rate must be a scalar or vector in (0, 1) with one value per ve scenario", call. = FALSE) } + experimental_event_rate <- control_event_rate * (1 - ve) + if (any(experimental_event_rate < 0) || any(experimental_event_rate >= 1)) { + stop("ve and control_event_rate imply experimental event rates outside [0, 1)", call. = FALSE) + } if (!is.logical(adaptive) || length(adaptive) < 1 || any(is.na(adaptive))) { stop("adaptive must be a logical vector with at least one value", call. = FALSE) diff --git a/tests/testthat/test-independent-test-simBinomialSeasonalExact.R b/tests/testthat/test-independent-test-simBinomialSeasonalExact.R index 5472ab88..77c04b65 100644 --- a/tests/testthat/test-independent-test-simBinomialSeasonalExact.R +++ b/tests/testthat/test-independent-test-simBinomialSeasonalExact.R @@ -54,11 +54,18 @@ test_that("simBinomialSeasonalExact validates core inputs", { expect_error( simBinomialSeasonalExact(gsD = design, ve = c(0.3, 1)), - "values in \\[0, 1\\)" + "finite values less than 1" ) expect_no_error( simBinomialSeasonalExact(gsD = design, ve = c(0, 0.3), nsim = c(1, 1)) ) + expect_no_error( + simBinomialSeasonalExact(gsD = design, ve = c(-0.1, 0, 0.3), nsim = c(1, 1, 1)) + ) + expect_error( + simBinomialSeasonalExact(gsD = design, ve = -10, control_event_rate = 0.5), + "experimental event rates outside" + ) expect_error( simBinomialSeasonalExact(gsD = design, nsim = c(10, 10, 10)),