Source code for neuroconv.datainterfaces.ecephys.openephys.openephysbinaryconverter
from pathlib import Path
from pydantic import DirectoryPath, validate_call
from .openephybinarysanaloginterface import OpenEphysBinaryAnalogInterface
from .openephysbinarydatainterface import OpenEphysBinaryRecordingInterface
from ....nwbconverter import ConverterPipe
from ....utils import get_json_schema_from_method_signature
[docs]
class OpenEphysBinaryConverter(ConverterPipe):
"""
Converter for multi-stream OpenEphys binary recording data.
Auto-discovers all streams in a folder and creates the appropriate interfaces
(recording for neural streams, analog for ADC/NI-DAQ streams).
"""
display_name = "OpenEphys Binary Converter"
keywords = OpenEphysBinaryRecordingInterface.keywords + OpenEphysBinaryAnalogInterface.keywords
associated_suffixes = OpenEphysBinaryRecordingInterface.associated_suffixes
info = "Converter for multi-stream OpenEphys binary recording data."
[docs]
@classmethod
def get_source_schema(cls) -> dict:
source_schema = get_json_schema_from_method_signature(method=cls.__init__, exclude=["exclude_streams"])
source_schema["properties"]["folder_path"][
"description"
] = "Path to the folder containing OpenEphys binary streams."
return source_schema
[docs]
@classmethod
def get_streams(cls, folder_path: DirectoryPath) -> list[str]:
"""
Get the stream names available in the folder.
Parameters
----------
folder_path : DirectoryPath
Path to the folder containing OpenEphys binary streams.
Returns
-------
list of str
The names of all available streams in the folder.
"""
from spikeinterface.extractors.extractor_classes import (
OpenEphysBinaryRecordingExtractor,
)
return OpenEphysBinaryRecordingExtractor.get_streams(folder_path=folder_path)[0]
@validate_call
def __init__(
self,
folder_path: DirectoryPath,
exclude_streams: list[str] | None = None,
verbose: bool = False,
):
"""
Read all data from every stream stored in OpenEphys binary format.
Parameters
----------
folder_path : DirectoryPath
Path to the folder containing OpenEphys binary streams.
exclude_streams : list of str, optional
Stream names to skip from auto-discovery. Useful for omitting a large
stream (for example an LFP band) during a fast test conversion.
``OpenEphysBinaryConverter.get_streams(folder_path=...)`` lists what is
available. Unknown names raise ``ValueError``.
verbose : bool, default: False
Whether to output verbose text.
"""
folder_path = Path(folder_path)
stream_names = self.get_streams(folder_path=folder_path)
if exclude_streams:
unknown = [name for name in exclude_streams if name not in stream_names]
if unknown:
raise ValueError(
f"Cannot exclude streams {unknown}: not present in {folder_path}. "
f"Available streams: {stream_names}."
)
stream_names = [name for name in stream_names if name not in exclude_streams]
non_neural_indicators = ["ADC", "NI-DAQ"]
is_non_neural = lambda name: any(indicator in name for indicator in non_neural_indicators)
_to_suffix = lambda name: name.rsplit(".", maxsplit=1)[-1].replace("-", "")
neural_streams = [name for name in stream_names if not is_non_neural(name)]
analog_streams = [name for name in stream_names if is_non_neural(name)]
data_interfaces = {}
for stream_name in neural_streams:
es_key = "ElectricalSeries" + _to_suffix(stream_name)
data_interfaces[stream_name] = OpenEphysBinaryRecordingInterface(
folder_path=folder_path,
stream_name=stream_name,
es_key=es_key,
)
for stream_name in analog_streams:
time_series_name = "TimeSeries" + _to_suffix(stream_name)
data_interfaces[stream_name] = OpenEphysBinaryAnalogInterface(
folder_path=folder_path,
stream_name=stream_name,
time_series_name=time_series_name,
)
super().__init__(data_interfaces=data_interfaces, verbose=verbose)
[docs]
def get_conversion_options_schema(self) -> dict:
conversion_options_schema = super().get_conversion_options_schema()
conversion_options_schema["properties"].update(
{name: interface.get_conversion_options_schema() for name, interface in self.data_interface_objects.items()}
)
return conversion_options_schema