-
Notifications
You must be signed in to change notification settings - Fork 86
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
[Feature]: Add ElectricalSeries should ensure that ElectrodeTable is added as well #1701
Comments
This is tough to handle in the current way mock interfaces are implemented. device = mock_Device()
group = mock_ElectrodeGroup(device=device)
electrodes_table = mock_ElectrodeTable(group=group)
electrodes = DynamicTableRegion(name="electrodes", data=list(range(5)), table=electrodes_table, description="electrodes")
nwbfile = mock_NWBFile(electrode_groups=[group], electrodes=electrodes_table, devices=[device])
nwbfile.add_acquisition(mock_ElectricalSeries(electrodes=electrodes))
with NWBHDF5IO("testsdfse.nwb", "w") as io:
io.write(nwbfile) In this case, the I agree that it would be useful to create a system that allows for the easy creation of entire mock NWBFiles that can be written. Perhaps the best way forward for that would be to create a class class MockNWBFileFactory():
def __init__(self, nwbfile=None, **kwargs):
self.nwbfile = nwbfile or mock_NWBFile(**kwargs)
def create_Device(**kwargs):
device = mock_Device(**kwargs)
self.nwbfile.devices.append(device)
return device
def create_ElectrodeGroup(device=None, **kwargs):
device = device or self.create_Device()
electrode_group = mock_ElectrodeGroup(device=device, **kwargs)
self.nwbfile.electrode_groups.append(electrode_group)
return electrode_group
def create_ElectrodesTable(electrode_group=None, **kwargs):
electrode_group = electrode_group or self.create_ElectrodeGroup()
electrodes_table = create_ElectrodesTable(group=electrode_group, **kwargs)
self.nwbfile.electrodes = electrodes_table
return electrodes_table
def create_ElectricalSeries(electrodes_table=None, **kwargs):
electrodes_table = electrodes_table or self.create_ElectrodesTable()
electrodes = DynamicTableRegion(
name="electrodes",
data=list(range(5)),
table=electrodes_table,
description="electrodes"
)
electrical_series = mock_ElectricalSeries(electrodes=electrodes, **kwargs)
self.nwbfile.add_acquisition(electrical_series)
return electrical_series Then the following should work nwbfile = MockNWBFileFactory().create_ElectricalSeries().nwbfile
with NWBHDF5IO("testsdfse.nwb", "w") as io:
io.write(nwbfile) This approach would require us to write a |
Another option as @oruebel mentioned is to modify pynwb:
I guess you could modify these lines: Lines 851 to 856 in a6fa917
You could create methods for automatic assignment of linked neurodata types within the neurodata classes themselves. class ElectricalSeries(...):
...
def auto_add_links(self, nwbfile):
nwbfile.electrodes = nwbfile.electrodes or self.electrodes.table and then call this method whenever a neurodata object is added: class NWBFile(...):
...
def add_acquisition(self, **kwargs):
nwbdata = popargs('nwbdata', kwargs)
nwbdata.auto_add_links(self)
self._add_acquisition_internal(nwbdata)
... This approach could work for any time that we can make reasonable assumptions about where linked data should go in the |
I don't mind the current implementation of the I was just using mock classes here as a quicker demonstration, but my main complaint is just that the HDMF stack trace was completely uninformative with respect to a relatively simple problem The simplest solution overall might be what Oliver says
with a small addendum that I don't know if it should automatically add the table simply because I don't know how deep it would go - the I'd be perfectly happy with a simple error (or warning for back-compatibility?) that says There is of course the issue brought up that this is all with respect to an in-memory My request put simply is that I should not be able to add an in-memory |
I agree, this would be a valuable feature. I just want to point out that implementing this is tricky - just adding (or checking) the electrodes table would not fix the issue. You would need to add the electrodes table and the electrode group, and the device. Otherwise, you'd get essentially the same error with a different orphaned neurodata object. It might be possible to do this in a more general way if all you are doing is checking. Maybe something like: class NWBContainer():
def check_linked_objects(nwbfile):
for obj in linked_objects:
if obj.parent is not nwbfile:
warn(f"linked object {obj.name} has not yet been added to the nwbfile") I guess there are 3 possible solutions here (not mutually exclusive):
|
Exactly, but I was then hoping that a similar attempt to call For a really general solution that would even apply to the
|
So after meeting with the team, we decided to address all three:
|
What would you like to see added to PyNWB?
See hdmf-dev/hdmf-zarr#95 (comment)
Leading to an error because the electrodes table has not been added to the file.
Is your feature request related to a problem?
See above
What solution would you like?
Possible solutions:
mock_ElectricalSeries
should requireelectrodes
or create electrodes if not presentnwbfile.add_acquisition(electrical_series)
orElectricalSeries
should ensure that when it an ElectricalSeries is added to the NWBFile that the electrodes are added as wellDo you have any interest in helping implement the feature?
Yes.
Code of Conduct
The text was updated successfully, but these errors were encountered: