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

Remove try/except around NWBZarrIO #242

Merged
merged 5 commits into from
Nov 22, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### Bug Fixes
* Fix reading of cached specs and caching of specs during export. @rly [#232](https://github.com/hdmf-dev/hdmf-zarr/pull/232)
* Fix hiding of pynwb compatibility errors. @rly [242](https://github.com/hdmf-dev/hdmf-zarr/pull/242)

## 0.9.0 (September 16, 2024)
### Enhancements
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ classifiers = [
"Topic :: Scientific/Engineering :: Medical Science Apps."
]
dependencies = [
'hdmf>=3.14.3',
'hdmf>=3.14.5',
'zarr>=2.11.0, <3.0', # pin below 3.0 until HDMF-zarr supports zarr 3.0
'numpy>=1.24',
'numcodecs>=0.9.1',
'pynwb>=2.5.0',
'pynwb>=2.8.3',
'threadpoolctl>=3.1.0',
]
dynamic = ["version"]
Expand Down Expand Up @@ -123,7 +123,7 @@ exclude = [
]
line-length = 120

[tool.ruff.per-file-ignores]
[tool.ruff.lint.per-file-ignores]
"docs/gallery/*" = ["E402", "T201"]
"src/*/__init__.py" = ["F401"]
"test_gallery.py" = ["T201"]
Expand Down
5 changes: 3 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
hdmf==3.14.5
zarr==2.18.3; python_version >= "3.10" # zarr 2.18.3 dropped support for python 3.9
zarr==2.18.2; python_version < "3.10"
pynwb==2.8.2
numpy==2.1.3
pynwb==2.8.3
numpy==2.1.3; python_version >= "3.10" # numpy 2.1.0 dropped support for python 3.9
numpy==2.0.2; python_version < "3.10"
numcodecs==0.13.1
threadpoolctl==3.5.0
144 changes: 70 additions & 74 deletions src/hdmf_zarr/nwb.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Module with Zarr backend for NWB for integration with PyNWB"""
from warnings import warn
from pathlib import Path
from .backend import ZarrIO, SUPPORTED_ZARR_STORES

Expand All @@ -9,85 +8,82 @@
from hdmf.backends.io import HDMFIO
from hdmf.build import (BuildManager,
TypeMap)
try:
from pynwb import get_manager, get_type_map
from pynwb import get_manager, get_type_map

class NWBZarrIO(ZarrIO):
"""
IO backend for PyNWB for writing NWB files

This class is similar to the :py:class:`~pynwb.NWBHDF5IO` class in PyNWB. The main purpose of this class
is to perform default setup for BuildManager, loading or namespaces etc., in the context
of the NWB format.
"""
@docval(*get_docval(ZarrIO.__init__),
{'name': 'load_namespaces', 'type': bool,
'doc': 'whether or not to load cached namespaces from given path - not applicable in write mode',
'default': True},
{'name': 'extensions', 'type': (str, TypeMap, list),
'doc': 'a path to a namespace, a TypeMap, or a list consisting paths to namespaces and TypeMaps',
'default': None})
def __init__(self, **kwargs):
path, mode, manager, extensions, load_namespaces, synchronizer, storage_options = \
popargs('path', 'mode', 'manager', 'extensions',
'load_namespaces', 'synchronizer', 'storage_options', kwargs)
class NWBZarrIO(ZarrIO):
"""
IO backend for PyNWB for writing NWB files

io_modes_that_create_file = ['w', 'w-', 'x']
if mode in io_modes_that_create_file or manager is not None or extensions is not None:
load_namespaces = False
This class is similar to the :py:class:`~pynwb.NWBHDF5IO` class in PyNWB. The main purpose of this class
is to perform default setup for BuildManager, loading or namespaces etc., in the context
of the NWB format.
"""
@docval(*get_docval(ZarrIO.__init__),
{'name': 'load_namespaces', 'type': bool,
'doc': 'whether or not to load cached namespaces from given path - not applicable in write mode',
'default': True},
{'name': 'extensions', 'type': (str, TypeMap, list),
'doc': 'a path to a namespace, a TypeMap, or a list consisting paths to namespaces and TypeMaps',
'default': None})
def __init__(self, **kwargs):
path, mode, manager, extensions, load_namespaces, synchronizer, storage_options = \
popargs('path', 'mode', 'manager', 'extensions',
'load_namespaces', 'synchronizer', 'storage_options', kwargs)

if load_namespaces:
tm = get_type_map()
super(NWBZarrIO, self).load_namespaces(tm, path, storage_options)
manager = BuildManager(tm)
else:
if manager is not None and extensions is not None:
raise ValueError("'manager' and 'extensions' cannot be specified together")
elif extensions is not None:
manager = get_manager(extensions=extensions)
elif manager is None:
manager = get_manager()
super(NWBZarrIO, self).__init__(path,
manager=manager,
mode=mode,
synchronizer=synchronizer,
storage_options=storage_options)
io_modes_that_create_file = ['w', 'w-', 'x']
if mode in io_modes_that_create_file or manager is not None or extensions is not None:
load_namespaces = False

@docval({'name': 'src_io', 'type': HDMFIO, 'doc': 'the HDMFIO object for reading the data to export'},
{'name': 'nwbfile', 'type': 'NWBFile',
'doc': 'the NWBFile object to export. If None, then the entire contents of src_io will be exported',
'default': None},
{'name': 'write_args', 'type': dict, 'doc': 'arguments to pass to :py:meth:`write_builder`',
'default': dict()})
def export(self, **kwargs):
nwbfile = popargs('nwbfile', kwargs)
kwargs['container'] = nwbfile
super().export(**kwargs)
if load_namespaces:
tm = get_type_map()
super(NWBZarrIO, self).load_namespaces(tm, path, storage_options)
manager = BuildManager(tm)
else:
if manager is not None and extensions is not None:
raise ValueError("'manager' and 'extensions' cannot be specified together")
elif extensions is not None:
manager = get_manager(extensions=extensions)
elif manager is None:
manager = get_manager()
super(NWBZarrIO, self).__init__(path,
manager=manager,
mode=mode,
synchronizer=synchronizer,
storage_options=storage_options)

@staticmethod
@docval({'name': 'path',
'type': (str, Path, *SUPPORTED_ZARR_STORES),
'doc': 'the path to the Zarr file or a supported Zarr store'},
is_method=False)
def read_nwb(**kwargs):
"""
Helper factory method for reading an NWB file and return the NWBFile object
"""
# Retrieve the filepath
path = popargs('path', kwargs)
if isinstance(path, Path):
path = str(path)
# determine default storage options to use when opening a file from S3
storage_options = {}
if isinstance(path, str) and path.startswith(("s3://")):
storage_options = dict(anon=True)
@docval({'name': 'src_io', 'type': HDMFIO, 'doc': 'the HDMFIO object for reading the data to export'},
{'name': 'nwbfile', 'type': 'NWBFile',
'doc': 'the NWBFile object to export. If None, then the entire contents of src_io will be exported',
'default': None},
{'name': 'write_args', 'type': dict, 'doc': 'arguments to pass to :py:meth:`write_builder`',
'default': dict()})
def export(self, **kwargs):
nwbfile = popargs('nwbfile', kwargs)
kwargs['container'] = nwbfile
super().export(**kwargs)

# open the file with NWBZarrIO and rad the file
io = NWBZarrIO(path=path, mode="r", load_namespaces=True, storage_options=storage_options)
nwbfile = io.read()
@staticmethod
@docval({'name': 'path',
'type': (str, Path, *SUPPORTED_ZARR_STORES),
'doc': 'the path to the Zarr file or a supported Zarr store'},
is_method=False)
def read_nwb(**kwargs):
"""
Helper factory method for reading an NWB file and return the NWBFile object
"""
# Retrieve the filepath
path = popargs('path', kwargs)
if isinstance(path, Path):
path = str(path)
# determine default storage options to use when opening a file from S3
storage_options = {}
if isinstance(path, str) and path.startswith(("s3://")):
storage_options = dict(anon=True)

# return the NWBFile object
return nwbfile
# open the file with NWBZarrIO and rad the file
io = NWBZarrIO(path=path, mode="r", load_namespaces=True, storage_options=storage_options)
nwbfile = io.read()

except ImportError:
warn("PyNWB is not installed. Support for NWBZarrIO is disabled.")
# return the NWBFile object
return nwbfile
Loading