Fix enrollment pooling that dropped per-stratum periods in simulation inputs#4
Open
lhunt13 wants to merge 1 commit into
Open
Conversation
… inputs get_dist_tite and get_info_tite pooled arm-level enrollment with group_by(rate, duration), which collapses enrollment periods with identical values across DIFFERENT strata into a single row keeping only the first stratum's label. In multi-stratum designs where strata share period values — most commonly zero-rate lead-in periods for a sub-study that opens late — all but the first stratum lost those periods and were treated as enrolling from time 0. The affected strata then accrued too much follow-up by each analysis time, inflating expected events, statistical information, and the simulated z-statistic means, so simulated power (Tables 6a/6b) exceeded the full-alpha local power for time-to-event hypotheses (e.g. H8 OS in the bundled platform_study: ~142 events at its first look instead of the correct ~105). Pool per stratum and enrollment period instead, exactly mirroring the pooling already used by get_boundaries for the design computations (which were unaffected). With the corrected pooling, ahr_dd/ahr reproduce gsDesign2's reference events, information, and effect size to machine precision for every hypothesis in platform_study. Adds regression tests comparing get_info_tite and get_dist_tite output for a two-stratum delayed sub-study against gsDesign2::ahr / ahr_dd fed the explicitly correct stratified enrollment; they fail before this fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3.
Problem
get_dist_tite()andget_info_tite()pool arm-level enrollment forahr_dd()/gsDesign2::ahr()withgroup_by(rate, duration) |> slice_head(n = 1), which collapses enrollment periods that have identical values in different strata into a single row keeping only the first stratum's label. In multi-stratum designs where strata share period values — e.g. the shared zero-rate lead-in periods of a sub-study that opens late — all but the first stratum lose those periods and are treated as enrolling from time 0. Expected events, information, and the simulated z-statistic means are inflated, so simulated power (Tables 6a/6b) for TTE hypotheses can exceed the full-alpha local power (Table 5). Full analysis in #3.get_boundaries()already pools correctly, so the design boundaries and local power were unaffected.Fix
Pool per stratum and enrollment period in both functions, mirroring
get_boundaries():With this change,
ahr_dd()/ahr()reproducegs_power_ahr's reference events/information/effect size to machine precision for every TTE hypothesis in the bundledplatform_study(e.g. H8 first look: 104.77 events as designed, instead of 142.2). Re-runningplatform_study(same seed), simulated power changes only for hypotheses in late-opening sub-studies (H3–H11; H8 first-look power 0.55 → 0.43); H1, H2, and H12 are bit-for-bit unchanged. Single-stratum configs are unaffected (the pooling is a no-op there).Tests
New
tests/testthat/test-enroll-pooling.R: a two-stratum sub-study opening at month 14 with 2:1 allocation; assertsget_info_tite()matchesgsDesign2::ahr()(independent reference) andget_dist_tite()matchesahr_dd()when both are fed the explicitly correct stratified enrollment. All three assertions fail onmainand pass with this change. Full suite passes (98/98);R CMD checkclean apart from the two notes already present onmain.Note: a smaller residual difference between simulated power and Table 5 remains after this fix, traced in #3 to the information scale used for the simulated z-statistic means (
infovsinfo0) — left out of this PR pending your input on the intended convention.🤖 Generated with Claude Code