Skip to content

read_phy / PhySortingExtractor raises "assignment destination is read-only" under pandas >= 3.0 #4687

Description

@rly

Description

BasePhyKilosortSortingExtractor.__init__ writes into a numpy array obtained from DataFrame.values. Since pandas 3.0 made Copy-on-Write permanent, .values returns a read-only array, so the in-place assignment raises ValueError: assignment destination is read-only. This makes read_phy fail on any Phy folder that spikeinterface itself exported (i.e. one containing an si_unit_id column).

This was previously noted in passing by @MarinManuel in #4231 (comment); filing it as a dedicated bug with a minimal reproduction and a proposed fix. It is downstream-visible: it breaks neuroconv's PhySortingInterface (and NWB GUIDE's tutorial, NeurodataWithoutBorders/nwb-guide#1080) whenever pandas 3.0 is installed. Note spikeinterface[full] pins pandas<3 and so is unaffected, but the base install is not.

Location

src/spikeinterface/extractors/phykilosortextractors.py in BasePhyKilosortSortingExtractor.__init__ (line numbers from current main):

168:  unit_ids = cluster_info["si_unit_id"].values   # read-only under pandas >= 3.0
...
183:  unit_ids[i] = new_si_id                         # ValueError: assignment destination is read-only

Minimal reproduction

Uses only spikeinterface + its dependencies. Verified on main and on 0.104.8.

import tempfile
from pathlib import Path

import numpy as np
import pandas as pd
import spikeinterface
from spikeinterface.extractors import read_phy

folder = Path(tempfile.mkdtemp()) / "phy"
folder.mkdir()

np.save(folder / "spike_times.npy", np.array([10, 20, 30, 40], dtype="int64"))
np.save(folder / "spike_clusters.npy", np.array([0, 1, 0, 1], dtype="int64"))
(folder / "params.py").write_text("sample_rate = 30000.\n")
# `si_unit_id` is the column spikeinterface writes when it exports a sorting to Phy.
(folder / "cluster_info.tsv").write_text("cluster_id\tsi_unit_id\n0\t0\n1\t1\n")

print("spikeinterface", spikeinterface.__version__, "| pandas", pd.__version__)
read_phy(folder_path=folder)   # ValueError: assignment destination is read-only  (pandas >= 3.0)
  • pandas 2.3.3 -> works.
  • pandas 3.0.0 -> raises.

Traceback

File ".../spikeinterface/extractors/phykilosortextractors.py", line 183, in __init__
    unit_ids[i] = new_si_id
ValueError: assignment destination is read-only

Suggested fix

Take an owned, writeable copy before mutating:

unit_ids = cluster_info["si_unit_id"].to_numpy(copy=True)

(Worth auditing the other cluster_info[...].values uses in this method for the same pattern.)

Environment

  • spikeinterface: main (also reproduced on 0.104.8); the buggy line is identical back to 0.103.0, so it is version-independent
  • pandas: 3.0.0
  • numpy: 2.x
  • Python: 3.12

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions