Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions neo/rawio/axonrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,13 @@ def _parse_abf_v1(f, header_description):
ss = header["lFileStartTime"] - hh * 3600 - mm * 60
ms = int(np.mod(ss, 1) * 1e6)
ss = int(ss)
header["rec_datetime"] = datetime.datetime(YY, MM, DD, hh, mm, ss, ms)
try:
header["rec_datetime"] = datetime.datetime(YY, MM, DD, hh, mm, ss, ms)
except (ValueError, OverflowError):
# Date/time header fields hold an out-of-range or "no date" sentinel

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we warn people? I don't know this system well enough to know if warning a person that they didn't have an acquisition time is a marker of a "poor" acquisition or is something that the user should know they forgot to set up? What do you think? It's not actionable, but it might be valuable for the user to know. I just don't know the reader.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am honestly not sure a missing date is a real problem, so I would rather follow pyABF precedent here to just skip it. As far as I can tell it happens because the date field holds an unset/sentinel value (0xFFFFFFFF) that does not parse into a real date, and pyABF does not treat that as fatal either, it just falls back.

In addition, most users of neo do not really use this field so I don't think the warning will be useful for their purposes. Most of the datetime work was done to parse metadata for neuroconv where this is required and there it fails loudly so I think is Ok.

Btw, thanks for making me check this, I found another error that I will address.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# (e.g. 0xFFFFFFFF). The acquisition date is non-essential annotation,
# so fall back to None rather than blocking the read of the signal.
header["rec_datetime"] = None

return header

Expand Down Expand Up @@ -1025,7 +1031,13 @@ def _parse_abf_v2(f, header_description):
ss = header["uFileStartTimeMS"] / 1000.0 - hh * 3600 - mm * 60
ms = int(np.mod(ss, 1) * 1e6)
ss = int(ss)
header["rec_datetime"] = datetime.datetime(YY, MM, DD, hh, mm, ss, ms)
try:
header["rec_datetime"] = datetime.datetime(YY, MM, DD, hh, mm, ss, ms)
except (ValueError, OverflowError):
# Date/time header fields hold an out-of-range or "no date" sentinel
# (e.g. 0xFFFFFFFF). The acquisition date is non-essential annotation,
# so fall back to None rather than blocking the read of the signal.
header["rec_datetime"] = None

return header

Expand Down
14 changes: 13 additions & 1 deletion neo/test/rawiotest/test_axonrawio.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import unittest

from neo.rawio.axonrawio import AxonRawIO
from neo.rawio.axonrawio import AxonRawIO, parse_axon_soup

from neo.test.rawiotest.common_rawio_test import BaseTestRawIO

Expand Down Expand Up @@ -28,6 +28,18 @@ def test_read_raw_protocol(self):

reader.read_raw_protocol()

def test_invalid_date_falls_back_to_none(self):
# Some ABF files store an out-of-range / "no date" sentinel (e.g. 0xFFFFFFFF)
# in the acquisition date header fields. The date is non-essential annotation,
# so parsing must fall back to rec_datetime=None rather than raising and
# blocking access to the signal.
for fixture in [
"axon/intracellular_data/files_with_errors/invalid_date_abf1.abf", # ABF v1
"axon/intracellular_data/files_with_errors/invalid_date_abf2.abf", # ABF v2
]:
header = parse_axon_soup(self.get_local_path(fixture))
self.assertIsNone(header["rec_datetime"])


if __name__ == "__main__":
unittest.main()
Loading