Changelog
manytestsr 0.0.4.1014
New functions
-
pStephensonQuad()andstephenson_scores(): the combined Stephenson rank test of the sharp null that the block_test_power paper runs. One linear rank statistic per tuning parameter zeta, each with the score choose(r - 1, zeta - 1) on within-block ranks, combined by the quadratic form incoin::independence_test()and referred to a chi-square with one degree of freedom per zeta. Until now that test lived only in the paper’s replication archive, while the package’spCombStephenson()wrapped the CMRSS quantile procedure under a similar name. The two are different tests; the documentation of each now says so. Tests intests/testthat/test_stephenson_quad.Rpin the score definition, tie the p-value to a computation done directly with coin, and check that the test depends on the outcome only through ranks and that its signed scores cancel across blocks whose effects reverse sign.
manytestsr 0.0.4.1013
Changes
-
pCombCauchyDist()now includes the maximum distance, so it combines seven p-values: six single-score tests and the six-score quadratic test thatpIndepDist()runs. The function had used a five-score set with no recorded reason since the June 2025 refactoring that introduced it. A check on the block_test_power paper’s simulations (Analysis/cauchy_maxdist_check.Rthere) found that under effects that cancel across blocks the maximum distance is the score that carries the signal: the five-score quadratic form rejected in 13.5 and 5.5 percent of replications in the two canceling scenarios, the six-score form in 44.5 and 49 percent, and the Cauchy combination rose from 7.5 and 2 percent to 30.5 and 34 percent once its quadratic term was the six-score form. The other six scenarios moved by two points or less. The tests intests/testthat/test_combcauchy_components.Rnow pin seven components, check that the quadratic term’s p-value equalspIndepDist()’s, and rule out both earlier compositions.
manytestsr 0.0.4.1012
Bug fixes
-
pCombCauchyDist()now combines the six components its documentation lists. The function builds one test formula per score and then adds a quadratic test of all the scores together. The line that added the quadratic formula overwrote the last single-score formula instead of appending, so the tanh score was tested only inside the quadratic and the Cauchy sum held five terms rather than six. It now appends. On the block_test_power paper’s simulations the change moves rejection rates by less than Monte Carlo error except in the sparse-effects scenario, where the rate rises from 0.513 to 0.530. Tests intests/testthat/test_combcauchy_components.Rcompute the six components withcoindirectly and check that the function returns their combination, with and without a block term.
manytestsr 0.0.4.1011
Bug fixes
-
pCombCauchyDist()implements the Cauchy combination rule of Liu and Xie (2020). The previous rule halved each p-value before the tangent transform, which put every angle in (0, pi/2), made every tangent positive, and made the two-sided correction select the same branch every time; fed five uniform independent p-values, its output fell below 0.5 about 80 percent of the time. The newacat_combine()inR/pval_combine.Rtakes each component on the log scale in both tails, so neither an underflow to 0 nor a saturation at 1 decides the combination, andcoin_component_logp()refits a component whose statistic sits exactly on its null expectation against the permutation distribution and uses its mid-p value. SeePLAN_ACAT_BOUNDARY.md.
manytestsr 0.0.4.1010
Bug fixes
-
Monte Carlo p-values can no longer be zero. Below
simthreshthe p-value functions draw their reference distribution withcoin::approximate(nresample = sims), andcoinreportscount/sims, which is exactly zero when no resample beats the observed statistic. Verified directly: with perfect separationcoinreturnsp = 0atsims = 9andsims = 49. A zero p-value sits at or below every threshold, so such a node always rejects. Under the null the observed statistic is the most extreme of thesims + 1exchangeable values with probability about1/(sims + 1), so any critical value below that had realized size about1/(sims + 1)rather than its nominal value.The functions now report
(count + 1)/(sims + 1), the standard convention (Davison and Hinkley 1997; Phipson and Smyth 2010, “Permutation P-values should never be zero”). The observed assignment is itself a draw from the null and belongs in both numerator and denominator. The correction is applied inpOneway(),pWilcox(),pIndepDist(),pTestTwice(),pPolyRank(), and to each component ofpCombCauchyDist()before the Cauchy combination. The asymptotic branch is untouched.This matters most for the smallest thresholds, which is to say for
alpha/m-style corrections, so the old behavior favoured procedures testing near nominal alpha – this package’s own top-down procedure included – over bottom-up competitors. It had to be fixed before any head-to-head benchmark. New tests intests/testthat/test_mc_pvalue_floor.R(59 assertions), verified failing before the fix.
manytestsr 0.0.4.1009
Documentation
- The vignettes now follow the 0.0.4.1008 corrections. The detection sections of
getting-startedandhierarchical-testing-workflowshow and explainhit_typeandgroup_p, and both vignettes stop recommending the stream-based sequential alpha procedures (alpha_investing,alpha_saffron,alpha_addis). Those procedures are now labeled experimental in the tree setting – their guarantees are proven for flat streams of p-values, not for gated tree-structured testing – and remain slated for deprecation, matching the README. - The
advanced-methodologiesvignette is archived toarchive/and is no longer built into the package or the pkgdown site. It presented experimental features (use_closed_testing,use_meinshausen,use_evalues) with stronger claims than the package can support, and referenced helper functions that do not exist.
manytestsr 0.0.4.1008
Corrections responding to an anonymous AOAS referee who worked through this package alongside the manuscript and identified genuine errors (2026-08; see FIX_PLAN.md for the mapping). The pre-correction state is tagged pre-referee-fixes so previously published numbers remain reproducible.
Breaking changes
-
compute_error_load()and the adaptive-alpha schedule builders now implement the paper’s Definition 2: per-depth loads sum path power (product of PROPER-ancestor rejection probabilities) over the nodes at each depth, from depth 2. The previous formula multiplied each node’s own theta back in and included a depth-1 term, understating the load and returningneeds_adjustment = FALSEin designs that require adjustment. Theneeds_adjustmentgate and the alpha-schedule denominators now use the same quantity. - Power calculations behind the error load are now two-tailed:
theta = pnorm(delta*sqrt(n) - z) + pnorm(-delta*sqrt(n) - z), so theta atdelta = 0equals the size alpha rather than alpha/2. - The error-load/power path refuses
nodesizevalues below 1 with an error.find_blocks()’s defaultblocksize = "hwt"stores harmonic weights whose node sums lie on the unit interval; feeding them to a power formula produced meaningless near-floor thetas. Pass a headcount column (e.g.blocksize = "nb") for any error-load or adaptive-alpha use;hwtremains valid for splitting and weighting. -
alpha_adaptive_tree_pruned()now warns at creation that the strong-FWER guarantee for the pruned-load schedule and its switching rule DOES NOT HOLD: the underlying theorem was falsified by exact counterexample (FWER 0.063 at alpha 0.05 with all hypotheses satisfied). Levels are computed as before for reproducibility; for a schedule with a proof usealpha_adaptive_tree()with static budget weights.
Bug fixes
-
report_detections()computed each block’s parent p-value at the GLOBAL maximum depth, so branches whose testing stopped earlier got the wrong parent or NA (surfacing ashit = NA, silently dropped bysum(hit, na.rm = TRUE)callers), and group coverage was missed on any branch shorter than the deepest one. All quantities now use each block’s own final tested depth, andhitis never NA. -
report_detections()gainshit_type(“single” = the block’s own test rejected; “group” = family parent rejected with no child rejected; “none” otherwise – a sibling’s individual rejection explains the parent, so coverage does not spread to failed siblings) andgroup_p(the rejecting parent’s p-value for covered blocks).pfinalbis now the running maximum of p-values along the block’s tested path rather than the deepest p reached. - Removed a stray positional argument in five
coin::approximate()calls that bound to coin’sclformal; harmless underparallel = "no"but broken underparallel = "snow".
manytestsr 0.0.4.1007
Bug fixes
-
make_results_tree()now propagates block-level truth (nonnull) up the tree instead of labeling leaf nodes only. An internal node is non-null iff a descendant leaf is non-null, and a known null iff all of its descendant leaves are known nulls. Without this, a false rejection of a true internal null hypothesis (rejecting a whole null group/college/region) was dropped from the node-level FWER tally (node_any_false_rejection,node_false_rejection_prop,node_num_false_rejections,node_false_discovery_prop), and correct rejections of non-null ancestors were missing fromnode_true_discoveriesandnode_power. The procedure’s rejection decisions are unchanged; only the truth labeling used to score node-level metrics is corrected. New tests intests/testthat/test_node_truth_propagation.R.
manytestsr 0.0.4.1005
Bug fixes
pCombStephenson()is now compatible withCMRSS0.2.6+, which constrains its internalkargument to1..m(wherem = sum(Z)is the number of treated units) rather than1..n. The wrapper’s user-facingkargument remains paper-notation in1..n(the rank index of tau among all units), and the wrapper now translates internally ascmrss_k = k - (n - m)before callingCMRSS::pval_comb_block(). The defaultk = nstill tests Fisher’s sharp null. The degenerate path (k <= n - m) now warns and returnsp = 1without calling CMRSS, avoiding the LP solver on a branch whose test statistic is constant across permutations anyway.pCombStephenson()now validatesk <= nand stops with a clear error ifkexceeds the total number of units.
manytestsr 0.0.4.1003
New features
New exported function
pPolyRank()tests Fisher’s sharp null of no effects using multiple polynomial rank score functions simultaneously viacoin::independence_test(). Computes within-block polynomial scores at multiple r values (default r = 2, 6, 10) and passes them as a multivariate response, providing adaptive sensitivity to treatment effects without pre-committing to a single rank scoring.New exported function
pCombStephenson()provides a formula-based wrapper aroundCMRSS::pval_comb_block(), the combined Stephenson rank test of Kim, Li, and Bowers. Tests quantile-of-effects hypotheses (whether the k-th largest individual effect exceeds a threshold); defaults to k = n, c = 0 for the sharp null. CMRSS is a Suggests dependency installed from GitHub (bowers-illinois-edu/CMRSS).
Dependency changes
Moved 8 packages from Imports to Suggests:
stringi,tidygraph,ggraph,digest,ggplot2,Ckmeans.1d.dp,onlineFDR,hommel. Core test statistic functions (pIndepDist,pTestTwice,pCombCauchyDist,pOneway,pWilcox) now install without pulling in heavy tree-testing and visualization libraries. Functions that need the moved packages check withrequireNamespace()and give a clear error message if the package is missing.Removed
ClusterRfrom Imports (unused; the code that called it was already commented out).Replaced
dataPreparationdependency with an internalwhich_are_constant()helper (a one-liner that checks for columns with fewer than 2 unique values).dataPreparationremains in Suggests for cross-validation testing only.Added
CMRSSto Suggests (GitHub-only:bowers-illinois-edu/CMRSS).
manytestsr 0.0.4.1002
New features
New exported factory function
alpha_adaptive_tree_pruned()creates a branch-pruning adaptive alpha system for use withfind_blocks(). Unlikealpha_adaptive_tree(), which pre-computes a fixed schedule, this version can recompute the schedule on the surviving subtree after each depth — giving more alpha to surviving branches when dead branches are removed. Returns a list with three components:$alphafn(standard closure),$update(recompute on pruned tree), and$reset(restore full tree).find_blocks()now supports list-valuedalphafnparameters. Whenalphafnis a list (as returned byalpha_adaptive_tree_pruned()),find_blocksextracts the$alphafn,$update, and$resetcomponents, callsresetat the start of each run, and callsupdateafter each depth’s testable decisions. Plain functionalphafnvalues continue to work unchanged.New internal helper
.get_all_descendants()performs BFS traversal on tree-structurednode_datto find all descendants of given nodes.
manytestsr 0.0.4.1001
New features
New exported function
compute_adaptive_alphas_tree()computes per-depth adjusted significance levels from an actual (possibly irregular) tree structure. Takesnode_datwith per-node sample sizes (as returned byfind_blocks()) instead of assuming a regular k-ary tree. The algorithm divides alpha at each depth by the sum of path powers — the expected number of tests conducted at that depth. For regular k-ary trees, this produces identical results to the parametriccompute_adaptive_alphas().New exported factory function
alpha_adaptive_tree()creates a closure for use withfind_blocks(alphafn = ...), using the tree-based alpha schedule fromcompute_adaptive_alphas_tree(). Drop-in replacement foralpha_adaptive()when the tree has irregular branching or unequal sample sizes across nodes.
manytestsr 0.0.4.1000
New features
- New exported function
compute_error_load()computes the error load at each tree level — the expected number of all-null sibling groups that the procedure tests. When the total error load is at most 1, the unadjusted procedure controls FWER via natural gating; when it exceeds 1, adaptive alpha adjustment is required. Supports both a parametric interface (regular k-ary trees with equal splits) and a tree interface (irregular trees with per-node sample sizes fromfind_blocks()).
Changes
compute_adaptive_alphas()now checks the error load before computing adjusted alphas. When the total error load is at most 1 (natural gating suffices), nominal alpha is returned at every level without adjustment. Thetauparameter has been removed; the error load check replaces it.compute_adaptive_alphas()gains an"error_load"attribute on its return value, so callers can inspect the error load diagnostics without a separate call tocompute_error_load().
manytestsr 0.0.4.0000
New features
- Added adaptive alpha adjustment for tree-structured hypothesis testing (
compute_adaptive_alphas()andalpha_adaptive()). This implements Algorithm 1 from the paper’s Appendix D, which adjusts significance levels at each tree depth based on estimated power decay. When cumulative power is high, alpha is tightened to account for the multiplicity of tests that power enables. When cumulative power drops below a threshold, natural gating suffices and nominal alpha is used. The procedure supports both constant and variable branching factors.
Interface changes
The
alphafninterface used byfind_blocks()now passes adepthparameter (integer vector of tree depths, 1 = root) to alpha adjustment functions. This enables alpha strategies that depend on tree structure rather than treating p-values as a flat stream.alpha_investing(),alpha_saffron(), andalpha_addis()now accept adepthargument for interface compatibility. They do not use it; their behavior is unchanged.
manytestsr 0.0.3.0000
- Initial tracked version with
find_blocks(), splitting functions (splitCluster,splitEqualApprox,splitLOO,splitSpecifiedFactor,splitSpecifiedFactorMulti), p-value functions (pOneway,pWilcox,pIndepDist,pCombCauchyDist,pTestTwice), online FDR alpha adjustment (alpha_investing,alpha_saffron,alpha_addis), local p-value adjustment (local_hommel_all_ps,local_simes,local_bh_all_ps), and reporting/visualization functions.