From 81f0e817b337c82c2dcaef11ad997421c5d46566 Mon Sep 17 00:00:00 2001 From: Graham Findlay Date: Sun, 31 May 2026 17:41:14 -0500 Subject: [PATCH] Add whitening_seed parameter to MountainSort5 MountainSort5 whitens the recording before sorting, and the whitening matrix is estimated from randomly-selected data chunks (spikeinterface.preprocessing.whiten -> get_random_data_chunks). Without control of the seed, sorting isn't reproducible, even on identical input. Added a `whitening_seed` parameter (default None, preserves current behavior) that is forwarded to whiten(seed=...). There is still some very small residual indeterminism (on my test recording: 100% of units match, but ~0.04% of spikes differ) between runs with identical input. Not sure where it comes from -- maybe BLAS multithreading? --- src/spikeinterface/sorters/external/mountainsort5.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spikeinterface/sorters/external/mountainsort5.py b/src/spikeinterface/sorters/external/mountainsort5.py index e76bdb2f6e..748390c9fb 100644 --- a/src/spikeinterface/sorters/external/mountainsort5.py +++ b/src/spikeinterface/sorters/external/mountainsort5.py @@ -43,6 +43,7 @@ class Mountainsort5Sorter(BaseSorter): "freq_max": 6000, "filter": True, "whiten": True, # Important to do whitening + "whitening_seed": None, # seed for whitening's random chunk selection (None = nondeterministic) "delete_temporary_recording": True, } @@ -67,6 +68,7 @@ class Mountainsort5Sorter(BaseSorter): "freq_max": "Low-pass filter cutoff frequency", "filter": "Enable or disable filter", "whiten": "Enable or disable whitening", + "whitening_seed": "Seed for the random data chunks used to estimate the whitening matrix. Set an int for reproducible (deterministic) whitening; None (default) uses fresh randomness each run.", "delete_temporary_recording": "If True, the temporary recording file is deleted after sorting (this may fail on Windows requiring the end-user to delete the file themselves later)", } @@ -142,7 +144,7 @@ def _run_from_folder(cls, sorter_output_folder, params, verbose): if p["whiten"]: if verbose: print("whitening") - recording = whiten(recording=recording, dtype="float32") + recording = whiten(recording=recording, dtype="float32", seed=p["whitening_seed"]) else: warn("Not whitening (MountainSort5 expects whitened data)")