testUpper, testLower, and
testHarm parameters to gsDesign(),
gsSurv(), and gsSurvCalendar() for selective
bound testing at interim analyses. Each accepts a logical scalar or
vector of length k specifying which analyses should include
that boundary. Inactive bounds are set to extreme values (±20 on
Z-scale) and displayed as NA in print() and
gsBoundSummary() output. This enables designs such as
futility-only at early interims, deferred efficacy testing, or selective
harm monitoring (@keaven, #141).test.type = 7 (binding futility and binding harm
bounds) and test.type = 8 (non-binding futility and
non-binding harm bounds) to gsDesign(),
gsSurv(), and gsSurvCalendar(). These
three-boundary designs support monitoring for efficacy, futility, and
potential harm simultaneously, motivated by FDA guidance on overall
survival monitoring in oncology trials (@keaven, #237).sfharm and sfharmparam parameters
control the spending function for the harm bound independently from
efficacy and futility spending (@keaven, #237).plot() types, gsBoundSummary(),
print(), summary(), and xtable()
methods support the new three-boundary designs (@keaven, #237).HarmBound vignette demonstrating harm bound
design and interpretation (@keaven, #237).nEvents(),
nSurv(), gsSurv(),
gsSurvCalendar()) now support hr > hr0 for
time-to-event designs where a larger hazard ratio is the alternative
hypothesis. This enables direct specification of designs for
time-to-response, safety endpoints, or reversed HR conventions. All
sample size methods (Lachin-Foulkes, Schoenfeld, Freedman,
Bernstein-Lagakos) and plotting functions handle both directions
symmetrically (@keaven, #251).gsSurvPower() function computes power for a group
sequential survival design with specified enrollment, dropout, treatment
effect, and analysis timing. Unlike gsSurv() and
gsSurvCalendar() which solve for sample size,
gsSurvPower() takes fixed assumptions and computes power.
Supports calendar-time and event-driven timing, stratified designs, all
test types (1–8 including harm bounds), and flexible analysis timing
criteria (targetEvents, plannedCalendarTime,
maxExtension, minTimeFromPreviousAnalysis,
minN, minFollowUp). When an existing
gsSurv design is provided via x, parameters
can be selectively overridden for “what-if” sensitivity analyses.
Changing alpha preserves original futility bounds
(following gsBoundSummary() convention) while recomputing
efficacy bounds (@keaven, #109).gsSurvPower() now supports
informationRates to cap spending at planned versus realized
information fractions and fullSpendingAtFinal to force the
final spending fraction to 1 when desired. This makes it easier to
evaluate delayed event accrual while keeping spending tied to a planned
information schedule. It also preserves the original one-sided versus
two-sided design convention when inheriting defaults from an existing
gsSurv object (#258).vignette("gsSurvPower")) with worked examples for
sensitivity analysis, alpha reallocation, biomarker subgroup to
stratified design, and event-driven timing (@keaven, #109).repeatedPValueBinomialExact() and
sequentialPValueBinomialExact() to compute repeated and
sequential exact-binomial p-values under spending function designs
derived from gsSurv() objects (#264).simBinomialSeasonalExact() to run fixed and
blinded-adaptive seasonal rare-event simulations with exact-binomial
efficacy monitoring summaries (#264).toBinomialExact() now supports explicit spending-time
overrides via usTime and lsTime (for
test.type = 4) to align with gsDesign() and
gsSurv() conventions when updating bounds with
observedEvents (#264).toBinomialExact() now accepts an alpha
override for deriving updated exact efficacy bounds (#167).simBinomialSeasonalExact() now supports
usTime/lsTime inputs and reports futility
stopping probabilities (futility_stop_rate with
futility_mc_se) in scenario summaries (#264).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).gsBoundSummary() now warns before defaulting missing
hr0 to 1 for hazard-ratio boundary summaries (#42).nSurv() and gsSurv() now validate fixed
survival timing inputs before enrollment periods are adjusted, giving a
clear error when R/gamma imply accrual beyond
T - minfup instead of failing later while assigning row
names (#274).Power.ssrCP() now uses the interim efficacy bound when
integrating the no-sample-size-re-estimation region and when falling
back to the upper conditional-power changepoint (#213).nSurv() and gsSurv() now use the requested
survival sample size method when either T or
minfup is NULL. gsSurv() also
uses the input accrual rate and duration when both T and
minfup are NULL, solving follow-up duration
against the final group-sequential event requirement. This allows
Schoenfeld survival designs to reproduce SAS PROC SEQDESIGN’s
fixed-accrual follow-up solve (#270).simBinomialSeasonalExact() now stops simulated trials
at the first efficacy or futility boundary crossing for reporting
stopping time, total events, and total enrollment, while preserving the
non-binding futility convention for efficacy crossing probability. The
simulation also updates exact-binomial bounds within each trial using
the observed total event counts and defaults fixed per-season enrollment
to the design’s planned seasonal enrollment (#264).toInteger() now preserves selective-bound flags
(testUpper, testLower, testHarm)
and harm-bound spending (sfharm, sfharmparam
for test.type 7 or 8) when recomputing the design after
integer sample size or event-count rounding. Previously the internal
gsDesign() call omitted these settings, so inactive looks
could incorrectly become active (#261).toInteger() now preserves the intended survival-design
behavior that roundUpFinal = TRUE rounds the final event
count up. If the independently rounded final sample size, using the
usual ratio + 1 allocation multiple, cannot support the
integer event target, toInteger() adjusts sample size by
allocation multiples, with a warning, until the target is achievable.
Designs where the rounded sample size already supports the integer event
target retain the previous behavior (#264).toInteger() survival integerization now keeps the
calendar design fixed while deriving interim integer events from timing
and final integer event target. Enrollment is inflated minimally by
scaling accrual rates and then rounded to allocation multiples, avoiding
unnecessary calendar-extension-driven enrollment increases for small
final-event rounding changes. A variable-duration fallback is retained
with a warning when fixed-calendar inflation is infeasible (#271).hrn2z() which used
sign(hr0 - hr1) while zn2hr() used
sign(hr1 - hr0), preventing correct round-trip conversion.
Both now use sign(hr1 - hr0) (@keaven, #251).toBinomialExact() one-sided
(test.type = 1) updating with observedEvents
so futility-adjustment code is only executed when
test.type = 4 (#264).toBinomialExact() now respects selective futility
testing (testLower) when present on a gsSurv
object by flattening lower spending at inactive looks (#264).SeqDesignSurvival vignette scope as a SAS
PROC SEQDESIGN sample size translation, with upfront guidance on
gsSurv() enrollment and follow-up workflows versus
gsSurvPower() power calculations (#271).SeqDesignSurvival vignette to use the
one-sided gsSurv() alpha convention when reproducing SAS
PROC SEQDESIGN fractional-time survival output (#264).toInteger() help and vignette guidance for
survival-design final event rounding, final sample-size feasibility
adjustment, and seasonal designs with a final zero event-rate period
(#264).test.type restriction in
toBinomialExact(): only test.type = 1 and
4 are supported; other types (including 7 and 8) produce an
error (@keaven,
#109).@param documentation using
@inheritParams so that test.type, spending
function parameters, and other shared arguments are defined once in
gsDesign() or nSurv() and inherited by
gsSurv() and gsSurvCalendar() (@keaven, #237).vignette("SelectiveBoundTesting")) with worked examples
for all supported scenarios (@keaven, #255).gsSurvPower() documentation and vignette
guidance for informationRates, calendar spending, and
fullSpendingAtFinal, including a corrected worked example
of the spending fractions used at the final analysis (#258).test.type = 2, alpha = 0.025,
method = "Schoenfeld", and T = minfup = NULL
to match SAS’s symmetric two-sided fixed-accrual design, with guidance
on fractional-time information schedules (#270).vignette("MultiSeasonRareEvents")) demonstrating
exact-binomial seasonal monitoring, analysis-time bound updates via
toBinomialExact(observedEvents = ...), and blinded
information-adaptive enrollment scenarios (#264).gsBoundSummary() output, IA1-only futility illustration, VE
and nominal one-sided p-values at exact-binomial bounds, and clearer
simulation tables including efficacy and futility stopping probabilities
with non-binding Type I interpretation notes (#264).toInteger() regression tests for selective-bound
preservation on gsDesign and gsSurv objects,
including test.type 8 with custom harm spending
(#261).gsSurvPower() regression tests for
informationRates, fullSpendingAtFinal, and
inherited sidedness behavior from existing time-to-event designs
(#258).simBinomialSeasonalExact() input
validation, reproducibility, and adaptive enrollment behavior
(#264).toBinomialExact()
one-sided (test.type = 1) updates with
observedEvents (#264).toBinomialExact()
usTime/lsTime overrides and selective-futility
behavior, plus tests for new futility stopping summary outputs from
simBinomialSeasonalExact() (#264).simBinomialSeasonalExact()
stopping summaries, design-based fixed enrollment defaults, and the
rare-event toInteger() equal-allocation path (#264).nSurv() and gsSurv() regression
tests across the supported T/minfup timing
combinations for Schoenfeld, Freedman, and Bernstein-Lagakos methods
(#270).|> is now used throughout
the code and documentation, so R >= 4.1.0 is now required (@nanxstats, #236).nSurv() and gsSurv() now incorporate
Schoenfeld and Freedman methods for sample size and power for
time-to-event studies with proportional hazards. This allows matching
versus other software (@keaven, #243).print.nSurv() and print.gsSurv() now use
refreshed output formatting (@keaven, #243).src/ is now consistently formatted with
clang-format, and C function comments now use Doxygen
blocks with clearer parameter and return documentation (@nanxstats, #238).gs_inv_sqrt_2pi constant from src/gsDesign.h,
which now also has include guards, replacing duplicated magic numbers
and repeated division (@nanxstats, #241).R/gsSurv-*.R files, improving maintainability and future
extension without changing user-facing behavior (@nanxstats, #240).gsBound() now prints the last two lower boundary values
correctly in an internal diagnostic message (atem and
atem2) when printerr is enabled (@nanxstats, #238).gsBound(),
gsBound1(), gsDensity(), and
gsProbability() to verify stable behavior after normal
density constant refactoring (@nanxstats, #241).as_gt() snapshots for gt 1.3.0 LaTeX output
changes so tests pass reliably across environments (@nanxstats, #239).gsBoundSummary() now displays calendar time for
gsNB objects from the gsDesignNB package when analysis
times are provided (@keaven, #229, #233).plotgsPower() now uses linewidth instead
of deprecated size aesthetic for geom_line()
calls, avoiding ggplot2 (>= 3.4.0) warnings (@nanxstats, #217).sfXG3() now correctly reports its name as “Xi-Gallo,
method 3” instead of “Xi-Gallo, method 1” (@DMuriuki, #223).plottype = 4) so labels passed to text()
match the plotted points. This prevents r-devel (R 4.6.0) truncation
warnings and keeps vdiffr snapshots bitwise reproducible across R
versions (@nanxstats, #231).sfXG1(),
sfXG2(), and sfXG3() (@DMuriuki, #223).toBinomialExact() and
xtable() (@DMuriuki, #224).as_gt() snapshot tests for gt 1.1.0
compatibility (@nanxstats, #221).capture.output() (@nanxstats, #217).nNormal() now links to vignette("nNormal")
in its See Also section for the full derivation and examples (@keaven, #220).workflow_dispatch trigger to
R CMD check workflow for easier testing on forks (@jdblischak, #225).hGraph() has been formally removed from gsDesign
(@nanxstats, #215).
It was soft-deprecated in gsDesign 3.4.0 and moved to gMCPLite. Use
gMCPLite::hGraph() instead.
This change also preemptively fixes an R CMD check issue
with ggplot2 (>= 4.0.0) that would otherwise require declaring MASS
as an explicit dependency (tidyverse/ggplot2#6578).
gsAdaptSim() and
gsSimulate() (@DMuriuki, #212).binomialPowerTable()
(@DMuriuki,
#214).vignette("binomialTwoSample") for
binomial two-arm trial design and analysis (@keaven, #202). Covers superiority,
non-inferiority, and super-superiority designs using risk-difference
methods. Includes sample size calculations, power analysis, and protocol
wording with both asymptotic approximations and simulation
approaches.binomialPowerTable() generates power
tables across control rates and treatment effects. Supports both
analytical calculations and fast simulation for exact results.gsBoundSummary() (as updated in gsDesign 3.6.6) did not
consider spending time for alternate alpha levels when the
alpha argument was specified. This issue has been resolved;
lsTime and usTime are now correctly used for
updated bounds with these alternate alpha levels (@keaven, #203).as_gt() (@DMuriuki, #196).DESCRIPTION (@jdblischak, #201).toInteger() (@DMuriuki, #186).gsBoundSummary() gains a new argument
alpha to assemble a summary table with multiple efficacy
boundaries (@keaven,
#183).gsSurvCalendar() (@keaven, #178).vdiffr::expect_doppelganger() (@nanxstats, #176).CODECOV_TOKEN to fix code coverage uploads (@jdblischak, #179).r for controlling
numerical integration grid points (@nanxstats, #181).toInteger() (introduced in gsDesign 3.5.0) is
updated to match broader, non-gsDesign conventions for deriving integer
sample size and event counts (@keaven, #172).
This update may result in different outputs compared to previous
versions. Users who use this function should review the updated function
documentation (?toInteger) and
vignette("toInteger") for details.
as_rtf() methods (@DMuriuki, #168).cph role to the Authors@R field
following best practices (@nanxstats, #166).We have made the spending function summary output more readable and informative.
a b = 0.5 1.5 is now
displayed as a = 0.5, b = 1.5 (@jdblischak, #162).summary() method for sfLDOF() no
longer includes the redundant none = 1 in its output (@jdblischak, #159).sfupar
in sfLDOF() to create a generalized O’Brien-Fleming
spending function (@keaven, 52cc711, 99996b).sfXG1(), sfXG2(), and sfXG3()
based on Xi and Gallo (2019). See
vignette("ConditionalErrorSpending") for details and
reproduced examples from the literature (@keaven, #147. Thanks, @xidongdxi, for comments on
vignette).eEvents() with input validation to ensure
lambda is not NULL (@keaven, 97f629d).gsSurvCalendar() (@myeongjong, #144).gsBinomialExact() (@menglu2, #143).vignette("ConditionalPowerPlot") (beb2957, 727fe20, 57394fe).gsBoundSummary() now has the as_rtf()
method implemented to generate RTF outputs for bound summary tables
(@wangben718,
#107).plotgsPower() gets new arguments offset
and titleAnalysisLegend to enable more flexible and
accurate power plots (plottype = 2) (@jdblischak, #121, #123).dplyr::reframe() to
replace dplyr::summarize() when performing grouped
cumsum() (@jdblischak, #114)..data
pronoun from rlang with ggplot2::aes(). This simplifies the
code and follows the recommended practice when using ggplot2 in packages
(@jdblischak,
#124).hGraph() now uses named guide argument in
the scale_fill_manual() call to be compatible with ggplot2
3.5.0 (@teunbrand,
#115). Note: this function has been deprecated and
moved to gMCPLite since gsDesign 3.4.0. It will be removed from gsDesign
in a future version. Please use gMCPLite::hGraph()
instead.vignettes("SurvivalOverview") is updated with more
details and minor corrections (@keaven, #126).gsSurv() and nSurv() have updated default
values for T and minfup so that function calls
with no arguments will run. Legacy code with T or
minfup not explicitly specified could break (#105).gsSurvCalendar() function added to enable group
sequential design for time-to-event outcomes using calendar timing of
interim analysis specification (#105).as_rtf() method for gsBinomialExact()
objects added, enable RTF table outputs for standard word processing
software (#102).toBinomialExact() and gsBinomialExact():
fix error checking in bound computations, improve documentation and
error messages (#105).print.gsSurv(): Improve the display of targeted events
(very minor). The boundary crossing probability computations did not
change. The need is made evident by the addition of the
toInteger() function (#105).toInteger(): Fix the documentation and execution based
on the ratio argument (#105).sfPower() now allows a wider parameter range (0,
15].toInteger() function added to convert
gsDesign or gsSurv classes to integer sample
size and event counts.toBinomialExact() function added to convert
time-to-event bounds to exact binomial for low event rate studies.as_table() and as_gt() methods for
gsBinomialExact objects added, as described in the new
“Binomial SPRT” vignette.plot.ssrCP(), the hat syntax in the
mathematical expression is revised, resolving labeling issues.ggplot2::qplot() usage replaced due to its deprecation
in ggplot2 3.4.0.gsCP() interim test statistic zi
(#63).hGraph() and suggested
using gMCPLite::hGraph() instead (#70).Depends to Imports
(#56).inherits() instead of is() to
determine if an object is an instance of a class, when appropriatehGraph() to support ggplot2 versions of
multiplicity graphssequentialPValuesequentialPValue functiongsDesign and gsSurvR CMD check
warningsnBinomial1Sample()nBinomial1Sample() to improve error handling
and claritysfLDOF() to generalize with rho parameter;
still backwards compatible for Lan-DeMets O’Brien-FleminggsDesign() function and the
change is the addition of the parameters usTime and
lsTime; default behavior is backwards compatible.gsCP()opts()importFrom statements - and DESCRIPTION - adding plyr to
imports) ensuring appropriate references.xtable.gsSurv and print.gsSurv to
work with 1-sided designsshow.legend arguments where used in
ggplot2::geom_text calls; no user impactsfLogistic help filesfTrimmed as likely preferred spending function
approach to skipping early or all interim efficacy analyses; this also
can adjust bound when final analysis is performed with less than maximum
planned information. Updated help(sfTrimmed) to demonstrate
these capabilities.sfGapped, which is primarily intended to
eliminate futility analyses later in a study; see
help(sfGapped) for an examplesummary.spendfn() to provide textual summary of
spending functions; this simplified the print function for gsDesign
objectssfStep() which can be used to set an interim
spend when the exact amount of information is unknown; an example of how
this can be misused is provided in the help filegsBoundSummary,
xtable.gsSurv and summary.gsDesign are
consistent for gsSurv objects