EEGLAB drop-in output parity (#92) - #100
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #100 +/- ##
==========================================
+ Coverage 79.44% 79.75% +0.30%
==========================================
Files 14 14
Lines 1975 2010 +35
Branches 337 339 +2
==========================================
+ Hits 1569 1603 +34
Misses 301 301
- Partials 105 106 +1
🚀 New features to boost your workflow:
|
Review round 1 (Sonnet) + a MATLAB round-trip surfaced a real format bugThe Format bug (found + fixed)pyAMICA wrote the non-square mixture params ( Fixed the writer ( Verification: re-ran the live MATLAB-faithful (column-major) round-trip on a converged fit (LL -3.399): Review findings (all addressed)
Regression safetyNumPy-vs-Fortran parity suite green (the reader change affects how genuine Fortran |
Closes #92.
Summary
Makes pyAMICA a drop-in replacement for EEGLAB's AMICA: a PyTorch NG fit can now
be written as the exact
loadmodout15binary output directory, so it loads inEEGLAB with the components in the same order and orientation, with no manual
re-sorting, sign-flipping, or reformatting.
Previously only the legacy NumPy backend could write this format; the primary
PyTorch backend could only
torch.savea private dict.What changed
write_amicaout()innumpy_impl/load.py(co-located with itsloadmodoutreader counterpart): emitsgm, W, S, mean, c, alpha, mu, sbeta, rho, comp_list, LL.numpy_impl/core.py:_write_resultsnow delegates to it(byte-identical, no duplication).
AMICATorchNG.write_amica_output(outdir)and theAMICA.write_amica_outputwrapper (with the
_check_usabledegenerate-fit guard, AMICA wrapper marks is_fitted_ even on a degenerate (nan_ll/singular_ll) fit #50).variance_order()on backend + wrapper: EEGLAB back-projected-variance order(IC1 = highest), using the same
Wconvention real MATLABloadmodout15.muses.docs/guides/eeglab.md(EEGLAB interop + round-trip), wired into the nav.Validation (real data + Fortran binary, no mocks)
test_amica_ng_wrapper.py): byte-fidelity of every writtenfile,
loadmodoutreadability + shapes, variance ordering, and the requires-fitguard. Full non-slow suite green (166 passed).
loadmodout15round-trip (column-major, exactly as MATLAB reads): ona converged fit (LL -3.399),
variance_order()equals the reader'sorigord,svar is descending, and per-component mixture proportions sum to 1.0 -- i.e. the
written directory is read correctly by real EEGLAB with the components in the
right order. Matched-config IC equivalence vs Fortran stays the ~0.997 from
validate_implementations.py.mixture params were written C-order but EEGLAB/Fortran store column-major, so
MATLAB would have read scrambled mixture proportions. Fixed writer + both numpy
readers to Fortran order; single-model output is now byte-faithful to Fortran.
Notes
is self-consistent (round-trips through
loadmodout15) but not byte-identical to anative multi-model AMICA run (issue Multi-model NG partition matching vs Fortran (>0.95 cross-corr) #27 scope).
loadmodoutreads C-order where MATLAB reads column-major (apre-existing latent transpose in the reader, out of this writer's scope); recorded
in
.context/scratch_history.md. The written bytes are correct for real EEGLAB.Tested: yes (see Validation).