-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support arbitrary multi probe and multi trigger structures in spikeglx #1150
Changes from 12 commits
58120d6
b560f29
ca00c34
1b350f1
683ba39
25e6486
78b9132
f12a900
79ac49d
e702a58
71b3299
a965d23
4d21be6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ | |
from typing import Optional | ||
|
||
import numpy as np | ||
from pydantic import FilePath, validate_call | ||
from pydantic import DirectoryPath, FilePath, validate_call | ||
|
||
from .spikeglx_utils import ( | ||
add_recording_extractor_properties, | ||
|
@@ -45,7 +45,6 @@ def get_source_schema(cls) -> dict: | |
def _source_data_to_extractor_kwargs(self, source_data: dict) -> dict: | ||
|
||
extractor_kwargs = source_data.copy() | ||
extractor_kwargs.pop("file_path") | ||
extractor_kwargs["folder_path"] = self.folder_path | ||
extractor_kwargs["all_annotations"] = True | ||
extractor_kwargs["stream_id"] = self.stream_id | ||
|
@@ -54,38 +53,58 @@ def _source_data_to_extractor_kwargs(self, source_data: dict) -> dict: | |
@validate_call | ||
def __init__( | ||
self, | ||
file_path: FilePath, | ||
file_path: Optional[FilePath] = None, | ||
verbose: bool = True, | ||
es_key: Optional[str] = None, | ||
folder_path: Optional[DirectoryPath] = None, | ||
stream_id: Optional[str] = None, | ||
): | ||
""" | ||
Parameters | ||
---------- | ||
folder_path: DirectoryPath | ||
Folder path containing the binary files of the SpikeGLX recording. | ||
stream_id: str, optional | ||
Stream ID of the SpikeGLX recording. | ||
file_path : FilePathType | ||
Path to .bin file. Point to .ap.bin for SpikeGLXRecordingInterface and .lf.bin for SpikeGLXLFPInterface. | ||
verbose : bool, default: True | ||
Whether to output verbose text. | ||
es_key : str, default: "ElectricalSeries" | ||
es_key : str, the key to access the metadata of the ElectricalSeries. | ||
""" | ||
|
||
self.stream_id = fetch_stream_id_for_spikelgx_file(file_path) | ||
if es_key is None: | ||
if "lf" in self.stream_id: | ||
es_key = "ElectricalSeriesLF" | ||
elif "ap" in self.stream_id: | ||
es_key = "ElectricalSeriesAP" | ||
else: | ||
raise ValueError("Cannot automatically determine es_key from path") | ||
file_path = Path(file_path) | ||
self.folder_path = file_path.parent | ||
if file_path is not None and stream_id is None: | ||
self.stream_id = fetch_stream_id_for_spikelgx_file(file_path) | ||
self.folder_path = Path(file_path).parent | ||
|
||
else: | ||
self.stream_id = stream_id | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we check here to ensure that stream_id is one of the valid streams and give an error message with a list of valid streams if it is not? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok great! Yeah that works There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anything else missing to merge thigs? |
||
self.folder_path = Path(folder_path) | ||
|
||
super().__init__( | ||
file_path=file_path, | ||
folder_path=folder_path, | ||
verbose=verbose, | ||
es_key=es_key, | ||
) | ||
self.source_data["file_path"] = str(file_path) | ||
self.meta = self.recording_extractor.neo_reader.signals_info_dict[(0, self.stream_id)]["meta"] | ||
|
||
signal_info_key = (0, self.stream_id) # Key format is (segment_index, stream_id) | ||
self._signals_info_dict = self.recording_extractor.neo_reader.signals_info_dict[signal_info_key] | ||
self.meta = self._signals_info_dict["meta"] | ||
|
||
if es_key is None: | ||
stream_kind = self._signals_info_dict["stream_kind"] # ap or lf | ||
stream_kind_caps = stream_kind.upper() | ||
device = self._signals_info_dict["device"].capitalize() # imec0, imec1, etc. | ||
|
||
electrical_series_name = f"ElectricalSeries{stream_kind_caps}" | ||
|
||
# Add imec{probe_index} to the electrical series name when there are multiple probes | ||
# or undefined, `typeImEnabled` is present in the meta of all the production probes | ||
self.probes_enabled_in_run = int(self.meta.get("typeImEnabled", 0)) | ||
if self.probes_enabled_in_run != 1: | ||
electrical_series_name += f"{device}" | ||
|
||
self.es_key = electrical_series_name | ||
|
||
# Set electrodes properties | ||
add_recording_extractor_properties(self.recording_extractor) | ||
|
@@ -100,7 +119,7 @@ def get_metadata(self) -> dict: | |
device = get_device_metadata(self.meta) | ||
|
||
# Should follow pattern 'Imec0', 'Imec1', etc. | ||
probe_name = self.stream_id[:5].capitalize() | ||
probe_name = self._signals_info_dict["device"].capitalize() | ||
device["name"] = f"Neuropixel{probe_name}" | ||
|
||
# Add groups metadata | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,9 +29,9 @@ | |
"device": "NIDQBoard" | ||
} | ||
], | ||
"ElectricalSeriesAPImec0": { | ||
"name": "ElectricalSeriesAPImec0", | ||
"description": "Acquisition traces for the ElectricalSeriesAPImec0." | ||
"ElectricalSeriesAP": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See this comment for the change: |
||
"name": "ElectricalSeriesAP", | ||
"description": "Acquisition traces for the ElectricalSeriesAP." | ||
}, | ||
"Electrodes": [ | ||
{ | ||
|
@@ -51,9 +51,9 @@ | |
"name": "ElectricalSeriesNIDQ", | ||
"description": "Raw acquisition traces from the NIDQ (.nidq.bin) channels." | ||
}, | ||
"ElectricalSeriesLFImec0": { | ||
"name": "ElectricalSeriesLFImec0", | ||
"description": "Acquisition traces for the ElectricalSeriesLFImec0." | ||
"ElectricalSeriesLF": { | ||
"name": "ElectricalSeriesLF", | ||
"description": "Acquisition traces for the ElectricalSeriesLF." | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the critical part of this. Previously, the Converter assumed a fix structure of the files. This PR gets rids of that assumption.