fix(io): keep member names and types when reading a compound dataset with no rows - #880
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #880 +/- ##
==========================================
+ Coverage 95.27% 95.31% +0.04%
==========================================
Files 234 234
Lines 8311 8329 +18
==========================================
+ Hits 7918 7939 +21
+ Misses 393 390 -3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ehennestad
marked this pull request as draft
August 27, 2026 07:45
3 tasks
ehennestad
marked this pull request as ready for review
August 27, 2026 15:23
ehennestad
force-pushed
the
fix-empty-compound-dataset-read
branch
from
August 27, 2026 15:23
5d18905 to
391a967
Compare
ehennestad
enabled auto-merge
August 27, 2026 15:25
ehennestad
force-pushed
the
fix-empty-compound-dataset-read
branch
from
August 27, 2026 15:29
391a967 to
3c08ee7
Compare
… dataset A compound dataset holding no rows was read as [], dropping its member names and types along with the evidence that the dataset exists. Re-exporting such a file failed with NWB:RequiredPropertyMissing, because the required `data` property of the neurodata type read as empty. PyNWB writes six such datasets for the HERD of a file that has no external resource references. H5D.read returns a 0x0 struct without fields for a dataset that holds no rows, so io.parseCompound rebuilds the columns from the compound type, giving each member an empty value of the MATLAB type it maps to. The HDF5 reader now stubs a compound dataset regardless of its row count, so reading one yields a DataStub whose dims and dataType carry the structure and whose export copies the dataset unchanged. DataStub/export takes the plain object copy for a row-less compound. The manual read-and-write path exists to work around an HDF5 library bug that corrupts reference values, and a dataset without rows has none. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ehennestad
force-pushed
the
fix-empty-compound-dataset-read
branch
from
August 31, 2026 10:44
eb7a97e to
866bf55
Compare
bendichter
approved these changes
Aug 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Background — #876 fixed the write path for compound datasets that hold no rows, and noted that reading one back still returns an empty array without member names. This is that follow-up.
Problem — A compound dataset that holds no rows is read as
[]. Its member names and types are lost, along with any sign that the dataset exists. A file containing one cannot be exported again: the read leaves the requireddataproperty empty, so export stops with a required-property error naming a property the user never set. PyNWB writes six such datasets for the HERD of any file whose external resources hold no references, so this reaches MatNWB through files it did not write.Solution — Read a compound dataset the same way whether or not it holds rows. It becomes a
DataStubthat carries the member names and types, and exporting it copies the dataset, so the file round-trips unchanged.What changed
types.untyped.DataStubrather than[]. Itsdimsis0and itsdataTypelists every member with the MATLAB type it maps to.load()on that stub returns a scalar struct holding one empty, correctly typed column per member.Implementation notes
H5D.readreturns a 0x0 struct without fields for a dataset that holds no rows, so the member names never reached the point whereio.parseCompoundbuilds its columns. It now rebuilds them from the compound type instead, giving each member an empty value of the MATLAB type it maps to, includingtypes.untyped.ObjectViewfor reference members andlogicalfor boolean enums.io.backend.hdf5.HDF5Readerexempts compound datasets from the rule that collapses a zero-size dataset to[]. A compound dataset is stubbed regardless of its row count, so export copies it and its HDF5 member types are preserved exactly rather than rederived from MATLAB classes.types.untyped.DataStub/exporttakes the plain object copy for a compound dataset with no rows. The manual read-and-write path exists to work around an HDF5 library bug that corrupts reference values, and a dataset without rows holds none.Examples
The file below is what PyNWB writes for a session whose external resources were requested but never populated. Its six HERD datasets are compound datasets with no rows.
Member names and types of a compound dataset that holds no rows
Before
After
Exporting a file that holds them
Before
After
How to test
Write the file with PyNWB using the snippet above, then run:
The new tests cover the round trip and a compound dataset whose members include a boolean and an object reference:
runtests('tests.unit.io.EmptyCompoundTest')Checklist
fix #XXwhereXXis the issue number?🤖 Generated with Claude Code