From 91ee051538cc3a3d531027ef9359a78a41b02d04 Mon Sep 17 00:00:00 2001 From: rly Date: Tue, 25 Jul 2023 10:41:57 -0400 Subject: [PATCH 1/3] Add find_neurodata_type methods --- src/pynwb/__init__.py | 26 ++++++++++++++++++++++++++ src/pynwb/file.py | 15 +++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/pynwb/__init__.py b/src/pynwb/__init__.py index 181079970..e33af9ff6 100644 --- a/src/pynwb/__init__.py +++ b/src/pynwb/__init__.py @@ -349,6 +349,32 @@ def export(self, **kwargs): kwargs['container'] = nwbfile super().export(**kwargs) + @docval({'name': 'neurodata_type', 'type': str, 'doc': 'The neurodata type to search for.'}, + {'name': 'namespace', 'type': str, 'doc': 'The namespace of the neurodata type to search for.'},) + def get_neurodata_type_objs(self, neurodata_type: str, namespace: str): + """Return all PyNWB objects in the file that have a neurodata type from a namespace. + + This works regardless of whether the extension was imported earlier in the python execution. + + All objects that are instances of the class associated with the given neurodata_type in the + given namespace will be returned. This includes objects that are instances of a subclass. + + For example, if an extension defines a new neurodata type OnePhotonSeries that extends + ImageSeries, then `get_neurodata_type_objects_in_file(io, "ImageSeries", "core")` will + include all OnePhotonSeries objects. + + .. code-block:: python + + from pynwb import NWBHDF5IO + with NWBHDF5IO(filepath, mode="r", load_namespaces=True) as io: + obj_list = io.get_neurodata_type_objs("Subject", "core") + + """ + pynwb_cls = self.manager.type_map.get_dt_container_cls(neurodata_type, namespace) + + read_nwbfile = self.read() + return read_nwbfile.find_all_of_class(pynwb_cls) + from . import io as __io # noqa: F401,E402 from .core import NWBContainer, NWBData # noqa: F401,E402 diff --git a/src/pynwb/file.py b/src/pynwb/file.py index b03141b7f..2b8defcac 100644 --- a/src/pynwb/file.py +++ b/src/pynwb/file.py @@ -549,6 +549,21 @@ def objects(self): self.all_children() return self.__obj + @docval({'name': 'pynwb_class', 'type': type, 'doc': 'The PyNWB class to search for instances of.'},) + def find_all_of_class(self, pynwb_class: type): + """Return all PyNWB objects in the file that are instances of the pynwb_class class. + + This includes objects that are instances of a subclass of the class. + + .. code-block:: python + + from pynwb import ImageSeries + obj_list = get_neurodata_type_objects(nwbfile, ImageSeries) + + """ + ret = [obj for obj in self.objects.values() if isinstance(obj, pynwb_class)] + return ret + @property def modules(self): warn("NWBFile.modules has been replaced by NWBFile.processing.", DeprecationWarning) From c5850b658b766541b5ee7742e717a1d12915a008 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Tue, 25 Jul 2023 10:27:04 -0700 Subject: [PATCH 2/3] Update src/pynwb/__init__.py --- src/pynwb/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pynwb/__init__.py b/src/pynwb/__init__.py index e33af9ff6..bd5373f7e 100644 --- a/src/pynwb/__init__.py +++ b/src/pynwb/__init__.py @@ -356,6 +356,9 @@ def get_neurodata_type_objs(self, neurodata_type: str, namespace: str): This works regardless of whether the extension was imported earlier in the python execution. + This method is useful for getting neurodata type objects from cached extensions where you + do not have easy access to a python class to pass to `NWBFile.find_all_of_class`. + All objects that are instances of the class associated with the given neurodata_type in the given namespace will be returned. This includes objects that are instances of a subclass. From bbcdf824096c98a54ef85795a3cee82ec7db12f3 Mon Sep 17 00:00:00 2001 From: rly Date: Tue, 25 Jul 2023 17:20:58 -0400 Subject: [PATCH 3/3] Refactor --- src/pynwb/__init__.py | 29 ----------------------------- src/pynwb/file.py | 21 +++++++++++++++------ 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/src/pynwb/__init__.py b/src/pynwb/__init__.py index bd5373f7e..181079970 100644 --- a/src/pynwb/__init__.py +++ b/src/pynwb/__init__.py @@ -349,35 +349,6 @@ def export(self, **kwargs): kwargs['container'] = nwbfile super().export(**kwargs) - @docval({'name': 'neurodata_type', 'type': str, 'doc': 'The neurodata type to search for.'}, - {'name': 'namespace', 'type': str, 'doc': 'The namespace of the neurodata type to search for.'},) - def get_neurodata_type_objs(self, neurodata_type: str, namespace: str): - """Return all PyNWB objects in the file that have a neurodata type from a namespace. - - This works regardless of whether the extension was imported earlier in the python execution. - - This method is useful for getting neurodata type objects from cached extensions where you - do not have easy access to a python class to pass to `NWBFile.find_all_of_class`. - - All objects that are instances of the class associated with the given neurodata_type in the - given namespace will be returned. This includes objects that are instances of a subclass. - - For example, if an extension defines a new neurodata type OnePhotonSeries that extends - ImageSeries, then `get_neurodata_type_objects_in_file(io, "ImageSeries", "core")` will - include all OnePhotonSeries objects. - - .. code-block:: python - - from pynwb import NWBHDF5IO - with NWBHDF5IO(filepath, mode="r", load_namespaces=True) as io: - obj_list = io.get_neurodata_type_objs("Subject", "core") - - """ - pynwb_cls = self.manager.type_map.get_dt_container_cls(neurodata_type, namespace) - - read_nwbfile = self.read() - return read_nwbfile.find_all_of_class(pynwb_cls) - from . import io as __io # noqa: F401,E402 from .core import NWBContainer, NWBData # noqa: F401,E402 diff --git a/src/pynwb/file.py b/src/pynwb/file.py index 2b8defcac..aa816c940 100644 --- a/src/pynwb/file.py +++ b/src/pynwb/file.py @@ -549,19 +549,28 @@ def objects(self): self.all_children() return self.__obj - @docval({'name': 'pynwb_class', 'type': type, 'doc': 'The PyNWB class to search for instances of.'},) - def find_all_of_class(self, pynwb_class: type): - """Return all PyNWB objects in the file that are instances of the pynwb_class class. + @docval({'name': 'neurodata_types', 'type': (type, str), + 'doc': ('The PyNWB container class to search for instances of, or the string with the name of ' + 'the neurodata_type')},) + def find_all(self, neurodata_type): + """Return all PyNWB objects in the file that are instances of the neurodata_type class. - This includes objects that are instances of a subclass of the class. + This includes objects that are instances of a subclass of the class. A string with the name of the + neurodata_type can also be passed in. .. code-block:: python from pynwb import ImageSeries - obj_list = get_neurodata_type_objects(nwbfile, ImageSeries) + obj_list = find_all(nwbfile, ImageSeries) + obj_list = find_all(nwbfile, "EcephysSpecimen") # EcephysSpecimen is defined in a loaded extension """ - ret = [obj for obj in self.objects.values() if isinstance(obj, pynwb_class)] + if isinstance(neurodata_type, str): + pynwb_cls = self.io.manager.type_map.get_dt_container_cls(neurodata_type) + else: + pynwb_cls = neurodata_type + + ret = [obj for obj in self.objects.values() if isinstance(obj, pynwb_cls)] return ret @property