Description:
When attempting to do a round-trip conversion (NDX -> ProbeInterface -> NDX) of a probe that uses complex contact shapes (e.g., polygon contacts from the Cambridge Neurotech library), from_probeinterface raises an IndexError.
To Reproduce:
import os
import numpy as np
from probeinterface import read_probeinterface
from ndx_probeinterface import to_probeinterface, from_probeinterface
# Load a Cambridge Neurotech probe (e.g., ASSY-1-E-1)
path = "path/to/ASSY-1-E-1.json"
probe_group = read_probeinterface(path)
probeNDX_original = from_probeinterface(probe_group)[0]
# Convert to ProbeInterface
p = to_probeinterface(probeNDX_original)
# Inspect the bug in contact_shape_params
count = p.get_contact_count() # Returns 16
print(len(p.contact_shape_params)) # Returns 32 instead of 16!
# Attempt to convert back to NDX
probeNDX_converted = from_probeinterface(p)[0]
Traceback:
IndexError: index 16 is out of bounds for axis 0 with size 16
...
File "ndx_probeinterface/io.py", line 142, in _single_probe_to_nwb_device
File "probeinterface/probe.py", line 1013, in to_numpy
Root cause:
The parser concatenates the dictionaries (e.g., 16 width dicts followed by 16 height dicts) instead of merging them into a list of 16 dictionaries. When from_probeinterface pre-allocates a numpy array of size 16 and iterates over p.contact_shape_params, it crashes at index 16.
Proposed Workaround/Fix:
Merging the concatenated list back into count dictionaries before calling from_probeinterface solves the issue:
if len(p.contact_shape_params) > count:
merged_params = [{} for _ in range(count)]
for i, d in enumerate(p.contact_shape_params):
merged_params[i % count].update(d)
p._contact_shape_params = np.array(merged_params) # bypassing read-only property
Description:
When attempting to do a round-trip conversion (NDX -> ProbeInterface -> NDX) of a probe that uses complex contact shapes (e.g., polygon contacts from the Cambridge Neurotech library),
from_probeinterfaceraises an IndexError.To Reproduce:
Traceback:
Root cause:
The parser concatenates the dictionaries (e.g., 16 width dicts followed by 16 height dicts) instead of merging them into a list of 16 dictionaries. When
from_probeinterfacepre-allocates a numpy array of size 16 and iterates overp.contact_shape_params, it crashes at index 16.Proposed Workaround/Fix:
Merging the concatenated list back into count dictionaries before calling from_probeinterface solves the issue: