diff --git a/CHANGES.md b/CHANGES.md index a4b68265c..2fd2524ec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,10 @@ ### Other changes +* Multi-level datasets (`.levels`) are now regular Zarr groups. + We now also write a `.zgroup` file into the root of the dataset folder, + so multi-level datasets can now be opened using `xr.open_datatree()`. (#1123) + * Improved the filesystem data stores (`"file"`, `"s3"`, ...): - Added parameter `engine` and its schema. It names an xarray backend to be used instead of the automatically detected one. diff --git a/docs/source/mldatasets.md b/docs/source/mldatasets.md index 39beb0ae6..f28a611ae 100644 --- a/docs/source/mldatasets.md +++ b/docs/source/mldatasets.md @@ -75,6 +75,18 @@ has been made part of the levels format: - 2.zarr/ ``` +Starting with xcube 1.9.1, multi-level datasets are regular Zarr groups (so they +be opened using `xarray.open_datatree()`). + +```text +- test_pyramid.levels/ + - .zgroup + - .zlevels + - 0.zarr/ + - 1.zarr/ + - 2.zarr/ +``` + If present, it is a text file comprising a JSON object with the following properties: @@ -148,7 +160,6 @@ To be discussed * Do not write `0.link` file. Instead, provide in `.zlevels` where to find each level. * No longer use `.zarr` extension for levels. Just use the index as name. -* Make top-level directory a Zarr group (`.zgroup`), so the multi-level - dataset can be opened as a group using the `zarr` package. - +* Now that datasets are Zarr groups it would be more intuitive to use + `.zattrs` instead of `.zlevels`. diff --git a/examples/serve/demo/cube-1-250-250.levels/.zgroup b/examples/serve/demo/cube-1-250-250.levels/.zgroup new file mode 100644 index 000000000..3b7daf227 --- /dev/null +++ b/examples/serve/demo/cube-1-250-250.levels/.zgroup @@ -0,0 +1,3 @@ +{ + "zarr_format": 2 +} \ No newline at end of file diff --git a/xcube/core/mldataset/fs.py b/xcube/core/mldataset/fs.py index 888c98d93..50331fab1 100644 --- a/xcube/core/mldataset/fs.py +++ b/xcube/core/mldataset/fs.py @@ -291,7 +291,10 @@ def write_dataset( else: num_levels_max = min(num_levels, ml_dataset.num_levels) - with fs.open(str(data_path / ".zlevels"), mode="w") as fp: + with fs.open(str(data_path / ".zgroup"), mode="wt") as fp: + json.dump({"zarr_format": 2}, fp, indent=2) + + with fs.open(str(data_path / ".zlevels"), mode="wt") as fp: levels_data: dict[str, Any] = dict( version=LEVELS_FORMAT_VERSION, num_levels=num_levels_max )