From 95e665e752da0116ee39f34bf2d4f25f3f21fc9c Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 14 Jul 2026 15:10:35 +0200 Subject: [PATCH 1/7] pandas>=3 and python>=3.11 --- .github/workflows/all-tests.yml | 2 +- .github/workflows/deepinterpolation.yml | 4 +-- .github/workflows/test_containers_docker.yml | 4 +-- .../workflows/test_containers_singularity.yml | 4 +-- pyproject.toml | 25 ++++++++--------- readthedocs.yml | 2 +- .../extractors/tests/test_iblextractors.py | 3 -- .../extractors/tests/test_neoextractors.py | 28 +++++++++---------- 8 files changed, 34 insertions(+), 38 deletions(-) diff --git a/.github/workflows/all-tests.yml b/.github/workflows/all-tests.yml index 62a931f7df..b8ccf8910b 100644 --- a/.github/workflows/all-tests.yml +++ b/.github/workflows/all-tests.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.13"] # Lower and higher versions we support + python-version: ["3.11", "3.13"] # Lower and higher versions we support os: [macos-latest, windows-latest, ubuntu-latest] steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/deepinterpolation.yml b/.github/workflows/deepinterpolation.yml index 037d9c566e..3cf9fa765a 100644 --- a/.github/workflows/deepinterpolation.yml +++ b/.github/workflows/deepinterpolation.yml @@ -22,10 +22,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.11' - uses: astral-sh/setup-uv@v7 with: - python-version: '3.10' + python-version: '3.11' enable-cache: false - name: Get changed files id: changed-files diff --git a/.github/workflows/test_containers_docker.yml b/.github/workflows/test_containers_docker.yml index bd459be440..7bfcae195e 100644 --- a/.github/workflows/test_containers_docker.yml +++ b/.github/workflows/test_containers_docker.yml @@ -15,10 +15,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.11' - uses: astral-sh/setup-uv@v7 with: - python-version: '3.10' + python-version: '3.11' enable-cache: true - name: Python version run: diff --git a/.github/workflows/test_containers_singularity.yml b/.github/workflows/test_containers_singularity.yml index 0c92163f46..200a7cc61a 100644 --- a/.github/workflows/test_containers_singularity.yml +++ b/.github/workflows/test_containers_singularity.yml @@ -16,10 +16,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.11' - uses: astral-sh/setup-uv@v7 with: - python-version: '3.10' + python-version: '3.11' enable-cache: true - uses: eWaterCycle/setup-singularity@v7 with: diff --git a/pyproject.toml b/pyproject.toml index 5cb1a99123..ba8edd5593 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ authors = [ ] description = "Python toolkit for analysis, visualization, and comparison of spike sorting output" readme = "README.md" -requires-python = ">=3.10" +requires-python = ">=3.11" classifiers = [ "Programming Language :: Python :: 3 :: Only", "License :: OSI Approved :: MIT License", @@ -69,16 +69,15 @@ extractors = [ "pynwb>=2.6.0", "hdmf-zarr>=0.11.0", "pyedflib>=0.1.30", - "sonpy;python_version<'3.10'", "lxml", # lxml for neuroscope "scipy", - "ibllib>=3.4.1;python_version>='3.10'", # streaming IBL + "ibllib>=3.4.1", # streaming IBL "pymatreader>=0.0.32", # For cell explorer matlab files "zugbruecke>=0.2; sys_platform!='win32'", # For plexon2 ] streaming_extractors = [ - "ibllib>=3.4.1;python_version>='3.10'", # streaming IBL + "ibllib>=3.4.1", # streaming IBL # Following dependencies are for streaming with nwb files "pynwb>=2.6.0", "fsspec", @@ -105,19 +104,19 @@ postprocessing = [ metrics = [ "scikit-learn<1.8", "scipy", - "pandas<3", + "pandas>=3", "numba>=0.59", ] comparison = [ "scipy", - "pandas<3", + "pandas>=3", "networkx", ] generation = [ "scipy", - "pandas<3", + "pandas>=3", ] sorters = [ @@ -147,7 +146,7 @@ curation = [ "spikeinterface[metrics]", "spikeinterface[postprocessing]", "spikeinterface[comparison]", - "pandas<3", + "pandas>=3", "scikit-learn<1.8", "skops", "huggingface_hub", @@ -158,7 +157,7 @@ curation = [ exporters = [ "spikeinterface[postprocessing]", "spikeinterface[widgets]", - "pandas<3", + "pandas>=3", "pynapple", ] @@ -219,7 +218,7 @@ docs = [ # for notebooks in the gallery "MEArec", # Use as an example - "pandas<3", # in the modules gallery comparison tutorial + "pandas>=3", # in the modules gallery comparison tutorial "hdbscan>=0.8.33", # For sorters spykingcircus2 + tridesclous "numba", # For many postprocessing functions "networkx", @@ -246,7 +245,7 @@ test-common = [ test-core = [ {include-group = "test-common"}, - "pandas<3", + "pandas>=3", ] test-extractors = [ @@ -268,7 +267,7 @@ test-streaming-extractors = [ test-preprocessing = [ {include-group = "test-common"}, - "ibllib>=3.4.1;python_version>='3.10'", + "ibllib>=3.4.1", "pooch", "datalad", "torch", # preprocessing tests exercise sortingcomponents.motion.dredge @@ -276,7 +275,7 @@ test-preprocessing = [ test-postprocessing = [ {include-group = "test-common"}, - "pandas<3", + "pandas>=3", ] test-metrics = [{include-group = "test-common"}] diff --git a/readthedocs.yml b/readthedocs.yml index 486ace7d53..c63f9e5053 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -4,7 +4,7 @@ version: 2 build: os: "ubuntu-24.04" tools: - python: "3.10" + python: "3.13" commands: - asdf plugin add uv - asdf install uv latest diff --git a/src/spikeinterface/extractors/tests/test_iblextractors.py b/src/spikeinterface/extractors/tests/test_iblextractors.py index fa9d59ec47..eb87b34829 100644 --- a/src/spikeinterface/extractors/tests/test_iblextractors.py +++ b/src/spikeinterface/extractors/tests/test_iblextractors.py @@ -11,9 +11,6 @@ EID = "e2b845a1-e313-4a08-bc61-a5f662ed295e" PID = "80f6ffdd-f692-450f-ab19-cd6d45bfd73e" -if sys.version_info < (3, 10): - pytest.skip("IBL support requires Python 3.10 or higher", allow_module_level=True) - @pytest.mark.streaming_extractors class TestDefaultIblRecordingExtractorApBand(TestCase): diff --git a/src/spikeinterface/extractors/tests/test_neoextractors.py b/src/spikeinterface/extractors/tests/test_neoextractors.py index 5601c08c6f..7522218d52 100644 --- a/src/spikeinterface/extractors/tests/test_neoextractors.py +++ b/src/spikeinterface/extractors/tests/test_neoextractors.py @@ -392,20 +392,20 @@ class Spike2RecordingTest(RecordingCommonTestSuite, unittest.TestCase): ] -@pytest.mark.skipif( - version.parse(platform.python_version()) >= version.parse("3.10") or platform.system() == "Darwin", - reason="Sonpy only testing with Python < 3.10 and not supported on macOS!", -) -class CedRecordingTest(RecordingCommonTestSuite, unittest.TestCase): - ExtractorClass = CedRecordingExtractor - downloads = [ - "spike2/130322-1LY.smr", - "spike2/m365_1sec.smrx", - ] - entities = [ - ("spike2/130322-1LY.smr", {"stream_id": "1"}), - "spike2/m365_1sec.smrx", - ] +# @pytest.mark.skipif( +# version.parse(platform.python_version()) >= version.parse("3.10") or platform.system() == "Darwin", +# reason="Sonpy only testing with Python < 3.10 and not supported on macOS!", +# ) +# class CedRecordingTest(RecordingCommonTestSuite, unittest.TestCase): +# ExtractorClass = CedRecordingExtractor +# downloads = [ +# "spike2/130322-1LY.smr", +# "spike2/m365_1sec.smrx", +# ] +# entities = [ +# ("spike2/130322-1LY.smr", {"stream_id": "1"}), +# "spike2/m365_1sec.smrx", +# ] @pytest.mark.skipif(platform.system() == "Darwin", reason="Maxwell plugin not supported on macOS") From 7ce56a468acf32e882f68ddc93b837aad49fa6f9 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 14 Jul 2026 15:16:50 +0200 Subject: [PATCH 2/7] update pyproject version --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ba8edd5593..9495ab2cf7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "spikeinterface" -version = "0.104.1" +version = "0.105.0" authors = [ { name="Alessio Buccino", email="alessiop.buccino@gmail.com" }, { name="Samuel Garcia", email="sam.garcia.die@gmail.com" }, @@ -220,7 +220,7 @@ docs = [ "MEArec", # Use as an example "pandas>=3", # in the modules gallery comparison tutorial "hdbscan>=0.8.33", # For sorters spykingcircus2 + tridesclous - "numba", # For many postprocessing functions + "numba>=0.59", # For many postprocessing functions "networkx", "seaborn", "skops", # For automated curation From 467ef0643894c548b4f4eb1869e01e2bd0fd0ae3 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Tue, 14 Jul 2026 15:23:19 +0200 Subject: [PATCH 3/7] fix: read-only assignment in Phy extractor --- src/spikeinterface/extractors/phykilosortextractors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spikeinterface/extractors/phykilosortextractors.py b/src/spikeinterface/extractors/phykilosortextractors.py index 9d34b57dc1..257860b921 100644 --- a/src/spikeinterface/extractors/phykilosortextractors.py +++ b/src/spikeinterface/extractors/phykilosortextractors.py @@ -165,7 +165,7 @@ def __init__( spike_times_clean = spike_times if "si_unit_id" in cluster_info.columns: - unit_ids = cluster_info["si_unit_id"].values + unit_ids = cluster_info["si_unit_id"].values.copy() if np.all(np.isnan(unit_ids)): max_si_unit_id = -1 From 7b75fd4485b423bc24604187d5e75644e7b073d8 Mon Sep 17 00:00:00 2001 From: Alessio Buccino Date: Wed, 15 Jul 2026 12:13:22 +0200 Subject: [PATCH 4/7] fix: widgets tests for pandas>=3 --- pyproject.toml | 1 + src/spikeinterface/widgets/comparison.py | 4 ++-- src/spikeinterface/widgets/metrics.py | 4 ++-- src/spikeinterface/widgets/utils_figpack.py | 10 +++++++++- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9495ab2cf7..9fae456b69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -302,6 +302,7 @@ test-widgets = [ "scikit-learn", "pyvips", "networkx", + "upsetplot-bombcell", # pandas>=3 compatible fork used by BombcellUpsetPlotWidget ] test-exporters = [{include-group = "test-common"}] diff --git a/src/spikeinterface/widgets/comparison.py b/src/spikeinterface/widgets/comparison.py index 2762c78e6b..d111124522 100644 --- a/src/spikeinterface/widgets/comparison.py +++ b/src/spikeinterface/widgets/comparison.py @@ -125,8 +125,8 @@ def plot_matplotlib(self, data_plot, **backend_kwargs): N1 = scores.shape[0] N2 = scores.shape[1] - unit_ids1 = scores.index.values - unit_ids2 = scores.columns.values + unit_ids1 = scores.index.to_numpy() + unit_ids2 = scores.columns.to_numpy() # Using matshow here just because it sets the ticks up nicely. imshow is faster. self.ax.matshow(scores.values, cmap="Greens") diff --git a/src/spikeinterface/widgets/metrics.py b/src/spikeinterface/widgets/metrics.py index 37bf138424..0631dc52c9 100644 --- a/src/spikeinterface/widgets/metrics.py +++ b/src/spikeinterface/widgets/metrics.py @@ -95,7 +95,7 @@ def plot_matplotlib(self, data_plot, **backend_kwargs): backend_kwargs["num_axes"] = num_metrics**2 backend_kwargs["ncols"] = num_metrics - all_unit_ids = metrics.index.values + all_unit_ids = metrics.index.to_numpy() self.figure, self.axes, self.ax = make_mpl_figure(**backend_kwargs) @@ -277,7 +277,7 @@ def plot_figpack(self, data_plot, **backend_kwargs): metric_names = list(metrics.columns) if dp.unit_ids is None: - unit_ids = metrics.index.values + unit_ids = metrics.index.to_numpy() else: unit_ids = dp.unit_ids unit_ids = make_serializable(unit_ids) diff --git a/src/spikeinterface/widgets/utils_figpack.py b/src/spikeinterface/widgets/utils_figpack.py index 4aa28b38f1..9d150980a5 100644 --- a/src/spikeinterface/widgets/utils_figpack.py +++ b/src/spikeinterface/widgets/utils_figpack.py @@ -36,7 +36,15 @@ def import_figpack_or_sortingview(use_sortingview: bool): def make_serializable(*args): - dict_to_serialize = {int(i): a for i, a in enumerate(args)} + def _to_native(a): + # Under pandas >= 3, string Index/columns return Arrow-backed ExtensionArrays + # (e.g. ArrowStringArray) from `.values`, which are not JSON serializable. + # Convert any pandas array/Index to a plain numpy array before serialization. + if not isinstance(a, np.ndarray) and hasattr(a, "to_numpy"): + a = a.to_numpy() + return a + + dict_to_serialize = {int(i): _to_native(a) for i, a in enumerate(args)} serializable_dict = check_json(dict_to_serialize) returns = () for i in range(len(args)): From c85d90d8a687f847d80ca41518541d3ba487ab86 Mon Sep 17 00:00:00 2001 From: chrishalcrow Date: Tue, 21 Jul 2026 09:33:57 +0100 Subject: [PATCH 5/7] Revert, allowing for any pandas version --- .github/workflows/caches_cron_job.yml | 10 ++++----- .github/workflows/core-test.yml | 10 ++++----- .../workflows/cross_version_serialization.yml | 16 +++++++------- .github/workflows/deepinterpolation.yml | 8 +++---- .github/workflows/test_containers_docker.yml | 11 ++++------ .../workflows/test_containers_singularity.yml | 13 +++++------- pyproject.toml | 21 +++++++++---------- 7 files changed, 41 insertions(+), 48 deletions(-) diff --git a/.github/workflows/caches_cron_job.yml b/.github/workflows/caches_cron_job.yml index 31d409478c..b0587186d9 100644 --- a/.github/workflows/caches_cron_job.yml +++ b/.github/workflows/caches_cron_job.yml @@ -2,11 +2,11 @@ name: Create caches for gin ecephys data and virtual env on: workflow_dispatch: - push: # When something is pushed into main this checks if caches need to be re-created + push: # When something is pushed into main this checks if caches need to be re-created branches: - main schedule: - - cron: "0 12 * * *" # Daily at noon UTC + - cron: "0 12 * * *" # Daily at noon UTC jobs: create-gin-data-cache-if-missing: @@ -19,10 +19,10 @@ jobs: steps: - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: true ignore-nothing-to-cache: true # some runs do not require building a cache (ie macOS) this says this is okay - name: Create the directory to store the data @@ -41,7 +41,7 @@ jobs: with: path: ~/spikeinterface_datasets key: ${{ runner.os }}-datasets-${{ steps.repo_hash.outputs.dataset_hash }} - lookup-only: 'true' # Avoids downloading the data, saving behavior is not affected. + lookup-only: "true" # Avoids downloading the data, saving behavior is not affected. - name: Cache found? run: echo "Cache-hit == ${{steps.cache-datasets.outputs.cache-hit == 'true'}}" shell: bash diff --git a/.github/workflows/core-test.yml b/.github/workflows/core-test.yml index 9142c11705..e64c49851e 100644 --- a/.github/workflows/core-test.yml +++ b/.github/workflows/core-test.yml @@ -6,7 +6,7 @@ on: branches: - main -concurrency: # Cancel previous workflows on the same pull request +concurrency: # Cancel previous workflows on the same pull request group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -22,10 +22,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: true - name: Install dependencies run: | @@ -35,7 +35,7 @@ jobs: - name: Test core with pytest run: | pytest -m "core" -vv -ra --durations=0 --durations-min=0.001 | tee report.txt; test $? -eq 0 || exit 1 - shell: bash # Necessary for pipeline to work on windows + shell: bash # Necessary for pipeline to work on windows - name: Build test summary run: | uv pip install --system pandas @@ -45,4 +45,4 @@ jobs: python ./.github/scripts/build_job_summary.py report.txt >> $GITHUB_STEP_SUMMARY cat $GITHUB_STEP_SUMMARY rm report.txt - shell: bash # Necessary for pipeline to work on windows + shell: bash # Necessary for pipeline to work on windows diff --git a/.github/workflows/cross_version_serialization.yml b/.github/workflows/cross_version_serialization.yml index 10e9829c65..a9d293722a 100644 --- a/.github/workflows/cross_version_serialization.yml +++ b/.github/workflows/cross_version_serialization.yml @@ -20,11 +20,11 @@ on: # watches core only; a break introduced in generation/ or preprocessing/ would not # trigger it. paths: - - 'src/spikeinterface/core/**' - - '.github/scripts/serialization/**' - - '.github/workflows/cross_version_serialization.yml' + - "src/spikeinterface/core/**" + - ".github/scripts/serialization/**" + - ".github/workflows/cross_version_serialization.yml" schedule: - - cron: '0 4 * * 0' # weekly, Sunday 04:00 UTC + - cron: "0 4 * * 0" # weekly, Sunday 04:00 UTC workflow_dispatch: concurrency: @@ -43,13 +43,13 @@ jobs: steps: - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - id: set env: GITHUB_EVENT_NAME: ${{ github.event_name }} # Support floor: oldest minor to test. Below this, installs fail on the CI # Python (numcodecs dependency rot in 0.100/0.101). Raise when 0.102 rots. - MIN_VERSION_TO_TEST: "0.102" # We will change this when making breaking changes (hopefully not too often) + MIN_VERSION_TO_TEST: "0.102" # We will change this when making breaking changes (hopefully not too often) run: | python -m pip install -q packaging available_versions=$(python -m pip index versions spikeinterface | sed -n 's/.*Available versions: //p') @@ -93,12 +93,12 @@ jobs: - name: Set up Python uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - name: Set up uv uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: false - name: Generate fixtures with spikeinterface ${{ matrix.si-version }} diff --git a/.github/workflows/deepinterpolation.yml b/.github/workflows/deepinterpolation.yml index 3cf9fa765a..913022ac6e 100644 --- a/.github/workflows/deepinterpolation.yml +++ b/.github/workflows/deepinterpolation.yml @@ -6,7 +6,7 @@ on: branches: - main -concurrency: # Cancel previous workflows on the same pull request +concurrency: # Cancel previous workflows on the same pull request group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true @@ -22,10 +22,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: false - name: Get changed files id: changed-files @@ -55,4 +55,4 @@ jobs: if: ${{ steps.modules-changed.outputs.DEEPINTERPOLATION_CHANGED == 'true' }} run: | pytest -v src/spikeinterface/preprocessing/deepinterpolation - shell: bash # Necessary for pipeline to work on windows + shell: bash # Necessary for pipeline to work on windows diff --git a/.github/workflows/test_containers_docker.yml b/.github/workflows/test_containers_docker.yml index 7bfcae195e..65bb2f90e9 100644 --- a/.github/workflows/test_containers_docker.yml +++ b/.github/workflows/test_containers_docker.yml @@ -2,7 +2,6 @@ name: Test sorter images in Docker on: workflow_dispatch - jobs: test-images: name: Test on (${{ matrix.os }}) @@ -15,17 +14,15 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: true - name: Python version - run: - python --version + run: python --version - name: Docker version - run: - docker --version + run: docker --version - name: Install dependencies run: | uv pip install --system pytest diff --git a/.github/workflows/test_containers_singularity.yml b/.github/workflows/test_containers_singularity.yml index 200a7cc61a..c39b98357b 100644 --- a/.github/workflows/test_containers_singularity.yml +++ b/.github/workflows/test_containers_singularity.yml @@ -2,7 +2,6 @@ name: Test sorter images in singularity on: workflow_dispatch - jobs: test-images: name: Test on (${{ matrix.os }}) @@ -11,25 +10,23 @@ jobs: fail-fast: false matrix: # "macos-latest", "windows-latest" - os: ["ubuntu-latest", ] + os: ["ubuntu-latest"] steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: '3.11' + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: '3.11' + python-version: "3.10" enable-cache: true - uses: eWaterCycle/setup-singularity@v7 with: singularity-version: 3.8.7 - name: Python version - run: - python --version + run: python --version - name: Singularity version - run: - singularity --version + run: singularity --version - name: Install dependencies run: | uv pip install --system pytest diff --git a/pyproject.toml b/pyproject.toml index 092ebabbfc..65e4971f36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ authors = [ ] description = "Python toolkit for analysis, visualization, and comparison of spike sorting output" readme = "README.md" -requires-python = ">=3.11" +requires-python = ">=3.10" classifiers = [ "Programming Language :: Python :: 3 :: Only", "License :: OSI Approved :: MIT License", @@ -20,8 +20,7 @@ classifiers = [ dependencies = [ - "numpy>=1.20;python_version<'3.13'", - "numpy>=2.0.0;python_version>='3.13'", + "numpy>=2.0", "threadpoolctl>=3.0.0", "tqdm", "zarr>=2.18,<3", @@ -104,19 +103,19 @@ postprocessing = [ metrics = [ "scikit-learn<1.8", "scipy", - "pandas>=3", + "pandas", "numba>=0.59", ] comparison = [ "scipy", - "pandas>=3", + "pandas", "networkx", ] generation = [ "scipy", - "pandas>=3", + "pandas", ] sorters = [ @@ -149,7 +148,7 @@ curation = [ "spikeinterface[metrics]", "spikeinterface[postprocessing]", "spikeinterface[comparison]", - "pandas>=3", + "pandas", "scikit-learn<1.8", "skops", "huggingface_hub", @@ -160,7 +159,7 @@ curation = [ exporters = [ "spikeinterface[postprocessing]", "spikeinterface[widgets]", - "pandas>=3", + "pandas", "pynapple", ] @@ -221,7 +220,7 @@ docs = [ # for notebooks in the gallery "MEArec", # Use as an example - "pandas>=3", # in the modules gallery comparison tutorial + "pandas", # in the modules gallery comparison tutorial "hdbscan>=0.8.33", # For sorters spykingcircus2 + tridesclous "numba>=0.59", # For many postprocessing functions "networkx", @@ -248,7 +247,7 @@ test-common = [ test-core = [ {include-group = "test-common"}, - "pandas>=3", + "pandas", ] test-extractors = [ @@ -278,7 +277,7 @@ test-preprocessing = [ test-postprocessing = [ {include-group = "test-common"}, - "pandas>=3", + "pandas", ] test-metrics = [{include-group = "test-common"}] From 9ad68ebe83e29ad1854d66cd047670f147da5f51 Mon Sep 17 00:00:00 2001 From: chrishalcrow Date: Tue, 21 Jul 2026 09:45:58 +0100 Subject: [PATCH 6/7] more tests back to 3.10 --- .github/workflows/all-tests.yml | 2 +- .github/workflows/cross_version_serialization.yml | 2 +- .github/workflows/test_imports.yml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/all-tests.yml b/.github/workflows/all-tests.yml index b8ccf8910b..62a931f7df 100644 --- a/.github/workflows/all-tests.yml +++ b/.github/workflows/all-tests.yml @@ -24,7 +24,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.11", "3.13"] # Lower and higher versions we support + python-version: ["3.10", "3.13"] # Lower and higher versions we support os: [macos-latest, windows-latest, ubuntu-latest] steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/cross_version_serialization.yml b/.github/workflows/cross_version_serialization.yml index a9d293722a..4712a3976d 100644 --- a/.github/workflows/cross_version_serialization.yml +++ b/.github/workflows/cross_version_serialization.yml @@ -103,7 +103,7 @@ jobs: - name: Generate fixtures with spikeinterface ${{ matrix.si-version }} run: | - uv run --isolated --no-project --python 3.11 \ + uv run --isolated --no-project --python 3.10 \ --with "spikeinterface[core]==${{ matrix.si-version }}" \ python .github/scripts/serialization/serialize_objects.py "$SI_SERIALIZATION_FIXTURES_DIR" diff --git a/.github/workflows/test_imports.yml b/.github/workflows/test_imports.yml index 6af1e1a253..d3d5b5dbb1 100644 --- a/.github/workflows/test_imports.yml +++ b/.github/workflows/test_imports.yml @@ -22,10 +22,10 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 with: - python-version: "3.11" + python-version: "3.10" - uses: astral-sh/setup-uv@v7 with: - python-version: "3.11" + python-version: "3.10" enable-cache: true - name: Install Spikeinterface with only core dependencies run: | From 8027e77bd00fc9ec6312b4d9e81eaf2d573488e1 Mon Sep 17 00:00:00 2001 From: chrishalcrow Date: Tue, 21 Jul 2026 11:08:48 +0100 Subject: [PATCH 7/7] Fix upsetplot if only one failure metric --- src/spikeinterface/widgets/bombcell_curation.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/spikeinterface/widgets/bombcell_curation.py b/src/spikeinterface/widgets/bombcell_curation.py index ee2cc92832..38b4e6c751 100644 --- a/src/spikeinterface/widgets/bombcell_curation.py +++ b/src/spikeinterface/widgets/bombcell_curation.py @@ -153,6 +153,12 @@ def plot_matplotlib(self, data_plot, **backend_kwargs): if len(upset_data) == 0: continue + if upset_data.index.nlevels == 1: + warnings.warn( + f"Skipping UpSet plot: only one metric, {memberships[0][0]}, was responsible for all failures." + ) + continue + fig = plt.figure(figsize=(12, 6)) UpSet( upset_data,