Skip to content

Speed up cluster index list construction in permutation cluster tests - #14217

Merged
larsoner merged 2 commits into
mne-tools:mainfrom
Lucakaemmer:speed-up-cluster-lists
Aug 25, 2026
Merged

Speed up cluster index list construction in permutation cluster tests#14217
larsoner merged 2 commits into
mne-tools:mainfrom
Lucakaemmer:speed-up-cluster-lists

Conversation

@Lucakaemmer

Copy link
Copy Markdown
Contributor

Reference issue (if any)

Follow-up to #13731 and #14057.

What does this implement/fix?

Since #13731/#14057, _get_clusters_st and _get_components build the list of cluster index arrays with

[active[labels == id_] for id_ in np.unique(labels)]

which goes through labels once per cluster. With many clusters this is the main cost of a permutation, especially for TFCE, where it happens at every threshold. This PR replaces it with a stable argsort followed by np.split, in a small helper used by both functions. The result is the same list (same clusters, same order), just built in one pass. A small test for the helper is included.

Timings on a 12 x 143 x 143 lattice (245,388 points, 12 "subjects" of Gaussian noise, tail=1; Apple M3, numpy 2.5.2, scipy 1.18.1, numba 0.67.0):

main this PR
_find_clusters, TFCE (start=0, step=0.2), global adjacency 2.03 s 0.50 s
_find_clusters, TFCE, spatial adjacency with max_step=1 1.91 s 0.40 s
_find_clusters, threshold=0.5 (14,788 clusters) 0.28 s 0.03 s
permutation_cluster_1samp_test, TFCE, 20 permutations 57 s 12 s

Cluster indices, cluster sums, TFCE scores, T_obs, H0 and p-values are identical between main and this branch on these inputs.

Additional information

Drafted and tested the initial implementation with Claude Fable 5.

Group the active indices by component label with a single stable sort
instead of masking the labels once per cluster. Output is unchanged.

@larsoner larsoner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense that this would speed up TFCE since it has so many independent "clusters" (treating each point as one potentially). LGTM, marking for merge-when-green and I approved CIs. Thanks in advance @Lucakaemmer !

@larsoner
larsoner enabled auto-merge (squash) August 25, 2026 09:38
@larsoner
larsoner merged commit c249d79 into mne-tools:main Aug 25, 2026
31 checks passed
@welcome

welcome Bot commented Aug 25, 2026

Copy link
Copy Markdown

🎉 Congrats on merging your first pull request! 🥳 Looking forward to seeing more from you in the future! 💪

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.

2 participants