Skip to content

Commit

Permalink
Merge pull request #96 from catalystneuro/custom_subconverter
Browse files Browse the repository at this point in the history
Add custom spikeglx subconverter
  • Loading branch information
CodyCBakerPhD authored Sep 29, 2024
2 parents b892c50 + 9d72fd0 commit fab3d0d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 34 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ An `Interface` reads a single data stream (such as DLC pose estimation) and crea

The `Converter` orchestrates the conversion by combining multiple interfaces, and can also be used to add additional metadata to the NWB file. It is responsible for creating the NWB file saved to disk.

Occasionally, a sub-`Converter`, such as the `IBLSpikeGLXConverter`, will be used to handle the conversion of multiple data streams that is more complex than a single interface can handle; though these behave like other `Interfaces` with respect to the main orchestrating `Converter`.

## Metadata

Anywhere you see handwritten text in the NWB files that is meant to be human-readable, it is likely that it was copied from the public Google IBL documents and written in the `.yaml` files found in `src/ibl_to_nwb/_metadata`.
Expand Down
40 changes: 6 additions & 34 deletions src/ibl_to_nwb/_scripts/convert_brainwide_map_raw_only.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from pathlib import Path

from brainbox.io.one import EphysSessionLoader, SpikeSortingLoader
from neuroconv.datainterfaces import SpikeGLXRecordingInterface
from one.api import ONE

from ibl_to_nwb.converters import BrainwideMapConverter
from ibl_to_nwb.converters import BrainwideMapConverter, IblSpikeGlxConverter
from ibl_to_nwb.datainterfaces import RawVideoInterface

session_id = "d32876dd-8303-4720-8e7e-20678dc2fd71"
Expand All @@ -28,39 +26,13 @@
)

# Specify the path to the SpikeGLX files on the server but use ONE API for timestamps
probe_1_source_folder_path = Path("D:/example_data/ephy_testing_data/spikeglx/Noise4Sam_g0")
probe_2_source_folder_path = Path(
"D:/example_data/ephy_testing_data/spikeglx/multi_trigger_multi_gate/SpikeGLX/5-19-2022-CI0/5-19-2022-CI0_g0/"
)


# Initialize interfaces one probe at a time and properly align raw timestamps
ephys_session_loader = EphysSessionLoader(one=ibl_client, eid=session_id)

probe_to_imec_map = {
"probe00": 0,
"probe01": 1,
}

data_interfaces = list()
for probe_name, pid in ephys_session_loader.probes.items():
spike_sorting_loader = SpikeSortingLoader(pid=pid, one=ibl_client)

probe_index = probe_to_imec_map[probe_name]
for band in ["ap", "lf"]:
file_path = probe_1_source_folder_path / f"Noise4Sam_g0_imec0/Noise4Sam_g0_t0.imec{probe_index}.{band}.bin"
interface = SpikeGLXRecordingInterface(file_path=file_path)

# This is the syntax for aligning the raw timestamps; I cannot test this without the actual data as stored
# on your end, so please work with Heberto if there are any problems after uncommenting

# band_info = spike_sorting_loader.raw_electrophysiology(band=band, stream=True)
# aligned_timestamps = spike_sorting_loader.samples2times(numpy.arange(0, band_info.ns), direction='forward')
# interface.set_aligned_timestamps(aligned_timestamps=aligned_timestamps)
data_interfaces = []

data_interfaces.append(interface)
spikeglx_source_folder_path = Path("D:/example_data/ephy_testing_data/spikeglx/Noise4Sam_g0")
spikeglx_subconverter = IblSpikeGlxConverter(folder_path=spikeglx_source_folder_path, one=ibl_client)
data_interfaces.append(spikeglx_subconverter)

# Raw video take some special handling
# Raw video takes some special handling
metadata_retrieval = BrainwideMapConverter(one=ibl_client, session=session_id, data_interfaces=[], verbose=False)
subject_id = metadata_retrieval.get_metadata()["Subject"]["subject_id"]

Expand Down
2 changes: 2 additions & 0 deletions src/ibl_to_nwb/converters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from ._brainwide_map_converter import BrainwideMapConverter
from ._iblconverter import IblConverter
from ._ibl_spikeglx_converter import IblSpikeGlxConverter

__all__ = [
"BrainwideMapConverter",
"IblConverter",
"IblSpikeGlxConverter",
]
44 changes: 44 additions & 0 deletions src/ibl_to_nwb/converters/_ibl_spikeglx_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from neuroconv.converters import SpikeGLXConverterPipe
from one.api import ONE
from pydantic import DirectoryPath
from pynwb import NWBFile


class IblSpikeGlxConverter(SpikeGLXConverterPipe):

def __init__(self, folder_path: DirectoryPath, one: ONE) -> None:
super().__init__(folder_path=folder_path)
self.one = one

def temporally_align_data_interfaces(self) -> None:
"""Align the raw data timestamps to the other data streams using the ONE API."""
# This is the syntax for aligning the raw timestamps; I cannot test this without the actual data as stored
# on your end, so please work with Heberto if there are any problems after uncommenting
# probe_to_imec_map = {
# "probe00": 0,
# "probe01": 1,
# }
#
# ephys_session_loader = EphysSessionLoader(one=self.one, eid=session_id)
# probes = ephys_session_loader.probes
# for probe_name, pid in ephys_session_loader.probes.items():
# spike_sorting_loader = SpikeSortingLoader(pid=pid, one=ibl_client)
#
# probe_index = probe_to_imec_map[probe_name]
# for band in ["ap", "lf"]:
# recording_interface = next(
# interface
# for interface in self.data_interface_objects
# if f"imec{probe_index}.{band}" in interface.source_data["file_path"]
# )
#
# band_info = spike_sorting_loader.raw_electrophysiology(band=band, stream=True)
# aligned_timestamps = spike_sorting_loader.samples2times(numpy.arange(0, band_info.ns), direction='forward')
# recording_interface.set_aligned_timestamps(aligned_timestamps=aligned_timestamps)
pass

def add_to_nwbfile(self, nwbfile: NWBFile, metadata) -> None:
self.temporally_align_data_interfaces()
super().add_to_nwbfile(nwbfile=nwbfile, metadata=metadata)

# TODO: Add ndx-extracellular-ephys here

0 comments on commit fab3d0d

Please sign in to comment.