Skip to content

Probes should always have contact ids #423

@h-mayorquin

Description

@h-mayorquin

I propose that Probe should always have contact_ids. Currently, Probe.set_contacts accepts contact_ids=None. I propose that we auto-generate them as ["0", ..., f"{num_contacts - 1}"] in that case, matching the zero-indexed convention

The initial decision to allow contact_ids = None makes sense in retrospect: some probes genuinely do not have per-contact labels. The clearest case is hand-made tetrodes, where no manufacturer exists to supply labels. Some acquisition formats also do not ship per-contact identifiers (Maxwell, 3Brain), so there is a provenance-based argument against inventing them. I still think that in those cases we can just auto-generate as proposed. There is a precedent in python-neo for this pattern (e.g. AxonRawIO) and I see no downside to it.

The upside is for Probe to have a unique user-facing identifier that is slicing, aggregation and re-ordering invariant. Exposing an index as the identifier is a bad idea because it conflates an internal implementation detail (the array used to express the properties) with the object we are modelling.

The None default also creates concrete friction today. Every consumer of contact_ids has to either check for None at the application level (ProbeGroup.add_probe under PR #420 already branches on it) or assume the field is populated and absorb the failure later. Serialisation is non-uniform at the schema level: JSON encodes None as null, a different type than a string array, so round-trips through mixed-state probegroups require conditional handling rather than a single consistent format. Archival formats hit the same: BIDS already requires contact_ids, and future NWB exports will too. A guaranteed contact_id makes all of these uniform. Both probeinterface #420 and SpikeInterface #4465 currently work around the None default at the consumer side; this proposal fixes it at the source.

If preserving manufacturer labels explicitly matters, we can split the concepts as python-neo does: contact_name for the manufacturer label (optional), contact_id for the always-set unique identifier.

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