[Bug]: get_ancestor checks for neurodata type name not class
What happened?
The method AbstractContainer.get_ancestor:
https://github.com/hdmf-dev/hdmf/blob/12864bb253908e3bd48e6610ee8bca4816f85be7/src/hdmf/container.py#L369
is called by NWBMixin.get_ancestor:
https://github.com/NeurodataWithoutBorders/pynwb/blob/43cfa7b4b31cd2506793faaf8a6297f78bfd47e2/src/pynwb/core.py#L36
which is called by UnitsMap.electrodes_column:
https://github.com/NeurodataWithoutBorders/pynwb/blob/43cfa7b4b31cd2506793faaf8a6297f78bfd47e2/src/pynwb/io/misc.py#L46
and Units.addUnit:
https://github.com/NeurodataWithoutBorders/pynwb/blob/43cfa7b4b31cd2506793faaf8a6297f78bfd47e2/src/pynwb/misc.py#L222
to find the ancestor container that has neurodata type "NWBFile". This is fine when the root class is NWBFile, but in ndx-events and some extensions, NWBFile is extended, e.g., to NdxEventsNWBFile. Then this method fails to find the root NdxEventsNWBFile object.
In the example below, when nwbfile is an instance of NdxEventsNWBFile, nwbfile.units.get_ancestor(data_type='NWBFile') returns None.
We should add a method like get_ancestor_by_class that accepts a class and finds all instances of that class or subclasses of it.
Source issue: https://github.com/rly/ndx-events/issues/22
Note that Container.get_ancestor:
https://github.com/hdmf-dev/hdmf/blob/12864bb253908e3bd48e6610ee8bca4816f85be7/src/hdmf/container.py#L369
is not used by anything else, so we can start deprecating this method and use get_ancestor_by_class instead.
Steps to Reproduce
from datetime import datetime
from pynwb import NWBHDF5IO
from ndx_events import NdxEventsNWBFile
nwbfile = NdxEventsNWBFile(
session_description="session description",
identifier="cool_experiment_001",
session_start_time=datetime.now().astimezone(),
)
electrode_group = nwbfile.create_electrode_group(
name='test_group',
description="test",
location='unknown',
device=nwbfile.create_device(name='test_device'))
nwbfile.add_electrode(
id = 0,
group=electrode_group,
location="brain area"
)
nwbfile.add_unit(spike_times=[0,1],electrodes=[0])
Traceback
Traceback (most recent call last):
File "<python-input-0>", line 24, in <module>
nwbfile.add_unit(spike_times=[0,1],electrodes=[0])
~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/rly/miniconda3/envs/test/lib/python3.13/site-packages/hdmf/utils.py", line 578, in func_call
return func(args[0], **pargs)
File "/Users/rly/miniconda3/envs/test/lib/python3.13/site-packages/pynwb/file.py", line 729, in add_unit
self.units.add_unit(**kwargs)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/Users/rly/miniconda3/envs/test/lib/python3.13/site-packages/hdmf/utils.py", line 578, in func_call
return func(args[0], **pargs)
File "/Users/rly/miniconda3/envs/test/lib/python3.13/site-packages/pynwb/misc.py", line 223, in add_unit
elec_col.table = nwbfile.electrodes
^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'electrodes'
Operating System
macOS
Python Version
3.13
Package Versions
pynwb==3.1.1 hdmf==4.1.0