Skip to content

Use scipy for Fisher combination and contingency chi-square - #6

Merged
tprest merged 1 commit into
masterfrom
saga-scipy-swaps
Jul 9, 2026
Merged

Use scipy for Fisher combination and contingency chi-square#6
tprest merged 1 commit into
masterfrom
saga-scipy-swaps

Conversation

@tprest

@tprest tprest commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Replace hand-rolled statistics with vetted scipy equivalents (scipy is already a dependency). Part of the code-quality pass.

Changes

  • Fisher's method-2·Σln(p) + chi² tail, written out at four sites (fisher_bh_meta, fft_domain_battery, and both battery verdicts) → scipy.stats.combine_pvalues(pvals, method="fisher"). Statistic and p-value are identical; two of the sites used 1 - chi2.cdf, so they also gain tail accuracy (combine_pvalues uses chi2.sf).
  • Contingency chi²block_homogeneity's hand-rolled row/col-totals loop → scipy.stats.chi2_contingency(obs, correction=False). Empty bins/blocks are dropped first (it requires positive margins); this also fixes a latent detail — the former code counted empty bins toward the degrees of freedom, which chi2_contingency correctly does not.

Deliberately not swapped

scipy.stats.monte_carlo_test for mc_calibrate/mc_pvalue: it needs a custom rvs + non-vectorized statistic (no net code saving) and would change the seeded MC p-value stream for no correctness gain — the current (1+count)/(B+1) estimator is already correct. A lateral move, so skipped.

Verification

Suite unchanged: 134 passed, 1 skipped.

Independent of #5 (dedup); touches different regions of univariate_tests.py, so the two merge cleanly in either order.

🤖 Generated with Claude Code

Replace two hand-rolled statistics with their vetted scipy equivalents
(scipy is already a dependency):

- Fisher's method (-2*sum(ln p) + chi2 tail), written out at four sites
  (fisher_bh_meta, fft_domain_battery, and both battery verdicts) ->
  scipy.stats.combine_pvalues(pvals, method="fisher"). The statistic and
  p-value are identical; two of the sites used `1 - chi2.cdf`, so they also
  gain tail accuracy (combine_pvalues uses chi2.sf).

- block_homogeneity's hand-rolled contingency chi-square ->
  scipy.stats.chi2_contingency(obs, correction=False). Empty bins/blocks are
  dropped first (chi2_contingency requires positive margins); this also fixes
  a latent detail -- the former code counted empty bins toward the degrees of
  freedom, which chi2_contingency correctly does not.

Suite unchanged: 134 passed, 1 skipped.

Note: scipy.stats.monte_carlo_test was considered for mc_calibrate/mc_pvalue
but deliberately NOT adopted -- it needs a custom rvs + non-vectorized
statistic (no net code saving), and it would change the seeded MC p-value
stream for no correctness gain (the current (1+count)/(B+1) estimator is
already correct).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tprest
tprest merged commit 2239408 into master Jul 9, 2026
4 checks passed
@tprest
tprest deleted the saga-scipy-swaps branch July 9, 2026 20:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant