Zarr v2 backward compatibility: read v2 NWB files with zarr-python v3 - #340
Zarr v2 backward compatibility: read v2 NWB files with zarr-python v3#340alejoe91 wants to merge 2 commits into
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## zarr-v3-migration #340 +/- ##
=====================================================
- Coverage 83.73% 80.80% -2.93%
=====================================================
Files 5 5
Lines 1371 1615 +244
Branches 274 325 +51
=====================================================
+ Hits 1148 1305 +157
- Misses 147 213 +66
- Partials 76 97 +21 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@alejoe91 Quick question, to what extend and for how long do we expect that Zarr V2 support will be needed? Also is V2 support required only for read of existing data or do we expect that users also need to continue to create new V2 files? If we expect that support for ZarrV2 is limited in time and for read only, then I'm wondering whether it may be simpler to have a V2 and V3 backend side-by-side vs. maintaining a lot of extra code in the V3 backend. |
|
Hi @oruebel We have tons of V2 data already produced on our end, so having a reader for V2 would be enough. Once we switch to V3, we won't produce V2 data anymore but we still want to read existing ones. If we go for a V2-specific backend (which is probably the best option), I don't see why support should be limited in time. What's the argument for that? Since carry V2 is not going to change anymore, I don't think it would take a lot of effort to keep it and maintain it. |
|
Superseeded by #349 |
Motivation
zarr-python v3 cannot parse certain zarr v2 array metadata:
|Owithpickle,json2,vlen-utf8codecs) raiseValueErrorfill_value: 0raiseTypeError(expects a string)This breaks reading existing zarr v2 NWB files written by previous versions of hdmf-zarr.
Disclaimer
Most of it was generated with agents
TODO:
Solution
Instead of skipping unreadable arrays, we now read them via a raw store fallback — decoding
.zarraymetadata and chunk bytes directly through numcodecs, bypassing zarr v3's metadata parser entirely.Core changes (
src/hdmf_zarr/backend.py)__read_v2_dataset_from_fs()— Reads.zarray+.zattrs+ raw chunk data from any store, decodes via numcodecs, returns aDatasetBuilder__decode_v2_dataset()/__decode_v2_chunk()— Handle decompression + filter application for both object and regular dtypes__read_store_bytes()/__store_key_exists()/__store_list_dir()— Store-agnostic helpers that work with bothLocalStoreandFsspecStore__iter_children()— Unified local/remote iteration via store listing + individual access; falls back to v2 raw reading on failure__open_file()/load_namespaces()— Catch(TypeError, ValueError)from consolidated metadata and fall back touse_consolidated=FalseRemote store support (
src/hdmf_zarr/utils.py)ZarrSpecReader.__read_v2_object_array()— Extended to supportFsspecStorevia asyncstore.get()Backward compatibility test
tests/unit/helpers/generate_v2_nwb_zarr.py— Generates a representative v2 NWB file (electrodes with pickle-encodedgroupcolumn, datetime fields, numerical TimeSeries) usinghdmf-zarr<1.0+zarr<3tests/unit/test_v2_backward_compat.py— 25 tests validating metadata, datetime fields, object-dtype columns, references, and numerical data.github/workflows/test_backward_compat.yml— CI workflow: generates v2 file in a temp venv with old deps, then reads it with current codeOther fixes
tests/unit/test_fsspec_streaming.py— Fixedmode="-r"typo →mode="r-"