Skip to content

Commit

Permalink
add documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
h-mayorquin committed Dec 12, 2024
1 parent a787680 commit edaaf40
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 2 deletions.
1 change: 1 addition & 0 deletions docs/user_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ and synchronize data across multiple sources.
csvs
expand_path
backend_configuration
linking_sorted_data
yaml
docker_demo
aws_demo
74 changes: 74 additions & 0 deletions docs/user_guide/linking_sorted_data.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
.. _linking_sorted_data:

How to Link Sorted Data to Electrodes
===================================

The ``SortedRecordingConverter`` maintains proper linkage between sorted units and their corresponding recording channels in NWB files.
It handles the critical relationship between ``Units`` and ``Electrodes`` tables by:

* Creating electrode table regions for each unit
* Maintaining electrode group and device relationships
* Mapping channel IDs to electrode indices correctly

This automated handling ensures proper provenance tracking in the NWB file, which is essential for interpreting and analyzing sorted electrophysiology data.

Basic Usage
----------

Single Probe and Single Recording
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This example demonstrates linking data from a single Neuropixel probe recorded with SpikeGLX and sorted with Kilosort.

The converter requires three components:

1. A recording interface (:py:class:`~neuroconv.datainterfaces.ecephys.spikeglx.spikeglxrecordinginterface.SpikeGLXRecordingInterface`)
2. A sorting interface (:py:class:`~neuroconv.datainterfaces.ecephys.kilosort.kilosortinterface.KiloSortSortingInterface`)
3. A mapping between unit IDs and their associated channel IDs

First, instantiate the interfaces::

from neuroconv import SortedRecordingConverter
from neuroconv.datainterfaces import SpikeGLXRecordingInterface, KiloSortSortingInterface

# Initialize interfaces
recording_interface = SpikeGLXRecordingInterface(
folder_path="path/to/spikeglx_data",
stream_id="imec0.ap"
)
sorting_interface = KiloSortSortingInterface(
folder_path="path/to/kilosort_data"
)

Access channel and unit IDs through interface properties::

# Access channel IDs
print(recording_interface.channel_ids)
# Example output: ['imec0.ap#AP0', 'imec0.ap#AP1', 'imec0.ap#AP2', ...]

# Access unit IDs
print(sorting_interface.unit_ids)
# Example output: ['0', '1', '2', ...]

Define the mapping between units and channels::

unit_ids_to_channel_ids = {
"0": ["imec0.ap#AP0", "imec0.ap#AP1"], # Unit 0 detected on two channels
"1": ["imec0.ap#AP2"], # Unit 1 detected on one channel
"2": ["imec0.ap#AP3", "imec0.ap#AP4"], # Unit 2 detected on two channels
... # Map all remaining units to their respective channels
}

.. note::

Every unit from the sorting interface must have a corresponding channel mapping.

Create the converter and run the conversion::

converter = SortedRecordingConverter(
recording_interface=recording_interface,
sorting_interface=sorting_interface,
unit_ids_to_channel_ids=unit_ids_to_channel_ids
)

nwbfile = converter.run_conversion(nwbfile_path="path/to/output.nwb")
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ def get_metadata(self) -> DeepDict:

return metadata

@property
def channel_ids(self):
"Gets the channel ids of the data."
return self.recording_extractor.get_channel_ids()

def get_original_timestamps(self) -> Union[np.ndarray, list[np.ndarray]]:
"""
Retrieve the original unaltered timestamps for the data in this interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ def get_metadata_schema(self) -> dict:
)
return metadata_schema

@property
def units_ids(self):
"Gets the units ids of the data."
return self.sorting_extractor.get_unit_ids()

def register_recording(self, recording_interface: BaseRecordingExtractorInterface):
self.sorting_extractor.register_recording(recording=recording_interface.recording_extractor)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ def __init__(
self.sorting_interface = sorting_interface
self.unit_ids_to_channel_ids = unit_ids_to_channel_ids

self.channel_ids = self.recording_interface.recording_extractor.get_channel_ids()
self.unit_ids = self.sorting_interface.sorting_extractor.get_unit_ids()
self.channel_ids = self.recording_interface.channel_ids
self.unit_ids = self.sorting_interface.units_ids

# Convert channel_ids to set for comparison
available_channels = set(self.channel_ids)
Expand Down

0 comments on commit edaaf40

Please sign in to comment.