From 3dc57290dbde0aeaa5048f2301ee75015a93fe26 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Mon, 29 Dec 2025 15:43:44 +0100 Subject: [PATCH 1/4] Test IBL extractors tests failing for PI update --- src/spikeinterface/extractors/tests/test_iblextractors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spikeinterface/extractors/tests/test_iblextractors.py b/src/spikeinterface/extractors/tests/test_iblextractors.py index 972a8e7bb0..56d01e38cf 100644 --- a/src/spikeinterface/extractors/tests/test_iblextractors.py +++ b/src/spikeinterface/extractors/tests/test_iblextractors.py @@ -76,8 +76,8 @@ def test_offsets(self): def test_probe_representation(self): probe = self.recording.get_probe() - expected_probe_representation = "Probe - 384ch - 1shanks" - assert repr(probe) == expected_probe_representation + expected_probe_representation = "Probe - 384ch" + assert expected_probe_representation in repr(probe) def test_property_keys(self): expected_property_keys = [ From 61c317aba92608d9f096a3a374bc3d43e27faaba Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Fri, 6 Mar 2026 10:09:46 -0800 Subject: [PATCH 2/4] Fix OpenEphys tests --- .../extractors/neoextractors/openephys.py | 20 ++++++++++++------- .../extractors/tests/test_neoextractors.py | 3 +++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/spikeinterface/extractors/neoextractors/openephys.py b/src/spikeinterface/extractors/neoextractors/openephys.py index 1c39a1b97c..1d16df534b 100644 --- a/src/spikeinterface/extractors/neoextractors/openephys.py +++ b/src/spikeinterface/extractors/neoextractors/openephys.py @@ -351,13 +351,19 @@ def __init__( # Ensure device channel index corresponds to channel_ids probe_channel_names = probe.contact_annotations.get("channel_name", None) if probe_channel_names is not None and not np.array_equal(probe_channel_names, self.channel_ids): - device_channel_indices = [] - probe_channel_names = list(probe_channel_names) - device_channel_indices = np.zeros(len(self.channel_ids), dtype=int) - for i, ch in enumerate(self.channel_ids): - index_in_probe = probe_channel_names.index(ch) - device_channel_indices[index_in_probe] = i - probe.set_device_channel_indices(device_channel_indices) + if set(probe_channel_names) == set(self.channel_ids): + device_channel_indices = [] + probe_channel_names = list(probe_channel_names) + device_channel_indices = np.zeros(len(self.channel_ids), dtype=int) + for i, ch in enumerate(self.channel_ids): + index_in_probe = probe_channel_names.index(ch) + device_channel_indices[index_in_probe] = i + probe.set_device_channel_indices(device_channel_indices) + else: + warnings.warn( + "Channel names in the probe do not match the channel ids from Neo. " + "Cannot set device channel indices, but this might lead to incorrect probe geometries" + ) if probe.shank_ids is not None: self.set_probe(probe, in_place=True, group_mode="by_shank") diff --git a/src/spikeinterface/extractors/tests/test_neoextractors.py b/src/spikeinterface/extractors/tests/test_neoextractors.py index f80f62ebf0..f40b4d05ab 100644 --- a/src/spikeinterface/extractors/tests/test_neoextractors.py +++ b/src/spikeinterface/extractors/tests/test_neoextractors.py @@ -121,6 +121,9 @@ class OpenEphysBinaryRecordingTest(RecordingCommonTestSuite, unittest.TestCase): ("openephysbinary/v0.5.x_two_nodes", {"stream_id": "0"}), ("openephysbinary/v0.5.x_two_nodes", {"stream_id": "1"}), ("openephysbinary/v0.6.x_neuropixels_multiexp_multistream", {"stream_id": "0", "block_index": 0}), + # TODO: block_indices 1/2 of v0.6.x_neuropixels_multiexp_multistream have a mismatch in the channel names between + # the settings files (starting with CH0) and structure.oebin (starting at CH1). + # Currently, the extractor will skip remapping to match order in oebin and settings file, raising a warning ("openephysbinary/v0.6.x_neuropixels_multiexp_multistream", {"stream_id": "1", "block_index": 1}), ( "openephysbinary/v0.6.x_neuropixels_multiexp_multistream", From 1c29d0ee33f88ce1caf99533b3b15f620f32877c Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 27 May 2026 14:53:32 +0200 Subject: [PATCH 3/4] fix: store use_valid_periods in quality_metrics params --- src/spikeinterface/metrics/quality/quality_metrics.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spikeinterface/metrics/quality/quality_metrics.py b/src/spikeinterface/metrics/quality/quality_metrics.py index 399908ec03..edceda0869 100644 --- a/src/spikeinterface/metrics/quality/quality_metrics.py +++ b/src/spikeinterface/metrics/quality/quality_metrics.py @@ -115,8 +115,6 @@ def _set_params( metric_names = [m for m in metric_names if m not in pc_metric_names] if use_valid_periods: - if periods is not None: - raise ValueError("If use_valid_periods is True, periods should not be provided.") periods = self.sorting_analyzer.get_extension("valid_unit_periods").get_data(outputs="numpy") return super()._set_params( @@ -124,6 +122,7 @@ def _set_params( metric_params=metric_params, delete_existing_metrics=delete_existing_metrics, metrics_to_compute=metrics_to_compute, + use_valid_periods=use_valid_periods, periods=periods, peak_sign=peak_sign, seed=seed, From a321af2f535e4272419796926e128cfd7a1a52c7 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 27 May 2026 15:23:30 +0200 Subject: [PATCH 4/4] fix: check if periods and valid periods are match --- .../metrics/quality/quality_metrics.py | 8 +++++++- .../quality/tests/test_quality_metric_calculator.py | 13 ++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/spikeinterface/metrics/quality/quality_metrics.py b/src/spikeinterface/metrics/quality/quality_metrics.py index edceda0869..a72e3d3775 100644 --- a/src/spikeinterface/metrics/quality/quality_metrics.py +++ b/src/spikeinterface/metrics/quality/quality_metrics.py @@ -6,6 +6,7 @@ from spikeinterface.core.template_tools import get_template_extremum_channel from spikeinterface.core.sortinganalyzer import register_result_extension from spikeinterface.core.analyzer_extension_core import BaseMetricExtension +from spikeinterface.core.sorting_tools import cast_periods_to_unit_period_dtype from .misc_metrics import misc_metrics_list from .pca_metrics import pca_metrics_list @@ -115,7 +116,12 @@ def _set_params( metric_names = [m for m in metric_names if m not in pc_metric_names] if use_valid_periods: - periods = self.sorting_analyzer.get_extension("valid_unit_periods").get_data(outputs="numpy") + valid_periods = self.sorting_analyzer.get_extension("valid_unit_periods").get_data(outputs="numpy") + if periods is not None: + provided_periods = cast_periods_to_unit_period_dtype(np.asarray(periods)) + if not np.array_equal(valid_periods, provided_periods): + raise ValueError("Provided periods do not match valid periods from the sorting analyzer.") + periods = valid_periods return super()._set_params( metric_names=metric_names, diff --git a/src/spikeinterface/metrics/quality/tests/test_quality_metric_calculator.py b/src/spikeinterface/metrics/quality/tests/test_quality_metric_calculator.py index dfd47c4df9..8566217d0b 100644 --- a/src/spikeinterface/metrics/quality/tests/test_quality_metric_calculator.py +++ b/src/spikeinterface/metrics/quality/tests/test_quality_metric_calculator.py @@ -218,7 +218,7 @@ def test_quality_metrics_with_periods(): seed=2205, ) - # test failure when both periods and use_valid_periods are set + # test failure when periods and valid_unit_periods do not match with pytest.raises(ValueError): compute_quality_metrics( sorting_analyzer, @@ -229,6 +229,17 @@ def test_quality_metrics_with_periods(): seed=2205, ) + # should not fail if external periods are the same as valid unit periods + valid_periods = sorting_analyzer.get_extension("valid_unit_periods").get_data(outputs="numpy") + metrics_ext_periods = compute_quality_metrics( + sorting_analyzer, + metric_names=None, + skip_pc_metrics=True, + use_valid_periods=True, + periods=valid_periods, + seed=2205, + ) + # test failure if use valid_periods is True but valid_unit_periods extension is missing sorting_analyzer.delete_extension("valid_unit_periods") with pytest.raises(AssertionError):