Skip to content

[Zarr-Support] Add Zarr v2 reader support - #821

Draft
ehennestad wants to merge 10 commits into
mainfrom
zarr-support/4-zarr2-reader
Draft

[Zarr-Support] Add Zarr v2 reader support#821
ehennestad wants to merge 10 commits into
mainfrom
zarr-support/4-zarr2-reader

Conversation

@ehennestad

@ehennestad ehennestad commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

Motivation

This PR adds a Zarr v2 reader implementation for nwbRead.

Depends on: https://github.com/ehennestad/MATLAB-support-for-Zarr-files/tree/phase7-compound-dataset-support

How to test the behavior?

nwbtest('Name', 'tests.unit.io.backend.*')

Checklist

  • Have you ensured the PR description clearly describes the problem and solutions?
  • Have you checked to ensure that there aren't other open or previously closed Pull Requests for the same change?
  • If this PR fixes an issue, is the first line of the PR description fix #XX where XX is the issue number?

🤖 Generated with Codex

@oruebel

oruebel commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Just FYI, there are also ongoing PR's in hdmf-zarr to adopt Zarr V3 https://github.com/hdmf-dev/hdmf-zarr/pulls

@oruebel oruebel closed this Jun 29, 2026
@oruebel oruebel reopened this Jun 29, 2026
@oruebel

oruebel commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Sorry, I only meant to add a comment and not close the PR, my mouse was a few pixels too far too the left

ehennestad and others added 10 commits July 4, 2026 11:07
Remove debugging scaffolding that wrapped io.createParsedType and
reader.readDatasetValue in try/catch blocks which suppressed errors
(returning [] or missing) and only warned. This affected every backend,
not just Zarr, and silently weakened read validation: nwbRead no longer
failed on malformed files.

Restoring error propagation fixes
tests.unit.nwbReadTest/readFileWithInvalidTimeSeriesTimestampsShape.

The warn-on-read-failure behavior is being designed in a separate PR and
is preserved on the debug/read-error-warning branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a pynwb+hdmf-zarr Python script that writes a minimal NWB Zarr v2
store exercising all reader paths (schema version, embedded specs, soft
link, object-reference attribute, object-reference dataset, scalar
string, 2-D float32 array). createZarrTestFile.m invokes it via pyrunfile
to produce the fixture on demand in a temporary folder.

Adds three test utilities:
- getZarrWrapperPath: resolves ZARR_WRAPPER_PATH env var or the default
  external_packages location used by setup.m
- isPythonModuleAvailable: probes a Python module via importlib without
  importing it, returning false on any error
- assumeZarrSupport: combines the three prerequisite checks (wrapper
  path, tensorstore, hdmf_zarr) and skips the calling test if any is
  absent

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces hardcoded developer paths with a TestClassSetup that generates
the Zarr fixture on-the-fly via createZarrTestFile and applies
PathFixture and TemporaryFolderFixture. Tests skip gracefully via
assumeZarrSupport when the wrapper or Python packages are absent.

Assertion values are derived from the constants in generateZarrTestFile.py
(IDENTIFIER, NUM_ELECTRODES, NUM_SAMPLES) so the test and fixture stay
in sync without magic literals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setup.m clones the MathWorks Zarr wrapper (ehennestad fork, pinned to
a55a3f2a) into external_packages/ and installs tensorstore into MATLAB's
configured Python interpreter.

CI changes (run_tests.yml):
- Checks out the Zarr wrapper at the pinned SHA and exports
  ZARR_WRAPPER_PATH so MATLAB tests can locate it without a path search.
- Installs tensorstore and hdmf-zarr on Python 3.10+ rows via a
  best-effort pip step; tests skip gracefully if unavailable.

.gitignore: excludes external_packages/MATLAB-support-for-Zarr-files so
the user-installed wrapper is never accidentally committed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sets

Fixture additions:
- SPIKE_TIMES, NUM_SPIKE_TIMES, ELECTRODE_LOCATION constants
- channel_id integer column on the electrode table (1-D int64 dataset)
- Explicit SPIKE_TIMES split across units (fixture stays deterministic)

New Zarr2ReaderTest cases:
- read1dDatasetReturnsDataStub: verifies scalar dims for /units/spike_times
- readStringArrayDatasetContainsExpectedValues: verifies electrode location
  strings load correctly regardless of whether the reader returns a DataStub
  or a direct cell/string array

New Zarr2LazyArrayTest cases:
- integer1dDatasetHasCorrectMatlabType: verifies int64 dtype mapping through
  getMatlabDataType for the channel_id electrode column
- loadWithInfCountReadsToEnd: exercises the Inf-count branch in readPartialData
  which computes count from dims/start/stride rather than taking it literally
- loadMatStyleIrregularSelectionFallsBackToFullRead: non-uniform step sizes
  disable the partial-read path; result must match full-read-then-index

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updates the pinned MathWorks Zarr wrapper SHA from a55a3f2a to 66373602
(phase7-compound-dataset-support). That commit adds compound dataset read
support to the wrapper's zarrread/ZarrDatatype — required by the
getMatlabDataType compound path in matnwb. The v2 numeric read path is
unchanged (v3 additions are guarded by zarr_format checks).

Fixture: adds a PlaneSegmentation with NUM_ROIS=3, NUM_PIXELS_PER_ROI=4
producing a 12-record pixel_mask compound dataset (x uint32, y uint32,
weight float32) at /processing/ophys/PlaneSegmentation/pixel_mask.

New Zarr2ReaderTest case readCompoundDatasetReturnsTable verifies that
readDatasetValue returns a DataStub, that load() returns 12 records, and
that the result (table or struct array) exposes x, y, and weight fields.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed the channel_id electrode column — pynwb's auto-generated id
column (int64) is a cleaner source for the integer dtype test and
requires no extra fixture machinery. Updated Zarr2LazyArrayTest to
point at electrodes/id and assert 'int64'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ehennestad
ehennestad force-pushed the zarr-support/4-zarr2-reader branch from 68a9742 to 34c5881 Compare July 4, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants