Skip to content

Error NWB extractor: "electrodes_indices" must be in increasing order #4619

@borrepp

Description

@borrepp

Hello everyone,

I was trying to load a recording object from an NWB file and got an error. For context, this electrical series is the result of using spikeinterface to process (filtering & motion correction) and sort the units. At the end of the sorting process, we export the units and the processed recording back into the original NWB (following NEUROCONV naming convention). As a result of the processing with spikeinterface, the channels were sorted by their location on the probe. However, the electrode table in the NWB preserves the recording system ordering. When trying to load the electrical series with spikeinterface we got an error that electrode_indices are not in increasing order, which makes sense because they were sorted by location.

To avoid this restriction, I added "[:]" to extract the data into a numpy array, and then the indices do not need to be in increasing order. I'm not sure if this will cause issues while loading other properties, but it works for us for now. But if this is not the proper way to do it, we will wait for any further comments.

I made the changes in the following lines:

spikeinterface.version = 0.102.3

spikeinterface\extractors\nwbextractors.py

Line 774: 	channel_names = electrodes_table["channel_name"]
new: 	    channel_names = electrodes_table["channel_name"][:]


Line 798:       locations[:, 0] = electrodes_table["rel_x"][electrodes_indices]
new: 	   locations[:, 0] = electrodes_table["rel_x"][:][electrodes_indices]


Line 799:       locations[:, 1] = electrodes_table["rel_y"][electrodes_indices]
new: 	   locations[:, 1] = electrodes_table["rel_y"][:][electrodes_indices]


Line 801:       locations[:, 2] = electrodes_table["rel_z"][electrodes_indices]
new: 	   locations[:, 2] = electrodes_table["rel_z"][:][electrodes_indices]


Line 806: 	groups = electrodes_table["group_name"][electrodes_indices][:]
new: 	   groups = electrodes_table["group_name"][:][electrodes_indices][:]


Line 833: 	properties[column_name] = electrodes_table[column][electrodes_indices]
new: 	   properties[column_name] = electrodes_table[column][:][electrodes_indices]

Here is the error that I got when using "read_nwb":

----> 1 si_recording = read_nwb(
      2     file_path=NWBfile_path, 
      3     electrical_series_path='processing/ecephys/Processed/' + 'ephys-{}'.format(electrodeGroupName),
      4     load_recording=True,
      5     load_sorting=False
      6 )
      8 si_recording

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:1771, in read_nwb(file_path, load_recording, load_sorting, electrical_series_path)
   1769 outputs = ()
   1770 if load_recording:
-> 1771     rec = read_nwb_recording(file_path, electrical_series_path=electrical_series_path)
   1772     outputs = outputs + (rec,)
   1773 if load_sorting:

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:590, in NwbRecordingExtractor.__init__(self, file_path, electrical_series_name, load_time_vector, samples_for_rate_estimation, stream_mode, stream_cache_path, electrical_series_path, load_channel_properties, file, cache, storage_options, use_pynwb)
    576     (
    577         channel_ids,
    578         sampling_frequency,
   (...)
    581         times_kwargs,
    582     ) = self._fetch_recording_segment_info_pynwb(file, cache, load_time_vector, samples_for_rate_estimation)
    583 else:
    584     (
    585         channel_ids,
    586         sampling_frequency,
    587         dtype,
    588         segment_data,
    589         times_kwargs,
--> 590     ) = self._fetch_recording_segment_info_backend(file, cache, load_time_vector, samples_for_rate_estimation)
    592 BaseRecording.__init__(self, channel_ids=channel_ids, sampling_frequency=sampling_frequency, dtype=dtype)
    593 recording_segment = NwbRecordingSegment(
    594     electrical_series_data=segment_data,
    595     times_kwargs=times_kwargs,
    596 )

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:775, in NwbRecordingExtractor._fetch_recording_segment_info_backend(self, file, cache, load_time_vector, samples_for_rate_estimation)
    773 if "channel_name" in electrode_table_columns:
    774     channel_names = electrodes_table["channel_name"]
--> 775     channel_ids = channel_names[electrodes_indices]
    776     # Decode if bytes with utf-8
    777     channel_ids = [x.decode("utf-8") if isinstance(x, bytes) else x for x in channel_ids]

File h5py\\_objects.pyx:54, in h5py._objects.with_phil.wrapper()

File h5py\\_objects.pyx:55, in h5py._objects.with_phil.wrapper()

File m:\YauLab_Python\SIenv\Lib\site-packages\h5py\_hl\dataset.py:831, in Dataset.__getitem__(self, args, new_dtype)
    826     return arr
    828 # === Everything else ===================
    829 
    830 # Perform the dataspace selection.
