diff --git a/environment.yml b/environment.yml index 8f651a0f..84ad160f 100644 --- a/environment.yml +++ b/environment.yml @@ -10,13 +10,15 @@ dependencies: - openimageio - nodejs - z5py >= 2.0.10 - - python == 3.7.9 + - python=3.7 - scikit-image - pytest - - zarr >= 2.8.3 + # temporarily need zarr from v3-spec-part6 development branch + # - zarr >= 2.8.3 - pip - pandas - tabulate - pip: - pyn5 - git+https://github.com/grlee77/zarrita.git@codec_update + - git+https://github.com/grlee77/zarr-python.git@v3-store-part6 diff --git a/generate_data/generate_zarr.py b/generate_data/generate_zarr.py index a0e0c4ca..15de4d39 100644 --- a/generate_data/generate_zarr.py +++ b/generate_data/generate_zarr.py @@ -16,19 +16,32 @@ def generate_zarr_format(compressors=['gzip', 'blosc', 'zlib', None]): for nested, StoreClass, store_kwargs in [ + # zarr version 2 flat storage cases (False, zarr.storage.DirectoryStore, {}), (False, zarr.storage.FSStore, {}), + # zarr version 2 nested storage cases (True, zarr.storage.NestedDirectoryStore, {}), (True, zarr.storage.FSStore, {'dimension_separator': '/', 'auto_mkdir': True}), + # zarr version 3 flat storage cases + (False, zarr.storage.DirectoryStoreV3, {'dimension_separator': '.'}), + (False, zarr.storage.FSStoreV3, {'dimension_separator': '.'}), + # zarr version 3 nested storage cases + (True, zarr.storage.DirectoryStoreV3, {}), + (True, zarr.storage.FSStoreV3, {}), ]: nested_str = '_nested' if nested else '_flat' path = f'data/zarr_{StoreClass.__name__}{nested_str}.zr' + zarr_version = StoreClass._store_version + if zarr_version == 3: + path = path.replace('.zr', '.zr3') store = StoreClass(path, **store_kwargs) im = astronaut() - f = zarr.open(store, mode='w') + if zarr_version == 2: + # can't open a group without an explicit `path` on v3 + f = zarr.open(store, mode='w') for compressor in compressors: copts = COMPRESSION_OPTIONS.get(compressor, {}) if compressor is None: @@ -38,8 +51,14 @@ def generate_zarr_format(compressors=['gzip', 'blosc', 'zlib', None]): else: name = compressor compressor_impl = STR_TO_COMPRESSOR[compressor](**copts) if compressor is not None else None - f.create_dataset(name, data=im, chunks=CHUNKS, - compressor=compressor_impl) + if zarr_version == 2: + f.create_dataset(name, data=im, chunks=CHUNKS, + compressor=compressor_impl) + else: + # Note: dimension_separator will be inferred from store + x = zarr.array(im, store=store, path=name, shape=im.shape, + chunks=CHUNKS, compressor=compressor_impl, + overwrite=True) def generate_n5_format(compressors=['gzip', None]): @@ -53,6 +72,8 @@ def generate_n5_format(compressors=['gzip', None]): compressor=compressor_impl) + + if __name__ == '__main__': generate_zarr_format() generate_n5_format() diff --git a/test/test_read_all.py b/test/test_read_all.py index c8e77049..1ab64633 100644 --- a/test/test_read_all.py +++ b/test/test_read_all.py @@ -60,7 +60,7 @@ }, "zarr": { "zarr": ["blosc", "gzip", "raw", "zlib"], - "zarr-v3": [], + "zarr-v3": ["blosc", "gzip", "raw", "zlib"], "N5": ["gzip", "raw"], }, "zarrita": { @@ -107,6 +107,19 @@ def read_with_zarr(fpath, ds_name, nested): store = zarr.storage.FSStore(os.fspath(fpath)) else: store = zarr.storage.DirectoryStore(fpath) + return zarr.open(store)[ds_name][:] + elif str(fpath).endswith('.zr3'): + dimension_separator = '/' if nested else '.' + common_kwargs = dict() + if 'FSStore' in str(fpath): + store = zarr.storage.FSStoreV3( + os.fspath(fpath), mode='r', dimension_separator=dimension_separator + ) + else: + store = zarr.storage.DirectoryStoreV3( + os.fspath(fpath), dimension_separator=dimension_separator + ) + return zarr.open(store, path=ds_name)[:] else: store = os.fspath(fpath) return zarr.open(store)[ds_name][:]