ENH: compute CSD directly for upper-triangle channel pairs in Fourier/multitaper#13719
ENH: compute CSD directly for upper-triangle channel pairs in Fourier/multitaper#13719PragnyaKhandelwal wants to merge 12 commits intomne-tools:mainfrom
Conversation
|
I looked into the failed Azure job. |
|
Changelog failure is legitimate, you should add a |
|
I am not super familiar with csd but assuming that all the unique information in the matrix can be extracted from the upper triangle, then it makes sense to me to do the computation on the upper triangle directly. And the aforementioned Tests are passing and a local micro-benchmark suggests we do get a speedup: codefrom functools import partial
from timeit import repeat
import numpy as np
import mne
from mne.time_frequency import csd_array_fourier, csd_array_multitaper
from mne.time_frequency.tests.test_csd import test_csd_fourier, test_csd_multitaper
mne.set_log_level("WARNING")
rng = np.random.default_rng(0)
n_epochs = 10
n_times = 1000
n_channels = 64
X = rng.standard_normal((n_epochs, n_channels, n_times))
kwargs = dict(sfreq=100, fmin=8, fmax=30, n_jobs=1)
def benchmark(func, n=100, n_repeats=5):
return repeat(partial(func, X, **kwargs), number=n, repeat=n_repeats)
n = 5
repeats = 3
funcs = {
"fourier": csd_array_fourier,
"multitaper": csd_array_multitaper,
}
for name, func in funcs.items():
times = benchmark(func, n=n, n_repeats=repeats)
best = min(times)
per_loop = best / n
print(f"{name.upper()}: {n} loops per run, best of {repeats} runs: {per_loop:.3f} s per loop")
@wmvanvliet GitLens seems to suggest that you last refactored this code (albeit a long time ago!). Do you have the time to take a quick pass at the diff? |
|
Done @larsoner! I have added the changelog entry at doc/changes/devel/13719.newfeature.rst using the :newcontrib: role as requested. I’ve also added my name to doc/changes/names.inc. All checks are now passing, including the Towncrier verification. This PR is ready for a final look and merge! |
…om/PragnyaKhandelwal/mne-python into fix-csd-upper-triangle-computation
|
Hi @tsbinns , just a quick heads-up that I’ve updated the towncrier entry to include the requested files. All CI checks are green now—ready for a final look and merge whenever you have a moment! Thanks! |
Reference issue
Fixes #13717
What does this implement/fix?
This PR addresses the
FIXMEinmne/time_frequency/csd.pyby avoiding full channel × channel CSD matrix construction in:_csd_fourier_csd_multitaperInstead, it computes CSD directly for upper-triangle channel pairs (
np.triu_indices), which matches the internal vectorized storage format and avoids unnecessary intermediate allocations.Additional information
_sym_mat_to_vectorconversion.mainvs this branch with a self-contained MWE:128and192pytest mne/time_frequency/tests/test_csd.py -k "csd_fourier or csd_multitaper" -qpre-commit run --files mne/time_frequency/csd.py