Skip to content
Merged
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
18 changes: 15 additions & 3 deletions neo/rawio/axonrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,13 @@ def parse_axon_soup(filename):

Returns
-------
dict or None
Header dictionary with file metadata, or None if file signature is invalid
dict
Header dictionary with file metadata.

Raises
------
NeoReadWriteError
If the file does not start with a valid ABF signature (b"ABF " or b"ABF2").
"""
with open(filename, "rb") as fid:
f = StructFile(fid)
Expand All @@ -502,7 +507,14 @@ def parse_axon_soup(filename):
elif signature == b"ABF2":
return _parse_abf_v2(f, headerDescriptionV2)
else:
return None
# The first 4 bytes are the ABF magic; anything else means the file is not an ABF
# file, is corrupt, or is an unsupported variant. Raise here rather than returning
# None so the caller gets a clear error instead of a downstream NoneType access.
raise NeoReadWriteError(
f"Could not parse {filename} as an ABF file: expected the header to start with "
f"signature b'ABF ' or b'ABF2', but found {signature}. The file is not an ABF "
f"file, is corrupt, or is an unsupported variant."
)


def _parse_abf_v1(f, header_description):
Expand Down
15 changes: 15 additions & 0 deletions neo/test/rawiotest/test_axonrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import unittest

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

from neo.test.rawiotest.common_rawio_test import BaseTestRawIO

Expand Down Expand Up @@ -29,6 +30,20 @@ def test_read_raw_protocol(self):

reader.read_raw_protocol()

def test_unparseable_file_raises(self):
# A file whose header does not start with a valid ABF signature must raise a clear error
# rather than a cryptic NoneType error deep in parsing. The fixture has a zeroed signature.
path = self.get_local_path("axon/intracellular_data/files_with_errors/unparseable_header.abf")
expected_msg = (
f"Could not parse {path} as an ABF file: expected the header to start with signature "
f"b'ABF ' or b'ABF2', but found b'\\x00\\x00\\x00\\x00'. The file is not an ABF file, "
f"is corrupt, or is an unsupported variant."
)
reader = AxonRawIO(filename=path)
with self.assertRaises(NeoReadWriteError) as cm:
reader.parse_header()
self.assertEqual(str(cm.exception), expected_msg)

def test_v1_reads_real_acquisition_date(self):
# ABF1 stores the calendar date in lFileStartDate (a YYYYMMDD-packed integer). Older neo
# ignored that field and hardcoded 1900-01-01, so the recording date was always wrong for
Expand Down
Loading