Skip to content

Crash when get_traces()ing an Intan digital input #1853

@cwindolf

Description

@cwindolf

Describe the bug
IntanRawIO finds wrong sample count when reading a digital input channel and crashes in get_traces()

To Reproduce
I can't share this data publicly, but maybe the below will be enough information to help?

First, reading the recording itself is fine with:

si.read_intan(
    ld / 'info.rhd',
    stream_name='RHD2000 amplifier channel',
    all_annotations=True,
    use_names_as_ids=True,
)

This finds an int16 recording with 82198272 samples. This is correct, the recording is great.

Next, I read

aux = si.read_intan(
    ld / 'info.rhd',
    stream_name='USB board digital input channel',
    all_annotations=True,
    use_names_as_ids=True,
)

This correctly finds 2 channels, but it reads 41099136 samples -- exactly half of the recording's length. It finds uint16 dtype. I'm not sure if that's right or wrong for "DIGITAL-IN" channels.

Next, when I aux.get_traces(), the traceback is:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[66], line 1
----> 1 aux.get_traces()

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/spikeinterface/core/baserecording.py:350, in BaseRecording.get_traces(self, segment_index, start_frame, end_frame, channel_ids, order, return_scaled, return_in_uV)
    348 num_samples = rs.get_num_samples()
    349 end_frame = int(min(end_frame, num_samples)) if end_frame is not None else num_samples
--> 350 traces = rs.get_traces(start_frame=start_frame, end_frame=end_frame, channel_indices=channel_indices)
    351 if order is not None:
    352     assert order in ["C", "F"]

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/spikeinterface/extractors/neoextractors/neobaseextractor.py:365, in NeoRecordingSegment.get_traces(self, start_frame, end_frame, channel_indices)
    359 def get_traces(
    360     self,
    361     start_frame: int | None = None,
    362     end_frame: int | None = None,
    363     channel_indices: list | None = None,
    364 ) -> np.ndarray:
--> 365     raw_traces = self.neo_reader.get_analogsignal_chunk(
    366         block_index=self.block_index,
    367         seg_index=self.segment_index,
    368         i_start=start_frame,
    369         i_stop=end_frame,
    370         stream_index=self.stream_index,
    371         channel_indexes=channel_indices,
    372     )
    373     if self.inverted_gain:
    374         raw_traces = -raw_traces

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/neo/rawio/baserawio.py:1003, in BaseRawIO.get_analogsignal_chunk(self, block_index, seg_index, i_start, i_stop, stream_index, channel_indexes, channel_names, channel_ids, prefer_slice)
   1000     if np.all(np.diff(channel_indexes) == 1):
   1001         channel_indexes = slice(channel_indexes[0], channel_indexes[-1] + 1)
-> 1003 raw_chunk = self._get_analogsignal_chunk(block_index, seg_index, i_start, i_stop, stream_index, channel_indexes)
   1005 return raw_chunk

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/neo/rawio/intanrawio.py:420, in IntanRawIO._get_analogsignal_chunk(self, block_index, seg_index, i_start, i_stop, stream_index, channel_indexes)
    413     sigs_chunk = self._get_analogsignal_chunk_header_attached(
    414         i_start,
    415         i_stop,
    416         stream_index,
    417         channel_indexes,
    418     )
    419 elif self.file_format == "one-file-per-signal":
--> 420     sigs_chunk = self._get_analogsignal_chunk_one_file_per_signal(
    421         i_start,
    422         i_stop,
    423         stream_index,
    424         channel_indexes,
    425     )
    426 else:
    427     sigs_chunk = self._get_analogsignal_chunk_one_file_per_channel(
    428         i_start,
    429         i_stop,
    430         stream_index,
    431         channel_indexes,
    432     )

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/neo/rawio/intanrawio.py:527, in IntanRawIO._get_analogsignal_chunk_one_file_per_signal(self, i_start, i_stop, stream_index, channel_indexes)
    524     signal_channels = self.header["signal_channels"][mask]
    525     channel_ids = signal_channels["id"][channel_indexes]
--> 527     output = self._demultiplex_digital_data(raw_data, channel_ids, i_start, i_stop)
    528 elif stream_is_stim:
    529     output = self._decode_current_from_stim_data(raw_data, i_start, i_stop)

File ~/miniforge3/envs/dart14/lib/python3.14/site-packages/neo/rawio/intanrawio.py:578, in IntanRawIO._demultiplex_digital_data(self, raw_digital_data, channel_ids, i_start, i_stop)
    576     mask = 1 << native_order
    577     demultiplex_data = np.bitwise_and(raw_digital_data, mask) > 0
--> 578     output[:, channel_index] = demultiplex_data[i_start:i_stop].flatten()
    580 return output

ValueError: could not broadcast input array from shape (82198272,) into shape (41099136,)

It seems like the demultiplex_data array has 82198272 samples like rec and that the output array (aux's length) is too small?

Environment:

  • OS: Linux
  • Python version: 3.14
  • Neo version: 0.14.4
  • NumPy version: 2.4.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions