Skip to content
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

Add ignore_timestamps_errors to OpenEphys interfaces #579

Closed
wants to merge 8 commits into from
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
* Removed `use_times` and `buffer_size` from `add_photon_series`. [PR #600](https://github.com/catalystneuro/neuroconv/pull/600)


* Changed the date parsing in `OpenEphysLegacyRecordingInterface` to `datetime.strptime` with the expected date format explicitly set to `"%d-%b-%Y %H%M%S"`. [PR #577](https://github.com/catalystneuro/neuroconv/pull/577)
* Added `ignore_timestamps_errors` keyword argument to `OpenEphysRecordingInterface` and `OpenEphysLegacyRecordingInterface` to have the possibility of ignoring discontinuous timestamps errors in neo. [PR #579](https://github.com/catalystneuro/neuroconv/pull/579)

# v0.4.4

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def __new__(
stream_name: Optional[str] = None,
verbose: bool = True,
es_key: str = "ElectricalSeries",
ignore_timestamps_errors: bool = False,
):
"""
Abstract class that defines which interface class to use for a given Open Ephys recording.
Expand All @@ -34,13 +35,19 @@ def __new__(
When channel stream is not available the name of the stream must be specified.
verbose : bool, default: True
es_key : str, default: "ElectricalSeries"
ignore_timestamps_errors : bool, default: False
Ignore the discontinuous timestamps error in neo. Only relevant for the "legacy" format (.continuous) files.
"""
super().__new__(cls)

folder_path = Path(folder_path)
if any(folder_path.rglob("*.continuous")):
return OpenEphysLegacyRecordingInterface(
folder_path=folder_path, stream_name=stream_name, verbose=verbose, es_key=es_key
folder_path=folder_path,
stream_name=stream_name,
verbose=verbose,
es_key=es_key,
ignore_timestamps_errors=ignore_timestamps_errors,
)

elif any(folder_path.rglob("*.dat")):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ class OpenEphysLegacyRecordingInterface(BaseRecordingExtractorInterface):
Uses :py:class:`~spikeinterface.extractors.OpenEphysLegacyRecordingExtractor`."""

@classmethod
def get_stream_names(cls, folder_path: FolderPathType) -> List[str]:
def get_stream_names(cls, folder_path: FolderPathType, ignore_timestamps_errors: bool = False) -> List[str]:
from spikeinterface.extractors import OpenEphysLegacyRecordingExtractor

stream_names, _ = OpenEphysLegacyRecordingExtractor.get_streams(folder_path=folder_path)
stream_names, _ = OpenEphysLegacyRecordingExtractor.get_streams(
folder_path=folder_path,
ignore_timestamps_errors=ignore_timestamps_errors,
)
return stream_names

@classmethod
Expand All @@ -33,6 +36,7 @@ def __init__(
stream_name: Optional[str] = None,
verbose: bool = True,
es_key: str = "ElectricalSeries",
ignore_timestamps_errors: bool = False,
):
"""
Initialize reading of OpenEphys legacy recording (.continuous files).
Expand All @@ -46,8 +50,12 @@ def __init__(
The name of the recording stream.
verbose : bool, default: True
es_key : str, default: "ElectricalSeries"
ignore_timestamps_errors : bool, default: False
Ignore the discontinuous timestamps error in neo.
"""
available_streams = self.get_stream_names(folder_path=folder_path)
available_streams = self.get_stream_names(
folder_path=folder_path, ignore_timestamps_errors=ignore_timestamps_errors
)
if len(available_streams) > 1 and stream_name is None:
raise ValueError(
"More than one stream is detected! Please specify which stream you wish to load with the `stream_name` argument. "
Expand All @@ -58,7 +66,21 @@ def __init__(
f"The selected stream '{stream_name}' is not in the available streams '{available_streams}'!"
)

super().__init__(folder_path=folder_path, stream_name=stream_name, verbose=verbose, es_key=es_key)
super().__init__(
folder_path=folder_path,
stream_name=stream_name,
ignore_timestamps_errors=ignore_timestamps_errors,
verbose=verbose,
es_key=es_key,
)

if ignore_timestamps_errors and self.recording_extractor.has_time_vector():
for segment_index in range(self.recording_extractor.get_num_segments()):
self.recording_extractor._recording_segments[segment_index].time_vector = None
warn(
"The recording has a time vector but the timestamps might be discontinuous. "
"The time vector was reset to None to avoid writing these timestamps with the electrical series."
)

def get_metadata(self):
metadata = super().get_metadata()
Expand Down
2 changes: 1 addition & 1 deletion src/neuroconv/datainterfaces/ecephys/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
spikeinterface>=0.98.2
spikeinterface @ git+https://github.com/SpikeInterface/spikeinterface.git@8ea82ee0a43f04c8a51017651710e19eb9a156db
packaging<22.0
Loading