[Parity] Implement statistics package - #141
Conversation
|
🤖 Specification Problem: EEGPrep had no runtime equivalent for EEGLAB functions/statistics, leaving docs/parity/eeglab_core_parity_matrix.json Phase 3 rows open and forcing Phase 4/6 work to risk private statistics copies. The missing surface included FDR, surrogate p-values/CIs, statcond, cell-array t-tests/ANOVA, correlation, and concatdata. Approach: Added src/eegprep/functions/statistics/_core.py with NumPy/SciPy implementations and same-name wrapper modules for EEGLAB discoverability. Public helpers use explicit final-axis case/subject/surrogate contracts; statcond returns named fields while preserving tuple unpacking. Two-way ANOVA uses named row/column/interaction effects to avoid MATLAB output-order ambiguity. Key code: FDR and surrogate helpers live in _core.py lines 104-218; surrogdistrib and statcond live in _core.py lines 504-631. The same-name modules are thin exports so future STUDY/time-frequency code can import stable package APIs without copying formulas. Tests: tests/test_statistics_package.py covers FDR, surrogate p-values/CIs, t-tests, ANOVA, statcond dispatch, deterministic resampling, invalid inputs, and teststat. MATLAB Engine parity tests compare deterministic helpers against the vendored EEGLAB statistics folder with ANOVA tolerance rtol=1e-4/atol=1e-5 for MATLAB single-precision intermediates. |
|
Claude finished @suraj-ranganath's task in 3m 59s —— View job Code review
Reviewed the new BlockingNone. Important1. 2. Nits
Test gaps
EEGLAB parity notes
|
| if tail_name in {"left", "lower"}: | ||
| return p_left | ||
| if tail_name == "both": | ||
| return 2 * np.minimum(p_right, p_left) |
There was a problem hiding this comment.
Severity: important — the two-tailed branch can return p-values greater than 1.
When the observed value is tied with surrogate samples, p_right and p_left can both exceed 0.5, so 2 * min(p_right, p_left) exceeds 1. Example: stat_surrogate_pvals([[1,2,2,3]], [2], "both") gives p_right=0.75, p_left=0.75 → 1.5. EEGLAB clamps the two-tailed p-value to 1; a probability above 1 is also invalid on its own terms. The existing unit test (test_surrogate_pvals_and_ci_use_last_axis) only exercises inputs where the result lands exactly on 1.0, so it misses this.
| return 2 * np.minimum(p_right, p_left) | |
| if tail_name == "both": | |
| return np.minimum(2 * np.minimum(p_right, p_left), 1.0) |
Please also add a tie case to the test.
ae09f40 to
c2a758a
Compare
Add an EEGLAB-style statistics package with NumPy/SciPy helpers for statcond, t-tests, ANOVA, FDR, surrogate p-values and confidence intervals. Includes focused tests, MATLAB Engine parity coverage, API docs, implementation notes, and parity matrix updates.
Fixes #134
Part of #131