What would you like to see added to PyNWB?
Nwb files created at different time points may use different versions of an extension (e.g. ndx_optogenetics=0.2.0 and =0.3.0). When analyzing data, it would be great to be able to open multiple files with different extension versions within the same python process.
Is your feature request related to a problem?
__TYPE_MAP will cache the spec for the version imported within python
- If these versions have breaking changes (e.g. renaming or refactoring an nwb object type), opening additional files of an incompatible version wil raise a
ConstructError
What solution would you like?
Below is an example of the issue and strategy that worked for me using pynwb=3.1.3, though I haven't extensively tested it. I understand if this would create fragility that you don't want in the main package, but sharing just in case.
import pickle
from pathlib import Path
from typing import Union
import ndx_optogenetics # import ndx-optogenetics v0.3.0 to register it in the global type map
from hdmf.backends.hdf5 import HDF5IO as _HDF5IO
from hdmf.build import BuildManager
from pynwb import NWBHDF5IO, __resources, get_type_map
PathLike = Union[str, Path]
path = "/stelmo/nwb/raw/Jacob20250619_.nwb" # file with ndx-optogenetics v0.2.0
try:
with NWBHDF5IO(path, "r", load_namespaces=True) as io:
nwbfile = (
io.read()
) # this raises an error due to ndx-optogenetics version conflict
except Exception as e:
print(f"Error reading NWB file with default IO: {e} \n\n\n")
def backcompatible_io(path: PathLike, **kwargs) -> NWBHDF5IO:
"""Create an io object capable of reading files incompatible with environment
Creates an isolated BuildManager that loads namespaces cached inside an NWB file.
These are used to generate an NWBHDF5IO that can read the file.
This avoids conflicts when a namespace (e.g., 'ndx-optogenetics') is already loaded
in the global PyNWB type map with a different version.
Parameters
----------
path
Path to an NWB file.
Returns
-------
io
An NWBHDF5IO object configured to read the file.
"""
# load fresh type map
with open(__resources["cached_typemap_path"], "rb") as f:
tm = pickle.load(f)
tm.copy_mappers(
get_type_map()
) # core mappings; does not force extension versions
print(tm.namespace_catalog.namespaces)
# load namespaces from the file into this type map
_HDF5IO.load_namespaces(
tm,
path,
)
print(tm.namespace_catalog.namespaces)
manager = BuildManager(tm)
return NWBHDF5IO(
str(path), mode="r", manager=manager, load_namespaces=False
)
"""Read an NWB file using the namespaces cached in that file."""
with backcompatible_io(path) as io:
nwbfile = io.read() # this works now
Do you have any interest in helping implement the feature?
Yes.
Code of Conduct
What would you like to see added to PyNWB?
Nwb files created at different time points may use different versions of an extension (e.g.
ndx_optogenetics=0.2.0and=0.3.0). When analyzing data, it would be great to be able to open multiple files with different extension versions within the same python process.Is your feature request related to a problem?
__TYPE_MAPwill cache the spec for the version imported within pythonConstructErrorWhat solution would you like?
Below is an example of the issue and strategy that worked for me using
pynwb=3.1.3, though I haven't extensively tested it. I understand if this would create fragility that you don't want in the main package, but sharing just in case.Do you have any interest in helping implement the feature?
Yes.
Code of Conduct