--> 831 selection = sel.select(self.shape, args, dataset=self)
    833 if selection.nselect == 0:
    834     return numpy.zeros(selection.array_shape, dtype=new_dtype)

File m:\YauLab_Python\SIenv\Lib\site-packages\h5py\_hl\selections.py:82, in select(shape, args, dataset)
     79     space = h5s.create_simple(shape)
     80     selector = _selector.Selector(space)
---> 82 return selector.make_selection(args)

File h5py\\_selector.pyx:282, in h5py._selector.Selector.make_selection()

File h5py\\_selector.pyx:215, in h5py._selector.Selector.apply_args()

TypeError: Indexing elements must be in increasing order

And I got this one when I tried with "read_nwb_recording"

TypeError                                 Traceback (most recent call last)
Cell In[5], line 1
----> 1 si_recording = read_nwb_recording(
      2     file_path=NWBfile_path, 
      3     electrical_series_path='processing/ecephys/Processed/' + 'ephys-{}'.format(electrodeGroupName),
      4     use_pynwb=True
      5 )
      7 si_recording

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:601, in NwbRecordingExtractor.__init__(self, file_path, electrical_series_name, load_time_vector, samples_for_rate_estimation, stream_mode, stream_cache_path, electrical_series_path, load_channel_properties, file, cache, storage_options, use_pynwb)
    599 # fetch and add main recording properties
    600 if use_pynwb:
--> 601     gains, offsets, locations, groups = self._fetch_main_properties_pynwb()
    602 else:
    603     gains, offsets, locations, groups = self._fetch_main_properties_backend()

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:860, in NwbRecordingExtractor._fetch_main_properties_pynwb(self)
    857     offset = electrodes_table["offset"].data[electrodes_indices]
    858 offsets = offset * 1e6
--> 860 locations, groups = self._fetch_locations_and_groups(electrodes_table, electrodes_indices)
    862 return gains, offsets, locations, groups

File m:\YauLab_Python\SIenv\Lib\site-packages\spikeinterface\extractors\nwbextractors.py:798, in NwbRecordingExtractor._fetch_locations_and_groups(self, electrodes_table, electrodes_indices)
    796 ndim = 3 if "rel_z" in electrodes_table else 2
    797 locations = np.zeros((self.get_num_channels(), ndim), dtype=float)
--> 798 locations[:, 0] = electrodes_table["rel_x"][electrodes_indices]
    799 locations[:, 1] = electrodes_table["rel_y"][electrodes_indices]
    800 if "rel_z" in electrodes_table:

File m:\YauLab_Python\SIenv\Lib\site-packages\hdmf\container.py:974, in Data.__getitem__(self, args)
    973 def __getitem__(self, args):
--> 974     return self.get(args)

File m:\YauLab_Python\SIenv\Lib\site-packages\hdmf\common\table.py:61, in VectorData.get(self, key, **kwargs)
     54 def get(self, key, **kwargs):
     55     """
     56     Retrieve elements from this VectorData
     57 
     58     :param key: Selection of the elements
     59     :param kwargs: Ignored
     60     """
---> 61     return super().get(key)

File m:\YauLab_Python\SIenv\Lib\site-packages\hdmf\container.py:982, in Data.get(self, args)
    979 if isinstance(self.data, h5py.Dataset) and isinstance(args, np.ndarray):
    980     # This is needed for h5py 2.9 compatibility
    981     args = args.tolist()
--> 982 return self.data[args]

File h5py\\_objects.pyx:54, in h5py._objects.with_phil.wrapper()

File h5py\\_objects.pyx:55, in h5py._objects.with_phil.wrapper()

File m:\YauLab_Python\SIenv\Lib\site-packages\h5py\_hl\dataset.py:831, in Dataset.__getitem__(self, args, new_dtype)
    826     return arr
    828 # === Everything else ===================
    829 
    830 # Perform the dataspace selection.
--> 831 selection = sel.select(self.shape, args, dataset=self)
    833 if selection.nselect == 0:
    834     return numpy.zeros(selection.array_shape, dtype=new_dtype)

File m:\YauLab_Python\SIenv\Lib\site-packages\h5py\_hl\selections.py:82, in select(shape, args, dataset)
     79     space = h5s.create_simple(shape)
     80     selector = _selector.Selector(space)
---> 82 return selector.make_selection(args)

File h5py\\_selector.pyx:282, in h5py._selector.Selector.make_selection()

File h5py\\_selector.pyx:215, in h5py._selector.Selector.apply_args()

TypeError: Indexing elements must be in increasing order

Thanks in advance for any suggestions.
Best
Pepe

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No 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