Skip to content

Commit 9de4d4c

Browse files
h-mayorquinrly
andauthored
add NWBHDF5IO.read_nwb() method (#1979)
Co-authored-by: Ryan Ly <[email protected]>
1 parent ad04661 commit 9de4d4c

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## PyNWB 2.8.3 (Upcoming)
44

5+
### Enhancements and minor changes
6+
* Added `NWBHDF5IO.read_nwb` convenience method to simplify reading an NWB file. @h-mayorquin [#1979](https://github.com/NeurodataWithoutBorders/pynwb/pull/1979)
7+
58
### Documentation and tutorial enhancements
69
- Added documentation example for `SpikeEventSeries`. @stephprince [#1983](https://github.com/NeurodataWithoutBorders/pynwb/pull/1983)
710

requirements-opt.txt

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
linkml-runtime==1.7.4; python_version >= "3.9"
22
schemasheets==0.2.1; python_version >= "3.9"
33
oaklib==0.5.32; python_version >= "3.9"
4+
5+
# for streaming tests
6+
fsspec==2024.10.0
7+
requests==2.32.3
8+
aiohttp==3.10.10

src/pynwb/__init__.py

+28
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,34 @@ def export(self, **kwargs):
506506
kwargs['container'] = nwbfile
507507
super().export(**kwargs)
508508

509+
@staticmethod
510+
@docval({'name': 'path', 'type': (str, Path), 'doc': 'the path to the HDF5 file', 'default': None},
511+
{'name': 'file', 'type': [h5py.File, 'S3File'], 'doc': 'a pre-existing h5py.File object', 'default': None},
512+
is_method=False)
513+
def read_nwb(**kwargs):
514+
"""
515+
Helper factory method for reading an NWB file and return the NWBFile object
516+
"""
517+
# Retrieve the filepath
518+
path = popargs('path', kwargs)
519+
file = popargs('file', kwargs)
520+
521+
path = str(path) if path is not None else None
522+
523+
# Streaming case
524+
if path is not None and (path.startswith("s3://") or path.startswith("http")):
525+
import fsspec
526+
fsspec_file_system = fsspec.filesystem("http")
527+
ffspec_file = fsspec_file_system.open(path, "rb")
528+
529+
open_file = h5py.File(ffspec_file, "r")
530+
io = NWBHDF5IO(file=open_file)
531+
nwbfile = io.read()
532+
else:
533+
io = NWBHDF5IO(path=path, file=file, mode="r", load_namespaces=True)
534+
nwbfile = io.read()
535+
536+
return nwbfile
509537

510538
from . import io as __io # noqa: F401,E402
511539
from .core import NWBContainer, NWBData # noqa: F401,E402

tests/integration/hdf5/test_io.py

+42
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
from pynwb.testing.mock.file import mock_NWBFile
1919

2020

21+
import unittest
22+
try:
23+
import fsspec # noqa f401
24+
HAVE_FSSPEC = True
25+
except ImportError:
26+
HAVE_FSSPEC = False
27+
2128
class TestHDF5Writer(TestCase):
2229

2330
_required_tests = ('test_nwbio', 'test_write_clobber', 'test_write_cache_spec', 'test_write_no_cache_spec')
@@ -586,3 +593,38 @@ def test_can_read_file_old_version(self):
586593
def test_can_read_file_invalid_hdf5_file(self):
587594
# current file is not an HDF5 file
588595
self.assertFalse(NWBHDF5IO.can_read(__file__))
596+
597+
def test_read_nwb_method_path(self):
598+
599+
# write the example file
600+
with NWBHDF5IO(self.path, 'w') as io:
601+
io.write(self.nwbfile)
602+
603+
# test that the read_nwb method works
604+
read_nwbfile = NWBHDF5IO.read_nwb(path=self.path)
605+
self.assertContainerEqual(read_nwbfile, self.nwbfile)
606+
607+
read_nwbfile.get_read_io().close()
608+
609+
def test_read_nwb_method_file(self):
610+
611+
# write the example file
612+
with NWBHDF5IO(self.path, 'w') as io:
613+
io.write(self.nwbfile)
614+
615+
import h5py
616+
617+
file = h5py.File(self.path, 'r')
618+
619+
read_nwbfile = NWBHDF5IO.read_nwb(file=file)
620+
self.assertContainerEqual(read_nwbfile, self.nwbfile)
621+
622+
read_nwbfile.get_read_io().close()
623+
624+
@unittest.skipIf(not HAVE_FSSPEC, "fsspec library not available")
625+
def test_read_nwb_method_s3_path(self):
626+
s3_test_path = "https://dandiarchive.s3.amazonaws.com/blobs/11e/c89/11ec8933-1456-4942-922b-94e5878bb991"
627+
read_nwbfile = NWBHDF5IO.read_nwb(path=s3_test_path)
628+
assert read_nwbfile.identifier == "3f77c586-6139-4777-a05d-f603e90b1330"
629+
630+
assert read_nwbfile.subject.subject_id == "1"

0 commit comments

Comments
 (0)