SpikeInterface/probeinterface

Reassignment of channel ids when probe is assigned to Extractor

Closed this issue · 2 comments

I am working on an extension for spikeinterface for a data format that we use in our lab. I ran into the following issue and am seeking some guidance whether I am missing something or if there is a better way to go about this. Unfortunately I cannot really provide a lot of code details as the format is proprietary and I am not sure what I am allowed to share.

The device is an older Axion Maestro system (2D MEA system with, in this case, 16 electrodes on a multiwell plate) with the corresponding file format.

An example of the issue I ran into is depicted below:

  • I have the electrode ids and the recording channel ids as they are read from the file assigned correctly.
Target channel ordering:
['11:128', '12:129', '13:130', '14:131', '21:132', '22:140', '23:136', '24:142', '31:134', '32:143', '33:135', '34:138', '41:133', '42:137', '43:141', '44:139']
  • I created a Probe object with appropriate geometries and set the device channel indices
  • I assign the Probe object to a BaseRecordingExtractor object using set_probe(probe = foo, in_place = True)
  • The piece of code that seems to be causing me trouble are the following lines from the BaseRecordingSnippets class
# check TODO: Where did this came from?
number_of_device_channel_indices = np.max(list(device_channel_indices) + [0])
if number_of_device_channel_indices >= self.get_num_channels():
    error_msg = (
        f"The given Probe have 'device_channel_indices' that do not match channel count \n"
        f"{number_of_device_channel_indices} vs {self.get_num_channels()} \n"
        f"device_channel_indices are the following: {device_channel_indices} \n"
        f"recording channels are the following: {self.get_channel_ids()} \n"
    )
    raise ValueError(error_msg)

I don't really understand why the highest possible channel number is compared to the electrode count since it is entirely possible (at least on this device) that the current stream does not use the whole range of indices. However, I would like to have the correct channel indices assigned.
The only thing I could get to work to get around this issue, was to change the device_channel_indices to np.arange(len(electrodes)), which is obviously not the intended behaviour.
Additionally, the following section does in fact get the correct channel indices from the Neo reader with get_channel_ids but does not assign them to the class and does not throw an error either (since the new_channel_ids and get_channel_ids() refer to the same information in this case.

new_channel_ids = self.get_channel_ids()[device_channel_indices]
probe_as_numpy_array = probe_as_numpy_array[order]
probe_as_numpy_array["device_channel_indices"] = np.arange(probe_as_numpy_array.size, dtype="int64")

# create recording : channel slice or clone or self
if in_place:
    if not np.array_equal(new_channel_ids, self.get_channel_ids()):
        raise Exception("set_probe(inplace=True) must have all channel indices")
    sub_recording = self
else:
    if np.array_equal(new_channel_ids, self.get_channel_ids()):
        sub_recording = self.clone()
    else:
        sub_recording = self.channel_slice(new_channel_ids)

The end result of this is an erroneous assignment of channel ids (as I assigned them this way to get around the max(...) vs len(...) comparison check) which looks like this:

Assigned contact and channel ids:
['11:0', '12:1', '13:2', '14:3', '21:4', '22:5', '23:6', '24:7', '31:8', '32:9', '33:10', '34:11', '41:12', '42:13', '43:14', '44:15']

I feel like I am missing something here.

Hi,

The device_channel_indices tells how the channels (as defined in the probe) should be re-ordered in order to match the recorded traces. It's basically a channel mapping. They should be an integer value from 0 to 15 (in case of 16 electrodes).

To set them properly, you should use the probe.set_device_channel_indices(device_channel_indices_list) function.

Thanks for the response for the quick response. I didn't think about the possibility to just remap the signals relative to the neo stream. I thought you had to map them as the device maps them in the file.