From 5d4b03cee3d3a426c28714f3997ac8e15a01a46b Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 14 Oct 2026 11:29:27 +0200 Subject: [PATCH 1/5] Fix: channel_slice should not check overlapping probes (#4862) --- src/spikeinterface/core/channelslice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spikeinterface/core/channelslice.py b/src/spikeinterface/core/channelslice.py index b4478360f7..4777920199 100644 --- a/src/spikeinterface/core/channelslice.py +++ b/src/spikeinterface/core/channelslice.py @@ -66,7 +66,7 @@ def __init__(self, recording, channel_ids=None, renamed_channel_ids=None): parent_probegroup = self._parent.get_probegroup() sliced_probegroup = parent_probegroup.get_slice(self._parent_channel_indices) sliced_probegroup.set_global_device_channel_indices(np.arange(len(self._channel_ids))) - self.set_probegroup(sliced_probegroup) + self.set_probegroup(sliced_probegroup, check_overlap=False) # Reset channel groups to original ones to avoid remapping self.set_channel_groups(recording.get_channel_groups()[self._parent_channel_indices]) From a0e8af85c2970cc89f327f04f37520936e409aba Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 14 Oct 2026 11:33:02 +0200 Subject: [PATCH 2/5] Fix: PCA computation in lazy mode (#4861) --- .../postprocessing/principal_component.py | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/spikeinterface/postprocessing/principal_component.py b/src/spikeinterface/postprocessing/principal_component.py index 092344a512..225b37c9f0 100644 --- a/src/spikeinterface/postprocessing/principal_component.py +++ b/src/spikeinterface/postprocessing/principal_component.py @@ -171,16 +171,24 @@ def get_pca_model(self): * if mode is "by_channel_local", "pca_model" is a list of PCA model by channel * if mode is "by_channel_global" or "concatenated", "pca_model" is a single PCA model """ - if self.sorting_analyzer._lazy: - raise RuntimeError("PCA models are not loaded in lazy mode. Reload the sorting analyzer in non-lazy mode.") mode = self.params["mode"] if mode == "by_channel_local": pca_models = [] for chan_id in self.sorting_analyzer.channel_ids: - pca_models.append(self.data[f"pca_model_{mode}_{chan_id}"]) + pca_model = self.data.get(f"pca_model_{mode}_{chan_id}") + if pca_model is None and self._sorting_analyzer._lazy: + raise RuntimeError( + "PCA models are not loaded in lazy mode. Reload the sorting analyzer in non-lazy mode." + ) + pca_models.append(pca_model) + return pca_models else: - pca_models = self.data[f"pca_model_{mode}"] - return pca_models + pca_model = self.data.get(f"pca_model_{mode}") + if pca_model is None and self._sorting_analyzer._lazy: + raise RuntimeError( + "PCA models are not loaded in lazy mode. Reload the sorting analyzer in non-lazy mode." + ) + return pca_model def get_projections_one_unit(self, unit_id, sparse=False): """ @@ -330,8 +338,6 @@ def _run(self, verbose=False, **job_kwargs): Compute the PCs on waveforms extacted within the by ComputeWaveforms. Projections are computed only on the waveforms sampled by the SortingAnalyzer. """ - if self.sorting_analyzer._lazy: - raise RuntimeError("PCA models are not loaded in lazy mode. Reload the sorting analyzer in non-lazy mode.") p = self.params mode = p["mode"] From fab56fdce11fbe64782789afba18a78954b09838 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 14 Oct 2026 11:39:27 +0200 Subject: [PATCH 3/5] wip --- doc/releases/0.105.2.rst | 24 ++++++++++++++++++++++++ doc/whatisnew.rst | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 doc/releases/0.105.2.rst diff --git a/doc/releases/0.105.2.rst b/doc/releases/0.105.2.rst new file mode 100644 index 0000000000..4c1b03d73c --- /dev/null +++ b/doc/releases/0.105.2.rst @@ -0,0 +1,24 @@ +.. _release0.105.2: + +SpikeInterface 0.105.2 release notes +------------------------------------ + +October 14th 2026 + +Minor release with bug fixes + + +core: + +* Fix: channel_slice should not check overlapping probes (#4862) +* Reintroduce ``set_times(..., with_warning)``, with deprecation (#4864) + +postprocessing: + +* Fix: grid convolution select_peaks (#4863) +* Fix: PCA computation in lazy mode (#4861) + + +Contributors: + +* @alejoe91 diff --git a/doc/whatisnew.rst b/doc/whatisnew.rst index a6524f7a43..e60b62a3bd 100644 --- a/doc/whatisnew.rst +++ b/doc/whatisnew.rst @@ -64,8 +64,8 @@ Release notes releases/0.9.1.rst -Versions 0.105.1 -================ +Versions 0.105.1/2 +================== * Minor releases with bug fixes and performance improvements From e5c403492fe989ed0da0746a9a4a3473ad46e5b9 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 14 Oct 2026 12:10:12 +0200 Subject: [PATCH 4/5] Reintroduce `set_times(..., with_warning)`, with deprecation (#4864) --- src/spikeinterface/core/time_series.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/spikeinterface/core/time_series.py b/src/spikeinterface/core/time_series.py index 1d5fd0afe1..2307647f27 100644 --- a/src/spikeinterface/core/time_series.py +++ b/src/spikeinterface/core/time_series.py @@ -222,7 +222,7 @@ def has_time_vector(self, segment_index: Optional[int] = None): segment_index = self._check_segment_index(segment_index) return self.segments[segment_index].has_time_vector() - def set_times(self, times, segment_index=None): + def set_times(self, times, segment_index=None, with_warning=None): """Set times for a recording segment. Parameters @@ -233,6 +233,14 @@ def set_times(self, times, segment_index=None): segment_index : int or None, default: None The segment index (required for multi-segment) """ + if with_warning is not None: + warnings.warn( + "The 'with_warning' parameter is deprecated and will be removed in 0.106.0. " + "Setting times in memory is now correctly propagated in preprocessing and saving operations, " + "so you can safely remove the 'with_warning' parameter.", + FutureWarning, + stacklevel=2, + ) segment_index = self._check_segment_index(segment_index) rs = self.segments[segment_index] From 860555741c35b4f7083389bfca23b255f1be3527 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 14 Oct 2026 12:19:51 +0200 Subject: [PATCH 5/5] Fix: grid convolution select_peaks (#4863) --- .../postprocessing/tests/test_spike_locations.py | 2 +- .../sortingcomponents/peak_localization/main.py | 6 ++++++ src/spikeinterface/sortingcomponents/tools.py | 9 +++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/spikeinterface/postprocessing/tests/test_spike_locations.py b/src/spikeinterface/postprocessing/tests/test_spike_locations.py index 09d2ce5a91..3810a470be 100644 --- a/src/spikeinterface/postprocessing/tests/test_spike_locations.py +++ b/src/spikeinterface/postprocessing/tests/test_spike_locations.py @@ -12,7 +12,7 @@ class TestSpikeLocationsExtension(AnalyzerExtensionCommonTestSuite): dict(method="center_of_mass", spike_retriever_kwargs=dict(channel_from_template=True)), dict(method="center_of_mass", spike_retriever_kwargs=dict(channel_from_template=False)), dict(method="monopolar_triangulation"), - dict(method="grid_convolution"), + dict(method="grid_convolution", method_kwargs=dict(n_peaks=100)), ], ) def test_extension(self, params): diff --git a/src/spikeinterface/sortingcomponents/peak_localization/main.py b/src/spikeinterface/sortingcomponents/peak_localization/main.py index ffbdb5973d..d75f4a8a55 100644 --- a/src/spikeinterface/sortingcomponents/peak_localization/main.py +++ b/src/spikeinterface/sortingcomponents/peak_localization/main.py @@ -60,6 +60,11 @@ def get_localization_pipeline_nodes( # How do you get peaks method_kwargs = method_kwargs.copy() + n_peaks = method_kwargs.pop("n_peaks", None) + if n_peaks is not None: + prototype_extra_kwargs = {"n_peaks": n_peaks} + else: + prototype_extra_kwargs = {} method_kwargs["prototype"], _, _ = get_prototype_and_waveforms_from_peaks( recording, peaks=peaks_or_spikes, @@ -68,6 +73,7 @@ def get_localization_pipeline_nodes( channel_index_array=channel_index_array, job_kwargs=job_kwargs, seed=seed, + **prototype_extra_kwargs, ) localization_nodes = method_class(recording, parents=[peak_source, extract_dense_waveforms], **method_kwargs) diff --git a/src/spikeinterface/sortingcomponents/tools.py b/src/spikeinterface/sortingcomponents/tools.py index 75161725a5..4799cd2632 100644 --- a/src/spikeinterface/sortingcomponents/tools.py +++ b/src/spikeinterface/sortingcomponents/tools.py @@ -130,15 +130,20 @@ def get_prototype_and_waveforms_from_peaks( nbefore = ms_to_samples(ms_before, recording.sampling_frequency) nafter = ms_to_samples(ms_after, recording.sampling_frequency) - few_peaks = select_peaks( + few_peaks, few_indices = select_peaks( peaks, recording=recording, method="uniform", n_peaks=n_peaks, margin=(nbefore, nafter), channel_index_array=channel_index_array, + return_indices=True, seed=seed, ) + if channel_index_array is not None: + few_channel_index_array = channel_index_array[few_indices] + else: + few_channel_index_array = None waveforms = extract_waveform_at_max_channel( recording, few_peaks, @@ -146,7 +151,7 @@ def get_prototype_and_waveforms_from_peaks( ms_after=ms_after, job_kwargs=job_kwargs, job_name="waveform prototype", - channel_index_array=channel_index_array, + channel_index_array=few_channel_index_array, ) with np.errstate(divide="ignore", invalid="ignore"):