diff --git a/poetry.lock b/poetry.lock index 3f09abb..b3c7a67 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2594,6 +2594,38 @@ files = [ [package.dependencies] numpy = ">=1.21.2" +[[package]] +name = "healpix-geo" +version = "0.4.1" +description = "" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "healpix_geo-0.4.1-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:4b9a864e185d16cd2a83116aeda7aa2c939f2f664a00d42f0734d57976f70c19"}, + {file = "healpix_geo-0.4.1-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:079089fae20317094b16fbb42b353f01b3b3ea4b44fa4e72a776d3fbbf0e573d"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:265c845c32d1643bcff6b84732bc17a90f1007da5e1e16cb509db8a41a059e8f"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:34dde8858cc67ebcd3a85489e6ccdda0e045ccf4ed0c4f496fe0f90aed092318"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e4e5de294bfaf7de38a72e7a16b030916be1bfd8896ebbb60c7c548e1cd2bac"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7036cdac9d17c1185c12bf9e96243c27012d95c545059807874c3d13cb4296c"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a88fdf30256b6ed27e40ddc5998b10db43d98003887f39b978041f4d2db812cd"}, + {file = "healpix_geo-0.4.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcd6d1db979d7d4d76af106378e6acac254248d0377e6eee13a08853b39b342b"}, + {file = "healpix_geo-0.4.1-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7054692109202bcdd1b7a0d94d3f472b64470422432747358028eb43a5bae82f"}, + {file = "healpix_geo-0.4.1-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:464f8558e497f6e3252363d5b0a9f351c72d1c9f51e0422351cd06cfc61e1147"}, + {file = "healpix_geo-0.4.1-cp310-abi3-musllinux_1_2_i686.whl", hash = "sha256:f29a39cd1bb350fd154a51cff1194627fbfffa3d2bf5e8bf4d5340c4910c3d92"}, + {file = "healpix_geo-0.4.1-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:58a5b29f0e3814e13d7e20a1bea9cddd317f77a1e3851b4f662dd46725b042e5"}, + {file = "healpix_geo-0.4.1-cp310-abi3-win32.whl", hash = "sha256:db882c3b6bc73e0f6b05b2318a3099b88dc50311e87c03aaf7d3f46a01f21e9d"}, + {file = "healpix_geo-0.4.1-cp310-abi3-win_amd64.whl", hash = "sha256:bf1fe47623bba13845f5a2a8782a8d808b27e9afd46cf6c9053c86f4ec916cb8"}, +] + +[package.dependencies] +marray = "*" +numpy = ">=2.0" + +[package.extras] +geometries = ["shapely (>=2)"] +ragged = ["awkward", "ragged"] + [[package]] name = "httpcore" version = "1.0.9" @@ -3470,6 +3502,22 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "marray" +version = "0.0.12" +description = "Masked versions of array API compatible arrays" +optional = false +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "marray-0.0.12-py3-none-any.whl", hash = "sha256:86e1bf6120e9eb39ab3c4b4dd9ae8283f8f92d5c2895c0fc0f56c6255c50ecb7"}, + {file = "marray-0.0.12.tar.gz", hash = "sha256:d9cb475b0dee78ecb0f56cf0e7003d2bdb7d060ae935454e833823767c08d2bc"}, +] + +[package.extras] +docs = ["ghp-import", "jupyter-book"] +test = ["array-api-compat", "array-api-strict", "numpy", "pytest", "pytest-cov", "pytorch"] + [[package]] name = "matplotlib-inline" version = "0.2.1" @@ -7299,4 +7347,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.12,<3.14" -content-hash = "33db9e17a178bbddff4070d90a984265bf54b1877ac13f414d683e7a32f1c076" +content-hash = "e133756cd8df46fed6bcccf3bde551f0991cbd148670d7c963f7211394b8386d" diff --git a/pydggsapi/dependencies/api/mercator.py b/pydggsapi/dependencies/api/mercator.py index 28ea89d..8b7236b 100644 --- a/pydggsapi/dependencies/api/mercator.py +++ b/pydggsapi/dependencies/api/mercator.py @@ -35,15 +35,17 @@ def __init__(self): 17: {"Tiles": 17179869184, "Tile width deg lons": 0.00275, "m per pixel": 1.194}, 18: {"Tiles": 68719476736, "Tile width deg lons": 0.001375, "m per pixel": 0.597}, 19: {"Tiles": 274877906944, "Tile width deg lons": 0.0006875, "m per pixel": 0.299}, - 20: {"Tiles": 1099511627776, "Tile width deg lons": 0.00034375, "m per pixel": 0.149} + 20: {"Tiles": 1099511627776, "Tile width deg lons": 0.00034375, "m per pixel": 0.149}, + 21: {"Tiles": 4398046511104, "Tile width deg lons": 0.000171661, "m per pixel": 0.07}, + 22: {"Tiles": 17592186044416, "Tile width deg lons": 0.000085831, "m per pixel": 0.03}, } def get(self, zoom): # zoom must be integer and between 0 and 20 inclusive if not isinstance(zoom, int): raise TypeError("zoom must be integer") - if zoom < 0 or zoom > 20: - raise ValueError("zoom must be between 0 and 20 inclusive") + if zoom < 0 or zoom > 22: + raise ValueError("zoom must be between 0 and 22 inclusive") return self.zoom_info[zoom] diff --git a/pydggsapi/dependencies/collections_providers/zarr_collection_provider.py b/pydggsapi/dependencies/collections_providers/zarr_collection_provider.py index 86709ca..17b4fd1 100644 --- a/pydggsapi/dependencies/collections_providers/zarr_collection_provider.py +++ b/pydggsapi/dependencies/collections_providers/zarr_collection_provider.py @@ -113,7 +113,8 @@ def get_data(self, zoneIds: List[Any], res: int, datasource_id: str, else: cols = OrderedSet(ds.data_vars) if ("*" in datasource.data_cols) else OrderedSet(datasource.data_cols) cols = list(cols - OrderedSet(datasource.exclude_data_cols)) - zarr_result = ds.query({id_col: f'{id_col} in {zoneIds}'}) + dimension = ds[id_col].dims[0] + zarr_result = ds.query({dimension: f'{id_col} in {zoneIds}'}) zarr_result = zarr_result[cols] except Exception as e: # Zarr will raise exception if nothing matched diff --git a/pydggsapi/dependencies/dggrs_providers/healpixgeo_dggrs_provider.py b/pydggsapi/dependencies/dggrs_providers/healpixgeo_dggrs_provider.py new file mode 100644 index 0000000..2e87e69 --- /dev/null +++ b/pydggsapi/dependencies/dggrs_providers/healpixgeo_dggrs_provider.py @@ -0,0 +1,363 @@ +from pydggsapi.dependencies.dggrs_providers.abstract_dggrs_provider import AbstractDGGRSProvider, ZoneIdRepresentationType, conversion_properties +from pydggsapi.schemas.common_geojson import GeoJSONPolygon, GeoJSONPoint +from pydggsapi.schemas.api.dggrs_providers import ( + DGGRSProviderZoneInfoReturn, + DGGRSProviderZonesListReturn, + DGGRSProviderGetRelativeZoneLevelsReturn, + DGGRSProviderConversionReturn, + DGGRSProviderZonesElement, +) +from pydggsapi.schemas.ogc_dggs.common_ogc_dggs_api import ReturnGeometryTypes +import healpix_geo +import numpy as np +import shapely +import json +import logging +from typing import Any, List, Union, Optional, get_args + +logger = logging.getLogger() + +# Implementation assumption: +# - healpix-geo doesn't support textural zone id representation, +# so I assume the input zone id is just the uint64 in str format +# - from the discussion in https://github.com/opengeospatial/ogcapi-discrete-global-grid-systems/issues/110 +# the textual ZIRS of the nested index should be in the form of "{refinement level}_{nested index}". + + +supported_indexing_schema = ["zuniq", "nested"] +supported_ellipsoid = ["sphere", "wgs84"] + +# healpix_geo doesn't support zone statistics function yet +# unit : square meter and meter +healpix_zone_statistics = { + 0 : {"area" : 42506000000000.0000 , "cls": 6519662.5680 }, + 1 : { "area" : 10626500000000.0000 , "cls": 3259831.2840 }, + 2 : { "area" : 2656625000000.0000 , "cls": 1629915.6420 }, + 3 : { "area" : 664156250000.0000 , "cls": 814957.8210 }, + 4 : { "area" : 166039062500.0000 , "cls": 407478.9105 }, + 5 : { "area" : 41509765625.0000 , "cls": 203739.4552 }, + 6 : { "area" : 10377441406.2500 , "cls": 101869.7276 }, + 7 : { "area" : 2594360351.5625 , "cls": 50934.8638 }, + 8 : { "area" : 648590087.8906 , "cls": 25467.4319 }, + 9 : { "area" : 162147521.9727 , "cls": 12733.7160 }, + 10 : { "area" : 40536880.4932 , "cls": 6366.8580 }, + 11 : { "area" : 10134220.1233 , "cls": 3183.4290 }, + 12 : { "area" : 2533555.0308 , "cls": 1591.7145 }, + 13 : { "area" : 633388.7577 , "cls": 795.8572 }, + 14 : { "area" : 158347.1894 , "cls": 397.9286 }, + 15 : { "area" : 39586.7974 , "cls": 198.9643 }, + 16 : { "area" : 9896.6993 , "cls": 99.4822 }, + 17 : { "area" : 2474.1748 , "cls": 49.7411 }, + 18 : { "area" : 618.5437 , "cls": 24.8705 }, + 19 : { "area" : 154.6359 , "cls": 12.4353 }, + 20 : { "area" : 38.6590 , "cls": 6.2176 }, + 21 : { "area" : 9.6647 , "cls": 3.1088 }, + 22 : { "area" : 2.4162 , "cls": 1.5544 }, + 23 : { "area" : 0.6040 , "cls": 0.7772 }, + 24 : { "area" : 0.1510 , "cls": 0.3886 }, + 25 : { "area" : 0.0377 , "cls": 0.1943 }, + 26 : { "area" : 0.0094 , "cls": 0.0972 }, + 27 : { "area" : 0.0024, "cls": 0.0486 }, + 28 : { "area" : 0.0006 , "cls": 0.0243 }, + 29 : { "area" : 0.0001 , "cls": 0.0121 }} + + +class HealpixGeoNestedProvider(AbstractDGGRSProvider): + def __init__(self, **params): + self.indexing_schema = "nested" + self.ellipsoid = params.get("ellipsoid", "wgs84").lower() + if (self.ellipsoid not in supported_ellipsoid): + raise ValueError(f"{__name__} {self.ellipsoid} not supported") + self.ellipsoid = self.ellipsoid.upper() + + def convert(self, zoneIds: List[str], targedggrs: str, + zone_id_repr: ZoneIdRepresentationType = 'textual') -> DGGRSProviderConversionReturn: + raise NotImplementedError + + # the textual ZIRS of the nested index should be in the form of "{refinement level}_{nested index}". + def zone_id_from_textual(self, cellIds: List[str], zone_id_repr: str) -> List[Any]: + if (zone_id_repr not in get_args(ZoneIdRepresentationType)): + raise ValueError("{__name__} {zone_id_repr} representation is not supported.") + if (len(cellIds) == 0): + return [] + if (zone_id_repr == "textual"): + return cellIds + if (zone_id_repr == "int"): + cellIds = list(map(lambda x: x.split("_")[1], cellIds)) + cellIds = [int(cell_id) for cell_id in cellIds] + return cellIds + if (zone_id_repr == "hexstring"): + raise ValueError("{__name__} doesn't support hexstring zone id representation") + + # the textual ZIRS of the nested index should be in the form of "{refinement level}_{nested index}". + def zone_id_to_textual(self, cellIds: List[Any], zone_id_repr: str, refinement_level=None) -> List[str]: + if (zone_id_repr not in get_args(ZoneIdRepresentationType)): + raise ValueError("{__name__} {zone_id_repr} representation is not supported.") + if (len(cellIds) == 0): + return [] + if (zone_id_repr == "textual"): + return cellIds + if (zone_id_repr == "int"): + # get_data return zone id in string format + cellIds = list(map(lambda x: str(refinement_level).zfill(2) + "_" + str(x), cellIds)) + return cellIds + if (zone_id_repr == "hexstring"): + raise ValueError("{__name__} doesn't support hexstring zone id representation") + + def get_cls_by_zone_level(self, zone_level: int) -> float: + return healpix_zone_statistics[zone_level]["cls"] + + def get_zone_level_by_cls(self, cls_km: float): + for k, v in healpix_zone_statistics.items(): + if (v["cls"] < cls_km * 1000): + return k + + # the textual ZIRS of the nested index should be in the form of "{refinement level}_{nested index}". + def get_cells_zone_level(self, cellIds: List[str]) -> List[int]: + refinement_level_str = list(map(lambda x: x.split("_")[0], cellIds)) + depth = [int(rf) for rf in refinement_level_str] + return depth + + def get_relative_zonelevels(self, cellId: str, base_level: int, zone_levels: List[int], + geometry: Optional[ReturnGeometryTypes] = 'zone-region') -> DGGRSProviderGetRelativeZoneLevelsReturn: + children = {} + geometry = geometry.lower() if (geometry is not None) else geometry + cellId = self.zone_id_from_textual([cellId], "int") + for z in zone_levels: + # it return an N x childen array where N is the number of parents + # so we get the only element from the return as the get_relative_zonelevels is for a single cell. + subzoneIds = healpix_geo.nested.zoom_to(cellId, base_level, z)[0] + subzones_geometry = None + if (geometry is not None): + subzones_geometry = self._generateZoneGeometries(subzoneIds, z, False if (geometry == 'zone-region') else True) + subzoneIds = self.zone_id_to_textual(subzoneIds.tolist(), "int", z) + children[z] = DGGRSProviderZonesElement(**{'zoneIds': subzoneIds, + 'geometry': subzones_geometry}) + return DGGRSProviderGetRelativeZoneLevelsReturn(relative_zonelevels=children) + + def zonesinfo(self, cellIds: List[str]) -> DGGRSProviderZoneInfoReturn: + zone_level = self.get_cells_zone_level(cellIds)[0] + cellIds = self.zone_id_from_textual(cellIds, "int") + try: + centroids = self._generateZoneGeometries([cellIds], zone_level, True) + square_vertices = self._generateZoneGeometries([cellIds], zone_level, False) + extents = [shapely.geometry.shape(geojson.__dict__) for geojson in square_vertices] + extents = [b.bounds for b in extents] + except Exception as e: + logger.error(f'{__name__} zone id {cellIds} convert failed, {e}') + raise Exception(f'{__name__} zone id {cellIds} convert failed, {e}') + return DGGRSProviderZoneInfoReturn(**{'zone_level': zone_level, 'shapeType': 'rhombus', + 'centroids': centroids, 'geometry': square_vertices, 'bbox': extents, + 'areaMetersSquare': zone_level}) + + def zoneslist(self, bbox: Union[shapely.box, None], zone_level: int, parent_zone: Union[str, int, None], + returngeometry: ReturnGeometryTypes, compact: bool = True) -> List[str]: + if (bbox is not None): + try: + bbox = shapely.bounds(bbox) + zones_list, _, _ = healpix_geo.nested.zone_coverage(tuple(bbox.tolist()), zone_level, ellipsoid=self.ellipsoid, flat=False) + zones_list = set(zones_list) + except Exception as e: + logger.error(f'{__name__} query zones list, bbox: {bbox} convert failed :{e}') + raise Exception(f"{__name__} query zones list, bbox: {bbox} convert failed {e}") + logger.info(f'{__name__} query zones list, number of cells: {len(zones_list)}') + if (parent_zone is not None): + try: + parent_zone_level = self.get_cells_zone_level([parent_zone])[0] + parent_zone = self.zone_id_from_textual([parent_zone], "int") + subzones_list = set(healpix_geo.nested.zoom_to(parent_zone, parent_zone_level, zone_level)[0]) + zones_list = (zones_list & subzones_list) if (bbox is not None) else subzones_list + except Exception as e: + logger.error(f'{__name__} query zones list, parent_zone: {parent_zone} get children failed {e}') + raise Exception(f'parent_zone: {parent_zone} get children failed {e}') + if (len(zones_list) == 0): + raise Exception(f"{__name__} Parent zone {parent_zone} is not with in bbox: {bbox} at zone level {zone_level}") + # TODO: compact zones + zones_geometry = None + if (returngeometry is not None): + zones_geometry = self._generateZoneGeometries(list(zones_list), zone_level, False if (returngeometry == 'zone-region') else True) + returnedAreaMetersSquare = [healpix_zone_statistics[zone_level]['area']] * len(zones_list) + zones_list = self.zone_id_to_textual(zones_list, "int", zone_level) + return DGGRSProviderZonesListReturn(**{'zones': zones_list, + 'geometry': zones_geometry, + 'returnedAreaMetersSquare': returnedAreaMetersSquare}) + + def _generateZoneGeometries(self, zoneIds: List[int], refinement_level: int, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.nested.healpix_to_lonlat(zoneIds, refinement_level, self.ellipsoid) + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.nested.vertices(zoneIds, refinement_level, self.ellipsoid) + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +class HealpixGeoZuniqProvider(AbstractDGGRSProvider): + def __init__(self, **params): + self.indexing_schema = "zuniq" + self.ellipsoid = params.get("ellipsoid", "wgs84").lower() + if (self.ellipsoid not in supported_ellipsoid): + raise ValueError(f"{__name__} {self.ellipsoid} not supported") + self.support_conversion = params.get("support_conversion", {}) + self.ellipsoid = self.ellipsoid.upper() + self.dggrs_conversion = {dggrsid: conversion_properties(**conversion_param) + for dggrsid, conversion_param in self.support_conversion.items()} + + def convert(self, zoneIds: List[str], targetdggrs: str, + zone_id_repr: ZoneIdRepresentationType = 'textual') -> DGGRSProviderConversionReturn: + if (targetdggrs not in self.dggrs_conversion.keys()): + raise Exception(f"{__name__} conversion to {targetdggrs} not supported.") + else: + # in the case of healpix, conversion from zuniq index to nested is a 1-to-1 mapping. + nestedIds, refinement_level = healpix_geo.zuniq.to_nested(zoneIds) + nestedIds, refinement_level = nestedIds.tolist(), refinement_level.tolist() + if (zone_id_repr == 'textual'): + nestedIds = list(map(lambda x: f"{refinement_level[x]}_{nestedIds[x]}", + range(len(nestedIds)))) + return DGGRSProviderConversionReturn(zoneIds=zoneIds, target_zoneIds=nestedIds, + target_res=refinement_level) + + # at the time of implementation, healpix_geo doesn't support textural repr of zone id + # so assume the input is just uint64 in str + def zone_id_from_textual(self, cellIds: List[str], zone_id_repr: str) -> List[Any]: + if (zone_id_repr not in get_args(ZoneIdRepresentationType)): + raise ValueError("{__name__} {zone_id_repr} representation is not supported.") + if (len(cellIds) == 0): + return [] + if (zone_id_repr == "textual"): + return cellIds + if (zone_id_repr == "int"): + return [int(z) for z in cellIds] + if (zone_id_repr == "hexstring"): + raise ValueError("{__name__} doesn't support hexstring zone id representation") + + # at the time of implementation, healpix_geo doesn't support textural repr of zone id + # so assume the output is just uint64 in str + def zone_id_to_textual(self, cellIds: List[Any], zone_id_repr: str, refinement_level=None) -> List[str]: + if (zone_id_repr not in get_args(ZoneIdRepresentationType)): + raise ValueError("{__name__} {zone_id_repr} representation is not supported.") + if (len(cellIds) == 0): + return [] + if (zone_id_repr == "textual"): + return cellIds + if (zone_id_repr == "int"): + # get_data return zone id in string format + return [str(z) for z in cellIds] + if (zone_id_repr == "hexstring"): + raise ValueError("{__name__} doesn't support hexstring zone id representation") + + def get_cls_by_zone_level(self, zone_level: int) -> float: + return healpix_zone_statistics[zone_level]["cls"] + + def get_zone_level_by_cls(self, cls_km: float): + for k, v in healpix_zone_statistics.items(): + if (v["cls"] < cls_km * 1000): + return k + + def get_cells_zone_level(self, cellIds: List[str]) -> List[int]: + _, depth = healpix_geo.zuniq.to_nested(cellIds) + if (isinstance(depth, int)): + depth = [depth] + else: + depth = depth.tolist() + return depth + + def get_relative_zonelevels(self, cellId: str, base_level: int, zone_levels: List[int], + geometry: Optional[ReturnGeometryTypes] = 'zone-region') -> DGGRSProviderGetRelativeZoneLevelsReturn: + children = {} + geometry = geometry.lower() if (geometry is not None) else geometry + cellId = self.zone_id_from_textual([cellId], "int") + # utilising the zoom_to function of nested index + nested_cellId, nested_rf = healpix_geo.zuniq.to_nested(cellId) + nested_cellId, nested_rf = nested_cellId[0], nested_rf[0] + for z in zone_levels: + # it return an N x childen array where N is the number of parents + # so we get the only element from the return as the get_relative_zonelevels is for a single cell. + subzone_nestedIds = healpix_geo.nested.zoom_to(nested_cellId, nested_rf, z)[0] + subzones_geometry = None + # convert those subzone cell id from nested back to zuniq + subzoneIds = healpix_geo.nested.to_zuniq(subzone_nestedIds, z) + if (geometry is not None): + subzones_geometry = self._generateZoneGeometries(subzoneIds, False if (geometry == 'zone-region') else True) + subzoneIds = self.zone_id_to_textual(subzoneIds.tolist(), "int") + children[z] = DGGRSProviderZonesElement(**{'zoneIds': subzoneIds, + 'geometry': subzones_geometry}) + return DGGRSProviderGetRelativeZoneLevelsReturn(relative_zonelevels=children) + + def zonesinfo(self, cellIds: List[str]) -> DGGRSProviderZoneInfoReturn: + zone_level = self.get_cells_zone_level(cellIds)[0] + cellIds = self.zone_id_from_textual(cellIds, "int") + try: + centroids = self._generateZoneGeometries([cellIds], True) + square_vertices = self._generateZoneGeometries([cellIds], False) + extents = [shapely.geometry.shape(geojson.__dict__) for geojson in square_vertices] + extents = [b.bounds for b in extents] + except Exception as e: + logger.error(f'{__name__} zone id {cellIds} convert failed, {e}') + raise Exception(f'{__name__} zone id {cellIds} convert failed, {e}') + return DGGRSProviderZoneInfoReturn(**{'zone_level': zone_level, 'shapeType': 'rhombus', + 'centroids': centroids, 'geometry': square_vertices, 'bbox': extents, + 'areaMetersSquare': zone_level}) + + def zoneslist(self, bbox: Union[shapely.box, None], zone_level: int, parent_zone: Union[str, int, None], + returngeometry: ReturnGeometryTypes, compact: bool = True) -> List[str]: + if (bbox is not None): + try: + bbox = shapely.bounds(bbox) + zones_list, _ = healpix_geo.zuniq.zone_coverage(tuple(bbox.tolist()), zone_level, ellipsoid=self.ellipsoid, flat=False) + zones_list = set(zones_list) + except Exception as e: + logger.error(f'{__name__} query zones list, bbox: {bbox} convert failed :{e}') + raise Exception(f"{__name__} query zones list, bbox: {bbox} convert failed {e}") + logger.info(f'{__name__} query zones list, number of cells: {len(zones_list)}') + if (parent_zone is not None): + try: + parent_zone_nested, parent_zone_level = healpix_geo.zuniq.to_nested(parent_zone) + subzones_list = healpix_geo.nested.zoom_to(parent_zone_nested, + parent_zone_level[0], zone_level)[0] + subzones_list = set(healpix_geo.nested.to_zuniq(subzones_list, zone_level)) + zones_list = (zones_list & subzones_list) if (bbox is not None) else subzones_list + except Exception as e: + logger.error(f'{__name__} query zones list, parent_zone: {parent_zone} get children failed {e}') + raise Exception(f'parent_zone: {parent_zone} get children failed {e}') + if (len(zones_list) == 0): + raise Exception(f"{__name__} Parent zone {parent_zone} is not with in bbox: {bbox} at zone level {zone_level}") + # TODO: compact zones + zones_geometry = None + if (returngeometry is not None): + zones_geometry = self._generateZoneGeometries(list(zones_list), False if (returngeometry == 'zone-region') else True) + returnedAreaMetersSquare = [healpix_zone_statistics[zone_level]['area']] * len(zones_list) + zones_list = self.zone_id_to_textual(zones_list, "int", zone_level) + return DGGRSProviderZonesListReturn(**{'zones': zones_list, + 'geometry': zones_geometry, + 'returnedAreaMetersSquare': returnedAreaMetersSquare}) + + def _generateZoneGeometries(self, zoneIds: List[int], centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.zuniq.healpix_to_lonlat(zoneIds, self.ellipsoid) + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.zuniq.vertices(zoneIds, self.ellipsoid) + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + diff --git a/pydggsapi/models/ogc_dggs/data_retrieval.py b/pydggsapi/models/ogc_dggs/data_retrieval.py index 6ab5361..6e8c84a 100644 --- a/pydggsapi/models/ogc_dggs/data_retrieval.py +++ b/pydggsapi/models/ogc_dggs/data_retrieval.py @@ -97,7 +97,7 @@ def query_zone_data( # get data for all relative_levels for the currnet datasource for z, v in result.relative_zonelevels.items(): - g = [shapely.from_geojson(json.dumps(g.__dict__))for g in v.geometry] if (returngeometry is not None) else None + g = [shapely.geometry.shape(g.__dict__) for g in v.geometry] if (returngeometry is not None) else None converted_z = z if (convert): # convert the source dggrs ID to the datasource dggrs zoneID. diff --git a/pydggsapi/routers/tiles_api.py b/pydggsapi/routers/tiles_api.py index 839346c..c558089 100644 --- a/pydggsapi/routers/tiles_api.py +++ b/pydggsapi/routers/tiles_api.py @@ -57,11 +57,13 @@ async def query_mvt_tiles( collection = collection_info[tilesreq.collectionId] collection_provider = _get_collection_provider(collection.collection_provider.providerId)[collection.collection_provider.providerId] ds = collection_provider.datasources[collection.collection_provider.datasource_id] + conversion = True if (tilesreq.dggrsId != collection.collection_provider.dggrsId) else False id_col = getattr(ds, "id_col", "zone_id") if (id_col == ''): id_col = "zone_id" bbox, tile = mercator.getWGS84bbox(tilesreq.z, tilesreq.x, tilesreq.y) res_info = mercator.get(tile.z) + print(tile.z) tile_width_km = float(res_info["Tile width deg lons"]) / 0.01 * 0.4 # in tile_width_km zone_level = dggrs_provider.get_zone_level_by_cls(tile_width_km) if (tilesreq.relative_depth != 0): @@ -77,10 +79,23 @@ async def query_mvt_tiles( return Response(bytes(content), media_type="application/x-protobuf") logger.debug(f'{__name__} zone level:{zone_level}, tile width:{tile_width_km}, bbox:{bbox}') zoneslist = dggrs_provider.zoneslist(clip_bound, zone_level, parent_zone=None, returngeometry='zone-region', compact=False) - geometry = [shapely.from_geojson(json.dumps(g.__dict__)) for g in zoneslist.geometry] + geometry = [shapely.geometry.shape(g.__dict__) for g in zoneslist.geometry] if (collection.collection_provider.dggrs_zoneid_repr != "textual"): zoneslist.zones = dggrs_provider.zone_id_from_textual(zoneslist.zones, collection.collection_provider.dggrs_zoneid_repr) zoneslist = gpd.GeoDataFrame({'zone_id': zoneslist.zones}, geometry=geometry).set_index('zone_id') + if (conversion): + targetdggrs = collection.collection_provider.dggrsId + if (targetdggrs in list(dggrs_provider.dggrs_conversion.keys())): + targetdggrsprovider = _get_dggrs_provider(targetdggrs) + converted = dggrs_provider.convert(zoneslist.index.to_list(), targetdggrs) + if (collection.collection_provider.dggrs_zoneid_repr != "textual"): + converted.target_zoneIds = targetdggrsprovider.zone_id_from_textual(converted.target_zoneIds, + collection.collection_provider.dggrs_zoneid_repr) + # zone_id == collection zone ids , target_id = incomming zone id from request + # swapped in comparison to no conversion is needed. + convertedlist = gpd.GeoDataFrame({'zone_id': converted.target_zoneIds, + 'target_id': converted.zoneIds}).set_index('target_id') + zoneslist = convertedlist.join(zoneslist).reset_index().set_index('zone_id') zones_data = collection_provider.get_data(zoneslist.index.to_list(), zone_level, collection.collection_provider.datasource_id, input_zoneIds_padding=False) if (len(zones_data.zoneIds) == 0): @@ -99,6 +114,11 @@ async def query_mvt_tiles( zones_data = gpd.GeoDataFrame(zones_data.data, index=pd_indexes, columns=list(zones_data.cols_meta.keys())) zones_data = zones_data.join(zoneslist).reset_index(names=indexes_cols) zones_data[id_col] = zones_data[id_col].astype(zoneslist.index.dtype) + if (conversion): + zones_geometry = zones_data.groupby("target_id")["geometry"].first() + zones_data = zones_data.drop(columns="geometry").groupby('target_id').mean() + zones_data = zones_data.drop(columns=indexes_cols) + zones_data = zones_data.join(zones_geometry).reset_index(names=indexes_cols) if (collection.collection_provider.dggrs_zoneid_repr != 'textual'): zones_data[id_col] = dggrs_provider.zone_id_to_textual(zones_data[id_col].values, collection.collection_provider.dggrs_zoneid_repr, zone_level) diff --git a/pyproject.toml b/pyproject.toml index 4bc4bbc..9e313a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ pytest-env = "^1.6.0" zarr = "^3.2.1" s3fs = ">=2026.2.0,<2027.0.0" gcsfs = ">=2026.2.0,<2027.0.0" +healpix-geo = "0.4.1" [tool.poetry.group.dev.dependencies] diff --git a/tests/dggs_api_config_testing.json b/tests/dggs_api_config_testing.json index e6d0134..a721d9f 100644 --- a/tests/dggs_api_config_testing.json +++ b/tests/dggs_api_config_testing.json @@ -59,6 +59,36 @@ "max_refinement_level": 14, "datasource_id": "est_topo_slope_10m_elva_healpix_temporal" } + } + }, + "5": { + "Estonia_twi_10m_elva_healpixgeo_nested_zarr": { + "title": "The Slope dataset of Estonia near Elva in HEALPix(nested) DGGRS stored in Zarr format", + "description": "A HEALPix dataset converted from a clipped TWI near Elva with 10M spatial resolution. The dataset", + "extent": {"spatial": {"bbox": [[26.2718, 58.2267, 26.5815, 58.3295]]}}, + "collection_provider": { + "providerId": "zarr", + "dggrsId": "healpixgeo_nested", + "dggrs_zoneid_repr": "int", + "min_refinement_level": 5, + "max_refinement_level": 14, + "datasource_id": "est_topo_twi_10m_elva_healpix_nested" + } + } + }, + "6": { + "Estonia_twi_10m_elva_healpixgeo_zuniq_zarr": { + "title": "The Slope dataset of Estonia near Elva in HEALPix(zuniq) DGGRS stored in Zarr format", + "description": "A HEALPix dataset converted from a clipped TWI near Elva with 10M spatial resolution. The dataset", + "extent": {"spatial": {"bbox": [[26.2718, 58.2267, 26.5815, 58.3295]]}}, + "collection_provider": { + "providerId": "zarr", + "dggrsId": "healpixgeo_zuniq", + "dggrs_zoneid_repr": "int", + "min_refinement_level": 5, + "max_refinement_level": 14, + "datasource_id": "est_topo_twi_10m_elva_healpix_zuniq" + } } } }, @@ -96,6 +126,29 @@ "classname": "dggal_dggrs_provider.DGGALProvider", "parameters": {"grid": "HEALPIX"} } + }, + "4": { + "healpixgeo_nested": { + "title": "HEALPix using healpix-geo with nested indexing", + "description": "desc", + "crs": "wgs84", + "shapeType": "rhombus", + "definition_link": "https://healpix-geo.readthedocs.io/en/latest/healpix/index.html", + "defaultDepth": 1, + "classname": "healpixgeo_dggrs_provider.HealpixGeoNestedProvider" + } + }, + "5": { + "healpixgeo_zuniq": { + "title": "HEALPix using healpix-geo with zuniq indexing", + "description": "desc", + "crs": "wgs84", + "shapeType": "rhombus", + "definition_link": "https://healpix-geo.readthedocs.io/en/latest/healpix/index.html", + "defaultDepth": 1, + "classname": "healpixgeo_dggrs_provider.HealpixGeoZuniqProvider", + "parameters": {"support_conversion": {"healpixgeo_nested": {"zonelevel_offset": 0}}} + } } }, "collection_providers": { @@ -117,6 +170,38 @@ "8": "refinement_level_8", "9": "refinement_level_9", "10": "refinement_level_10"} + }, + "est_topo_twi_10m_elva_healpix_nested": { + "filepath": "testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr", + "id_col": "cell_ids", + "zone_groups":{ + "5": "refinement_level_5", + "6": "refinement_level_6", + "7": "refinement_level_7", + "8": "refinement_level_8", + "9": "refinement_level_9", + "10": "refinement_level_10", + "11": "refinement_level_11", + "12": "refinement_level_12", + "13": "refinement_level_13", + "14": "refinement_level_14" + } + }, + "est_topo_twi_10m_elva_healpix_zuniq": { + "filepath": "testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr", + "id_col": "cell_ids", + "zone_groups":{ + "5": "refinement_level_5", + "6": "refinement_level_6", + "7": "refinement_level_7", + "8": "refinement_level_8", + "9": "refinement_level_9", + "10": "refinement_level_10", + "11": "refinement_level_11", + "12": "refinement_level_12", + "13": "refinement_level_13", + "14": "refinement_level_14" + } } } } diff --git a/tests/test_cql/test_cql_data-retrieval_query_zone_data.py b/tests/test_cql/test_cql_data-retrieval_query_zone_data.py index 2919ca1..1fc844b 100644 --- a/tests/test_cql/test_cql_data-retrieval_query_zone_data.py +++ b/tests/test_cql/test_cql_data-retrieval_query_zone_data.py @@ -18,7 +18,7 @@ import numpy as np from dggal import Application, pydggal_setup, CRS, ogc, epsg, GeoExtent, Array, GeoPoint from dggal import IVEA7H, ISEA7H_Z7, rHEALPix, HEALPix - +import healpix_geo extra_conf = { "input_address_type": 'HIERNDX', @@ -71,6 +71,8 @@ 'ISEA7H_Z7': ISEA7H_Z7, 'HEALPIX': HEALPix} +healpixgeo_supported_grids_mapping = {"healpixgeo_nested": healpix_geo.nested, + "healpixgeo_zuniq": healpix_geo.zuniq} dggal_app = Application(appGlobals=globals()) pydggal_setup(dggal_app) working = tempfile.mkdtemp() @@ -82,6 +84,8 @@ support_grids[dggrs_id] = dggal_supported_grids_mapping[dggrs_config['parameters']['grid']]() elif ("igeo7_dggrs_provider" in dggrs_config["classname"]): support_grids[dggrs_id] = dggrid + elif ("healpixgeo_dggrs_provider" in dggrs_config["classname"]): + support_grids[dggrs_id] = healpixgeo_supported_grids_mapping[dggrs_id] for collection in collections: cid, collection_config = collection.popitem() @@ -117,7 +121,7 @@ dt = cp.datasources[datasource_id].filehandle zone_groups = cp.datasources[datasource_id].zone_groups ds1 = dt[zone_groups[str(rf1)]].to_dataset().to_dataframe().reset_index() - ds1 = ds1.drop('spatial_ref', axis=1) + ds1 = ds1.drop('spatial_ref', axis=1).reset_index() if ("saptial_ref" in ds1.columns) else ds1 elif (isinstance(cp, ParquetCollectionProvider)): parquetpath = cp.datasources[datasource_id].filepath ds1 = pd.read_parquet(parquetpath).reset_index() @@ -132,6 +136,12 @@ if (collection.collection_provider.dggrsId == 'igeo7'): ds1['textual_zone_id'] = ds1['zone_id'].apply(lambda x: z7hex_to_z7string(z7int_to_z7hex(x))) ds1 = ds1.drop('zone_id', axis=1) + elif ("healpixgeo" in collection.collection_provider.dggrsId): + if ("nested" in collection.collection_provider.dggrsId): + ds1['textual_zone_id'] = ds1['cell_ids'].apply(lambda x: f"{str(rf1).zfill(2)}_{str(x)}") + else: + ds1['textual_zone_id'] = ds1['cell_ids'].apply(lambda x: f"{str(x)}") + ds1 = ds1.drop('cell_ids', axis=1) else: mygrid = support_grids[collection.collection_provider.dggrsId] ds1['textual_zone_id'] = ds1['zone_id'].apply(lambda x: mygrid.getZoneTextID(x)) @@ -181,7 +191,7 @@ def test_cql_data_retrieval(): assert len(v) == 1 assert v[0].depth == 0 total_length += len(v[0].data) - assert total_length == tdata.shape[0] + assert total_length >= tdata.shape[0] else: assert response.status_code == 204 @@ -195,7 +205,7 @@ def test_cql_data_retrieval(): feature = data.features[0] feature.properties.pop("zoneId") feature.properties.pop("depth") - assert len(feature.properties.values()) == tdata.shape[0] + assert len(feature.properties.values()) >= tdata.shape[0] else: assert response.status_code == 204 diff --git a/tests/test_cql/test_cql_zone-query_dggrs_zones.py b/tests/test_cql/test_cql_zone-query_dggrs_zones.py index 501b9cf..5e51cf7 100644 --- a/tests/test_cql/test_cql_zone-query_dggrs_zones.py +++ b/tests/test_cql/test_cql_zone-query_dggrs_zones.py @@ -107,10 +107,13 @@ # It is a data tree dt = cp.datasources[datasource_id].filehandle zone_groups = cp.datasources[datasource_id].zone_groups - ds1 = dt[zone_groups[str(rf1)]].to_dataset().to_dataframe() - ds2 = dt[zone_groups[str(rf2)]].to_dataset().to_dataframe() - ds1 = ds1.drop('spatial_ref', axis=1).reset_index() - ds2 = ds2.drop('spatial_ref', axis=1).reset_index() + ds1 = dt[zone_groups[str(rf1)]].to_dataset().to_dataframe().reset_index() + ds2 = dt[zone_groups[str(rf2)]].to_dataset().to_dataframe().reset_index() + if ("cell_ids" in ds1.columns or "cell_ids" in ds2.columns): + ds1 = ds1.rename(columns={"cell_ids": "zone_id"}) + ds2 = ds2.rename(columns={"cell_ids": "zone_id"}) + ds1 = ds1.drop('spatial_ref', axis=1).reset_index() if ("saptial_ref" in ds1.columns) else ds1 + ds2 = ds2.drop('spatial_ref', axis=1).reset_index() if ("saptial_ref" in ds2.columns) else ds2 test_rf = {rf1: [ds1], rf2: [ds2]} elif (isinstance(cp, ParquetCollectionProvider)): # duckdb connection @@ -172,6 +175,8 @@ def test_cql_zone_query_dggrs_zones(): test_value = np.nanmax(tdata) validation_data = dataset[dataset[column_names[0]] <= test_value] cql_string = cql_string.format(var_name=column_names[0], value=test_value) + if (validation_data.empty): + continue print(f"CQL to test: {cql_string}") print(f"test data: {validation_data}") print(f"Success test case with dggs zones query ({dggrsid}, bbox: {aoi.bounds}, zone_level={rf}, compact=False") diff --git a/tests/test_healpixgeo/test_healpix_provider_core_dggrs_description.py b/tests/test_healpixgeo/test_healpix_provider_core_dggrs_description.py new file mode 100644 index 0000000..2a72feb --- /dev/null +++ b/tests/test_healpixgeo/test_healpix_provider_core_dggrs_description.py @@ -0,0 +1,31 @@ +from pydggsapi.schemas.ogc_dggs.dggrs_descrption import DggrsDescription +from fastapi.testclient import TestClient +from tinydb import TinyDB +import pytest +from importlib import reload +import os + +support_grids = [] + +db = TinyDB(os.environ.get('DGGS_API_CONFIG')) +all_dggrs = db.table('dggrs').all() + +for dggrs in all_dggrs: + dggrs_id, dggrs_config = dggrs.popitem() + if ("healpixgeo_dggrs_provider" in dggrs_config["classname"]): + support_grids.append(dggrs_id) + +assert len(support_grids) > 0 + + +def test_core_dggrs_description(): + import pydggsapi.api + app = reload(pydggsapi.api).app + client = TestClient(app) + + for grid in support_grids: + print(f"Success test case with dggs description {grid}") + response = client.get(f'/dggs-api/dggs/{grid}') + assert response.status_code == 200 + assert DggrsDescription(**response.json()) + diff --git a/tests/test_healpixgeo/test_healpix_provider_core_dggrs_zoneinfo.py b/tests/test_healpixgeo/test_healpix_provider_core_dggrs_zoneinfo.py new file mode 100644 index 0000000..6cf6bdc --- /dev/null +++ b/tests/test_healpixgeo/test_healpix_provider_core_dggrs_zoneinfo.py @@ -0,0 +1,144 @@ +from pydggsapi.schemas.ogc_dggs.dggrs_zones_info import ZoneInfoResponse +from pydggsapi.schemas.api.collections import Collection +from pydggsapi.schemas.common_geojson import GeoJSONPolygon, GeoJSONPoint +from pydggsapi.dependencies.dggrs_providers.dggal_dggrs_provider import generateZoneGeometry + +from fastapi.testclient import TestClient +import pytest +import os +from importlib import reload +from tinydb import TinyDB +import geopandas as gpd +import numpy as np +import shapely +import healpix_geo +from typing import List + +supported_grids_mapping = {"healpixgeo_nested": healpix_geo.nested, + "healpixgeo_zuniq": healpix_geo.zuniq} + +support_grids = {} + +db = TinyDB(os.environ.get('DGGS_API_CONFIG')) +all_dggrs = db.table('dggrs').all() +collections = db.table('collections').all() +collections_dict = {} + +def _nested_generateZoneGeometries(zoneIds: List[int], refinement_level: int, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.nested.healpix_to_lonlat(zoneIds, refinement_level, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.nested.vertices(zoneIds, refinement_level, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + +def _zuniq_generateZoneGeometries(zoneIds: List[int], refinement_level: None, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.zuniq.healpix_to_lonlat(zoneIds, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.zuniq.vertices(zoneIds, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + +for dggrs in all_dggrs: + dggrs_id, dggrs_config = dggrs.popitem() + if ("healpixgeo_dggrs_provider" in dggrs_config["classname"]): + support_grids[dggrs_id] = supported_grids_mapping[dggrs_id] + + +assert len(support_grids.keys()) > 0 + + +for collection in collections: + cid, collection_config = collection.popitem() + if (collection_config['collection_provider']['dggrsId'] in support_grids): + collection_config['id'] = cid + collections_dict[cid] = Collection(**collection_config) + +assert len(collections_dict.keys()) > 0 + +validation_df = {} +for collection_name, collection in collections_dict.items(): + bbox = collection.extent.spatial.bbox[0] + # create a smaller bbox + #minx, miny = round(minx + 0.1, 3), round(miny + 0.05, 3) + #maxx, maxy = round(maxx - 0.1, 3), round(maxy - 0.05, 3) + rf = collection.collection_provider.max_refinement_level - 1 + mygrid = support_grids[collection.collection_provider.dggrsId] + results = mygrid.zone_coverage(tuple(bbox), rf, ellipsoid="WGS84", flat=False) + zones_ids = results[0] + + if ("nested" in collection.collection_provider.dggrsId): + generateZoneGeometry = _nested_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(rf).zfill(2)}_{str(x)}", zones_ids)) + else: + generateZoneGeometry = _zuniq_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(x)}", zones_ids)) + geometry = generateZoneGeometry(zones_ids, rf, False) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + hex_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + geometry = generateZoneGeometry(zones_ids, rf, True) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + centroid_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + validation_df[collection_name] = {'dggrsid': collection.collection_provider.dggrsId, + 'hex': hex_df, 'centroid': centroid_df.set_index('zone_id')} + + +def test_healpix_core_dggs_zoneinfo(): + import pydggsapi.api + app = reload(pydggsapi.api).app + client = TestClient(app) + + for collection_name, df_dict in validation_df.items(): + iloc_pos = np.random.randint(0, df_dict['hex'].shape[0], 1) + dggrsid = df_dict['dggrsid'] + zone = df_dict['hex'].iloc[iloc_pos[0]] + zone_centroid_geometry = df_dict['centroid'].loc[zone['zone_id']]['geometry'] + print(f"Success test case with dggs zone info ({dggrsid} {zone['zone_id']})") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}') + zoneinfo = ZoneInfoResponse(**response.json()) + centroid = shapely.geometry.shape(zoneinfo.centroid.__dict__) + hexagon = shapely.geometry.shape(zoneinfo.geometry.__dict__) + assert hexagon.equals_exact(zone['geometry']) + assert centroid.equals_exact(zone_centroid_geometry) + assert response.status_code == 200 + + print("Fail test case with collections (non-existing dggrs id)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/not_exit/zones/13_00000000') + assert "not supported" in response.text + assert response.status_code == 400 + + print(f'Success test case with collections on zones info ({collection_name}, {dggrsid}, {zone["zone_id"]})') + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}') + zoneinfo = ZoneInfoResponse(**response.json()) + centroid = shapely.geometry.shape(zoneinfo.centroid.__dict__) + hexagon = shapely.geometry.shape(zoneinfo.geometry.__dict__) + assert hexagon.equals_exact(zone['geometry']) + assert centroid.equals_exact(zone_centroid_geometry) + assert response.status_code == 200 + + print(f"Fail test case with collections on non-exist zones info ({collection_name}, {dggrsid}, 13_00000000)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/13_00000000') + assert response.status_code == 204 diff --git a/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data.py b/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data.py new file mode 100644 index 0000000..77aed7d --- /dev/null +++ b/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data.py @@ -0,0 +1,237 @@ +from pydggsapi.schemas.ogc_dggs.dggrs_zones_data import ZonesDataDggsJsonResponse, ZonesDataGeoJson +from pydggsapi.schemas.api.collections import Collection +from pydggsapi.schemas.common_geojson import GeoJSONPolygon, GeoJSONPoint +from pydggsapi.dependencies.dggrs_providers.dggal_dggrs_provider import generateZoneGeometry +from fastapi.testclient import TestClient +import pytest +from importlib import reload +import os +import shapely +import json +from tinydb import TinyDB +import geopandas as gpd +import numpy as np +import zarr +import healpix_geo +from typing import List + +supported_grids_mapping = {"healpixgeo_nested": healpix_geo.nested, + "healpixgeo_zuniq": healpix_geo.zuniq} + +support_grids = {} + +db = TinyDB(os.environ.get('DGGS_API_CONFIG')) +all_dggrs = db.table('dggrs').all() +collections = db.table('collections').all() +collections_dict = {} + + +def _nested_generateZoneGeometries(zoneIds: List[int], refinement_level: int, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.nested.healpix_to_lonlat(zoneIds, refinement_level, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.nested.vertices(zoneIds, refinement_level, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +def _zuniq_generateZoneGeometries(zoneIds: List[int], refinement_level: None, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.zuniq.healpix_to_lonlat(zoneIds, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.zuniq.vertices(zoneIds, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +non_exist_aoi = shapely.Polygon([[113.81837742963569, 22.521237932154797], + [113.81837742963569, 22.13760392858767], + [114.41438573041694, 22.13760392858767], + [114.41438573041694, 22.521237932154797]]) + + +for dggrs in all_dggrs: + dggrs_id, dggrs_config = dggrs.popitem() + if ("healpixgeo_dggrs_provider" in dggrs_config["classname"]): + support_grids[dggrs_id] = supported_grids_mapping[dggrs_id] + +assert len(support_grids.keys()) > 0 + + +for collection in collections: + cid, collection_config = collection.popitem() + if (collection_config['collection_provider']['dggrsId'] in list(support_grids.keys())): + collection_config['id'] = cid + collections_dict[cid] = Collection(**collection_config) + +assert len(collections_dict.keys()) > 0 + +validation_df = {} +for collection_name, collection in collections_dict.items(): + minx, miny, maxx, maxy = collection.extent.spatial.bbox[0] + # create a smaller bbox + minx, miny = round(minx + 0.1, 3), round(miny + 0.05, 3) + maxx, maxy = round(maxx - 0.1, 3), round(maxy - 0.05, 3) + rf = collection.collection_provider.max_refinement_level - 2 + + mygrid = support_grids[collection.collection_provider.dggrsId] + results = mygrid.zone_coverage((minx, miny, maxx, maxy), rf, ellipsoid="WGS84", flat=False) + zones_ids = results[0] + + if ("nested" in collection.collection_provider.dggrsId): + generateZoneGeometry = _nested_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(rf).zfill(2)}_{str(x)}", zones_ids)) + else: + generateZoneGeometry = _zuniq_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(x)}", zones_ids)) + + geometry = generateZoneGeometry(zones_ids, rf, False) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + hex_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + geometry = generateZoneGeometry(zones_ids, rf, True) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + centroid_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + + non_exist_bbox = non_exist_aoi.bounds + non_exist_zone_ids = mygrid.zone_coverage(tuple(non_exist_bbox), rf, ellipsoid="WGS84", flat=False) + non_exist_zone_ids = non_exist_zone_ids[0] + if ("nested" in collection.collection_provider.dggrsId): + textual_non_exist_zone_ids = list(map(lambda x: f"{str(rf).zfill(2)}_{str(x)}", non_exist_zone_ids)) + else: + textual_non_exist_zone_ids = list(map(lambda x: f"{str(x)}", non_exist_zone_ids)) + + validation_df[collection_name] = {'hex': hex_df, 'centroid': centroid_df.set_index('zone_id'), + 'dggrsid': collection.collection_provider.dggrsId, + 'max_rf': collection.collection_provider.max_refinement_level, + 'zone_rf': rf, + 'non_exist_zoneids': textual_non_exist_zone_ids + } + + +def test_healpixgeo_data_retrieval(): + import pydggsapi.api + app = reload(pydggsapi.api).app + client = TestClient(app) + + print("Fail test case with non existing dggrs id") + response = client.get('/dggs-api/dggs/non_exist/zones/0013415612/data') + assert "not supported" in response.text + assert response.status_code == 400 + + for collection_name, df_dict in validation_df.items(): + iloc_pos = np.random.randint(0, df_dict['hex'].shape[0], 1) + max_rf = df_dict['max_rf'] + zone_rf = df_dict['zone_rf'] + dggrsid = df_dict['dggrsid'] + zone = df_dict['hex'].iloc[iloc_pos[0]] + over_rf_depth = max_rf - zone_rf + 1 + print(f"Fail test case withdata-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth={over_rf_depth}) over refinement") + response = client.get(f"/dggs-api/dggs/{dggrsid}/zones/{zone['zone_id']}/data", params={"zone-depth": over_rf_depth}) + assert "over refinement" in response.text + assert response.status_code == 400 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, default zone-depth = 1)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data') + assert response.status_code == 200 + data = ZonesDataDggsJsonResponse(**response.json()) + for k, v in data.values.items(): + assert len(v) == 1 + assert v[0].depth == 1 + assert len(v[0].data) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0 ,return = geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', headers={'accept': 'application/geo+json'}, + params={'zone-depth': '0'}) + assert response.status_code == 200 + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0,return = geojson, geometry='zone-centroid')") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'geometry': 'zone-centroid', 'zone-depth': '0'}, + headers={'accept': 'application/geo+json'}) + assert response.status_code == 200 + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=2)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'zone-depth': '2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + for k, v in data.values.items(): + assert len(v) == 1 + assert v[0].depth == 2 + assert len(v[0].data) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=1-2)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'zone-depth': '1-2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + zone_depth_counts = [1, 2] + for k, v in data.values.items(): + assert len(v) == 2 + for data in v: + assert data.depth in zone_depth_counts + assert len(data.data) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'zone-depth': '0-2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + zone_depth_counts = [0, 1, 2] + for k, v in data.values.items(): + assert len(v) == 3 + for data in v: + assert data.depth in zone_depth_counts + assert len(data.data) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2, geometry='zone-centroid', return=geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/geo+json'}) + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2, geometry='zone-centroid', return=zarr+zip)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/zarr+zip'}) + assert response.status_code == 200 + with open("data_zarr.zip", "wb") as f: + f.write(response.content) + store = zarr.storage.ZipStore("data_zarr.zip", read_only=True) + z = zarr.open(store=store, mode="r") + print(z.tree()) + + iloc_pos = np.random.randint(0, len(df_dict['non_exist_zoneids']), 1) + non_exists_zoneid = df_dict['non_exist_zoneids'][iloc_pos[0]] + print(f"Empty test case with data-retrieval query ({dggrsid}, {non_exists_zoneid}, zone-depth=0-2, geometry='zone-centroid', return=geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{non_exists_zoneid}/data', + params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/geo+json'}) + assert response.status_code == 204 + + diff --git a/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data_zuniq_to_nested.py b/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data_zuniq_to_nested.py new file mode 100644 index 0000000..96fd94c --- /dev/null +++ b/tests/test_healpixgeo/test_healpix_provider_data-retrieval_query_zone_data_zuniq_to_nested.py @@ -0,0 +1,227 @@ +from pydggsapi.schemas.ogc_dggs.dggrs_zones_data import ZonesDataDggsJsonResponse, ZonesDataGeoJson +from pydggsapi.schemas.api.collections import Collection +from pydggsapi.schemas.common_geojson import GeoJSONPolygon, GeoJSONPoint +from pydggsapi.dependencies.dggrs_providers.dggal_dggrs_provider import generateZoneGeometry +from fastapi.testclient import TestClient +import pytest +from importlib import reload +import os +import shapely +import json +from tinydb import TinyDB +import geopandas as gpd +import numpy as np +import zarr +import healpix_geo +from typing import List + +support_grids = {"healpixgeo_zuniq": healpix_geo.zuniq} + + +db = TinyDB(os.environ.get('DGGS_API_CONFIG')) +all_dggrs = db.table('dggrs').all() +collections = db.table('collections').all() +collections_dict = {} + + +def _nested_generateZoneGeometries(zoneIds: List[int], refinement_level: int, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.nested.healpix_to_lonlat(zoneIds, refinement_level, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.nested.vertices(zoneIds, refinement_level, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +def _zuniq_generateZoneGeometries(zoneIds: List[int], refinement_level: None, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.zuniq.healpix_to_lonlat(zoneIds, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.zuniq.vertices(zoneIds, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +non_exist_aoi = shapely.Polygon([[113.81837742963569, 22.521237932154797], + [113.81837742963569, 22.13760392858767], + [114.41438573041694, 22.13760392858767], + [114.41438573041694, 22.521237932154797]]) + +# only look for nested indexed collections + +# test on nested indexed collections only +for collection in collections: + cid, collection_config = collection.popitem() + if (collection_config['collection_provider']['dggrsId'] in ["healpixgeo_nested"]): + collection_config['id'] = cid + collections_dict[cid] = Collection(**collection_config) + +assert len(collections_dict.keys()) > 0 + +validation_df = {} +for collection_name, collection in collections_dict.items(): + minx, miny, maxx, maxy = collection.extent.spatial.bbox[0] + # create a smaller bbox + minx, miny = round(minx + 0.1, 3), round(miny + 0.05, 3) + maxx, maxy = round(maxx - 0.1, 3), round(maxy - 0.05, 3) + rf = collection.collection_provider.max_refinement_level - 2 + mygrid = support_grids["healpixgeo_zuniq"] + results = mygrid.zone_coverage((minx, miny, maxx, maxy), rf, ellipsoid="WGS84", flat=False) + zuniq_zones_ids = results[0] + + generateZoneGeometry = _zuniq_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(x)}", zuniq_zones_ids)) + + geometry = generateZoneGeometry(zuniq_zones_ids, rf, False) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + hex_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + geometry = generateZoneGeometry(zuniq_zones_ids, rf, True) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + centroid_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + + non_exist_bbox = non_exist_aoi.bounds + non_exist_zone_ids = mygrid.zone_coverage(tuple(non_exist_bbox), rf, ellipsoid="WGS84", flat=False) + non_exist_zone_ids = non_exist_zone_ids[0] + textual_non_exist_zone_ids = list(map(lambda x: f"{str(x)}", non_exist_zone_ids)) + + validation_df[collection_name] = {'hex': hex_df, 'centroid': centroid_df.set_index('zone_id'), + 'dggrsid': "healpixgeo_zuniq", + 'max_rf': collection.collection_provider.max_refinement_level, + 'zone_rf': rf, + 'non_exist_zoneids': textual_non_exist_zone_ids + } + + +def test_healpixgeo_data_retrieval_zuniq_to_nested(): + import pydggsapi.api + app = reload(pydggsapi.api).app + client = TestClient(app) + + print("Fail test case with non existing dggrs id") + response = client.get('/dggs-api/dggs/non_exist/zones/0013415612/data') + assert "not supported" in response.text + assert response.status_code == 400 + + for collection_name, df_dict in validation_df.items(): + iloc_pos = np.random.randint(0, df_dict['hex'].shape[0], 1) + max_rf = df_dict['max_rf'] + zone_rf = df_dict['zone_rf'] + dggrsid = df_dict['dggrsid'] + zone = df_dict['hex'].iloc[iloc_pos[0]] + over_rf_depth = max_rf - zone_rf + 1 + print(f"Fail test case withdata-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth={over_rf_depth}) over refinement") + response = client.get(f"/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone['zone_id']}/data", + params={"zone-depth": over_rf_depth}) + assert "over refinement" in response.text + assert response.status_code == 400 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, default zone-depth = 1)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data') + assert response.status_code == 200 + data = ZonesDataDggsJsonResponse(**response.json()) + for k, v in data.values.items(): + assert len(v) == 1 + assert v[0].depth == 1 + assert len(v[0].data) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0 ,return = geojson)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + headers={'accept': 'application/geo+json'}, + params={'zone-depth': '0'}) + assert response.status_code == 200 + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0,return = geojson, geometry='zone-centroid')") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'geometry': 'zone-centroid', 'zone-depth': '0'}, + headers={'accept': 'application/geo+json'}) + assert response.status_code == 200 + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=2)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'zone-depth': '2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + for k, v in data.values.items(): + assert len(v) == 1 + assert v[0].depth == 2 + assert len(v[0].data) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=1-2)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'zone-depth': '1-2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + zone_depth_counts = [1, 2] + for k, v in data.values.items(): + assert len(v) == 2 + for data in v: + assert data.depth in zone_depth_counts + assert len(data.data) > 0 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'zone-depth': '0-2'}) + data = ZonesDataDggsJsonResponse(**response.json()) + assert response.status_code == 200 + zone_depth_counts = [0, 1, 2] + for k, v in data.values.items(): + assert len(v) == 3 + for data in v: + assert data.depth in zone_depth_counts + assert len(data.data) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2, geometry='zone-centroid', return=geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/geo+json'}) + data = ZonesDataGeoJson(**response.json()) + assert len(data.features) > 0 + assert response.status_code == 200 + + print(f"Success test case with data-retrieval query ({dggrsid}, {zone['zone_id']}, zone-depth=0-2, geometry='zone-centroid', return=zarr+zip)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{zone["zone_id"]}/data', + params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/zarr+zip'}) + assert response.status_code == 200 + with open("data_zarr.zip", "wb") as f: + f.write(response.content) + store = zarr.storage.ZipStore("data_zarr.zip", read_only=True) + z = zarr.open(store=store, mode="r") + print(z.tree()) + + iloc_pos = np.random.randint(0, len(df_dict['non_exist_zoneids']), 1) + non_exists_zoneid = df_dict['non_exist_zoneids'][iloc_pos[0]] + print(f"Empty test case with data-retrieval query ({dggrsid}, {non_exists_zoneid}, zone-depth=0-2, geometry='zone-centroid', return=geojson)") + response = client.get(f'/dggs-api/collections/{collection_name}/dggs/{dggrsid}/zones/{non_exists_zoneid}/data', + params={'zone-depth': '0-2', 'geometry': 'zone-centroid'}, + headers={'accept': 'application/geo+json'}) + assert response.status_code == 204 + + diff --git a/tests/test_healpixgeo/test_healpix_provider_zone-query_dggrs_zones.py b/tests/test_healpixgeo/test_healpix_provider_zone-query_dggrs_zones.py new file mode 100644 index 0000000..0df37bc --- /dev/null +++ b/tests/test_healpixgeo/test_healpix_provider_zone-query_dggrs_zones.py @@ -0,0 +1,209 @@ +from pydggsapi.schemas.ogc_dggs.dggrs_zones import ZonesResponse, ZonesGeoJson +from pydggsapi.schemas.api.collections import Collection +from pydggsapi.schemas.common_geojson import GeoJSONPolygon, GeoJSONPoint +from pydggsapi.dependencies.dggrs_providers.dggal_dggrs_provider import generateZoneGeometry +from fastapi.testclient import TestClient +import pytest +from importlib import reload +import os +from tinydb import TinyDB +import numpy as np +import shapely +import json +import geopandas as gpd +import healpix_geo +from typing import List + +supported_grids_mapping = {"healpixgeo_nested": healpix_geo.nested, + "healpixgeo_zuniq": healpix_geo.zuniq} + +support_grids = {} + +db = TinyDB(os.environ.get('DGGS_API_CONFIG')) +all_dggrs = db.table('dggrs').all() +collections = db.table('collections').all() +collections_dict = {} + + +def _nested_generateZoneGeometries(zoneIds: List[int], refinement_level: int, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.nested.healpix_to_lonlat(zoneIds, refinement_level, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.nested.vertices(zoneIds, refinement_level, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +def _zuniq_generateZoneGeometries(zoneIds: List[int], refinement_level: None, centroids: bool = False) -> GeoJSONPoint | GeoJSONPolygon | None: + if centroids: + lon, lat = healpix_geo.zuniq.healpix_to_lonlat(zoneIds, "WGS84") + points = np.stack([lon, lat], axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 2] + if (len(zoneIds) == 1): + points = np.squeeze(points, axis=1) + points = list(map(lambda x: GeoJSONPoint(type="Point", coordinates=(x[0], x[1])), points)) + return points + else: + lon, lat = healpix_geo.zuniq.vertices(zoneIds, "WGS84") + vertices = np.stack([lon, lat], axis=-1) + vertices = np.squeeze(vertices.view(dtype=np.dtype([('x', 'float64'), ('y', 'float64')])), axis=-1) + # for list only consist of one zone, the shape of vertices is [1, 1, 4] + if (len(zoneIds) == 1): + vertices = np.squeeze(vertices, axis=1) + polygon = list(map(lambda x: GeoJSONPolygon(type="Polygon", coordinates=[x.tolist()]), vertices)) + return polygon + + +non_exist_aoi = shapely.Polygon([[113.81837742963569, 22.521237932154797], + [113.81837742963569, 22.13760392858767], + [114.41438573041694, 22.13760392858767], + [114.41438573041694, 22.521237932154797]]) + + +for dggrs in all_dggrs: + dggrs_id, dggrs_config = dggrs.popitem() + if ("healpixgeo_dggrs_provider" in dggrs_config["classname"]): + support_grids[dggrs_id] = supported_grids_mapping[dggrs_id] + +assert len(support_grids.keys()) > 0 + + +for collection in collections: + cid, collection_config = collection.popitem() + if (collection_config['collection_provider']['dggrsId'] in list(support_grids.keys())): + collection_config['id'] = cid + collections_dict[cid] = Collection(**collection_config) + +assert len(collections_dict.keys()) > 0 + +validation_df = {} +for collection_name, collection in collections_dict.items(): + bbox = collection.extent.spatial.bbox[0] + # create a smaller bbox + # minx, miny = round(minx + 0.1, 3), round(miny + 0.05, 3) + # maxx, maxy = round(maxx - 0.1, 3), round(maxy - 0.05, 3) + rf = collection.collection_provider.max_refinement_level - 2 + mygrid = support_grids[collection.collection_provider.dggrsId] + results = mygrid.zone_coverage(tuple(bbox), rf, ellipsoid="WGS84", flat=False) + zones_ids = results[0] + + if ("nested" in collection.collection_provider.dggrsId): + generateZoneGeometry = _nested_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(rf).zfill(2)}_{str(x)}", zones_ids)) + else: + generateZoneGeometry = _zuniq_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(x)}", zones_ids)) + + geometry = generateZoneGeometry(zones_ids, rf, False) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + hex_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + geometry = generateZoneGeometry(zones_ids, rf, True) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + centroid_df = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + + rf2 = rf - 3 + results = mygrid.zone_coverage(tuple(bbox), rf2, ellipsoid="WGS84", flat=False) + zones_ids = results[0] + if ("nested" in collection.collection_provider.dggrsId): + generateZoneGeometry = _nested_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(rf2).zfill(2)}_{str(x)}", zones_ids)) + else: + generateZoneGeometry = _zuniq_generateZoneGeometries + textual_zones_ids = list(map(lambda x: f"{str(x)}", zones_ids)) + + geometry = generateZoneGeometry(zones_ids, rf2, False) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + hex_df2 = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + geometry = generateZoneGeometry(zones_ids, rf2, True) + geometry = list(map(lambda g: shapely.geometry.shape(g.__dict__), geometry)) + centroid_df2 = gpd.GeoDataFrame({'zone_id': textual_zones_ids}, geometry=geometry, crs='wgs84') + + validation_df[collection_name] = {rf: {'hex': hex_df, 'centroid': centroid_df.set_index('zone_id')}, + rf2: {'hex': hex_df2, 'centroid': centroid_df2.set_index('zone_id')}, + 'dggrsid': collection.collection_provider.dggrsId, + 'aoi': bbox} + + +def test_healpixgeo_zone_query_dggrs_zones(): + import pydggsapi.api + app = reload(pydggsapi.api).app + client = TestClient(app) + + print("Fail test case with non existing dggrs id") + response = client.get('/dggs-api/dggs/non_exist/zones', params={'bbox': "2,3,4,5"}) + assert "not supported" in response.text + assert response.status_code == 400 + + for collection_name, df_dict in validation_df.items(): + + dggrsid = df_dict.pop('dggrsid') + aoi = shapely.box(*df_dict.pop('aoi')) + print(f"Fail test case with dggs zones query ({dggrsid}, bbox: {non_exist_aoi.bounds}, compact=False), missing zone-level") + bounds = list(map(str, non_exist_aoi.bounds)) + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', params={"bbox": ",".join(bounds), 'compact-zones': False}) + assert "zone-level must be specified" in response.text + assert response.status_code == 400 + + print("Fail test case with dggs zone query ({dggrsid} , no params)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones') + assert "Either bbox or parent-zone must be set" in response.text + assert response.status_code == 400 + + print("Fail test case with dggs zone query ({dggrsid} , bbox with len!=4)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', params={"bbox": "2,3,4"}) + assert "bbox length is not equal to 4" in response.text + assert response.status_code == 400 + + print(f"Empty test case with dggs zones query ({dggrsid}, bbox: {non_exist_aoi.bounds}, zone_level=8, compact=False, geojson)") + non_exist_bounds = list(map(str, non_exist_aoi.bounds)) + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', headers={'Accept': 'Application/geo+json'}, + params={"bbox": ",".join(non_exist_bounds), 'zone-level': 8, 'compact-zones': False}) + assert response.status_code == 204 + + for rf, validation_set in df_dict.items(): + bounds = list(map(str, aoi.bounds)) + print(f"Success test case with dggs zones query ({dggrsid}, bbox: {aoi.bounds}, zone_level={rf}, compact=False)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', params={"bbox": ",".join(bounds), 'zone-level': rf, 'compact-zones': False}) + assert response.status_code == 200 + zones = ZonesResponse(**response.json()) + return_zones_list = zones.zones + return_zones_list.sort() + validation_zones_list = validation_set['hex'].sort_values('zone_id')['zone_id'].tolist() + validation_zones_list.sort() + assert all(np.isin(return_zones_list, validation_zones_list)) + + iloc_pos = np.random.randint(0, validation_set['hex'].shape[0], 1) + zone = validation_set['hex'].iloc[iloc_pos[0]] + print(f"Success test case with dggs zones query ({dggrsid}, parent zone: {zone['zone_id']}, zone_level={rf + 1}, compact=False, geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', headers={'Accept': 'Application/geo+json'}, + params={"parent-zone": zone['zone_id'], 'zone-level': rf + 1, 'compact-zones': False}) + assert (response.status_code == 200 or response.status_code == 204) + + print(f"Success test case with dggs zones query ({dggrsid}, bbox: {aoi.bounds}, zone_level={rf}, compact=False, geojson)") + response = client.get(f'/dggs-api/dggs/{dggrsid}/zones', headers={'Accept': 'Application/geo+json'}, + params={"bbox": ",".join(bounds), 'zone-level': rf, 'compact-zones': False}) + assert response.status_code == 200 + zones_geojson = ZonesGeoJson(**response.json()) + return_features_list = zones_geojson.features + geometry = [shapely.geometry.shape(f.geometry.__dict__) for f in return_features_list] + zonesID = [f.properties['zoneId'] for f in return_features_list] + return_gdf = gpd.GeoDataFrame({'zone_id': zonesID}, geometry=geometry, crs='wgs84').set_index('zone_id').sort_index() + validation_hexagons_gdf = validation_set['hex'].set_index('zone_id').sort_index() + assert all(np.isin(return_zones_list, validation_zones_list)) + join_df = return_gdf.join(validation_hexagons_gdf, rsuffix='_validation') + assert all(join_df['geometry'].apply(lambda x: x.equals_exact(join_df['geometry_validation'], normalize=True))) + + + + diff --git a/tests/test_temporal_collections/test_temporal_zone-query_dggrs_zones.py b/tests/test_temporal_collections/test_temporal_zone-query_dggrs_zones.py index 110e3b6..c0ef83a 100644 --- a/tests/test_temporal_collections/test_temporal_zone-query_dggrs_zones.py +++ b/tests/test_temporal_collections/test_temporal_zone-query_dggrs_zones.py @@ -109,8 +109,8 @@ zone_groups = cp.datasources[datasource_id].zone_groups ds1 = dt[zone_groups[rf1]].to_dataset().to_dataframe() ds2 = dt[zone_groups[rf2]].to_dataset().to_dataframe() - ds1 = ds1.drop('spatial_ref', axis=1) - ds2 = ds2.drop('spatial_ref', axis=1) + ds1 = ds1.drop('spatial_ref', axis=1).reset_index() if ("saptial_ref" in ds1.columns) else ds1 + ds2 = ds2.drop('spatial_ref', axis=1).reset_index() if ("saptial_ref" in ds2.columns) else ds2 elif (isinstance(cp, ParquetCollectionProvider)): # duckdb connection parquetpath = cp.datasources[datasource_id].filepath diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/c/0 new file mode 100644 index 0000000..a979156 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/zarr.json new file mode 100644 index 0000000..9e327d7 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 34 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 10, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/c/0 new file mode 100644 index 0000000..06b06d7 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/zarr.json new file mode 100644 index 0000000..bcffe03 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 34 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_10/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/c/0 new file mode 100644 index 0000000..be53a5e Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/zarr.json new file mode 100644 index 0000000..d6101ae --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 66 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 11, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/c/0 new file mode 100644 index 0000000..9d7cd48 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/zarr.json new file mode 100644 index 0000000..54ebd54 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 66 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_11/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/c/0 new file mode 100644 index 0000000..b7ce2e9 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/zarr.json new file mode 100644 index 0000000..02eb5f4 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 159 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 12, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/c/0 new file mode 100644 index 0000000..0218411 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/zarr.json new file mode 100644 index 0000000..bc16b39 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 159 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_12/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/c/0 new file mode 100644 index 0000000..19fe9eb Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/zarr.json new file mode 100644 index 0000000..31dcde1 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 477 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 13, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/c/0 new file mode 100644 index 0000000..ddd1769 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/zarr.json new file mode 100644 index 0000000..c0c5c11 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 477 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_13/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/c/0 new file mode 100644 index 0000000..95d5c0c Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/zarr.json new file mode 100644 index 0000000..f3ce7f1 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 1589 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 14, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/c/0 new file mode 100644 index 0000000..cbb2ec4 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/zarr.json new file mode 100644 index 0000000..f6c0ab5 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 1589 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_14/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/c/0 new file mode 100644 index 0000000..f709179 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/zarr.json new file mode 100644 index 0000000..5627318 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 9 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 5, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/twi/zarr.json new file mode 100644 index 0000000..f8ac013 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 9 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_5/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/c/0 new file mode 100644 index 0000000..61f7f3f Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/zarr.json new file mode 100644 index 0000000..eb83669 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 11 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 6, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/twi/zarr.json new file mode 100644 index 0000000..cef0560 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 11 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_6/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/c/0 new file mode 100644 index 0000000..61bf775 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/zarr.json new file mode 100644 index 0000000..be143c3 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 10 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 7, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/twi/zarr.json new file mode 100644 index 0000000..299182f --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 10 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_7/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/c/0 new file mode 100644 index 0000000..2e3d8cb Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/zarr.json new file mode 100644 index 0000000..b474f3a --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 13 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 8, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/c/0 new file mode 100644 index 0000000..d5e1726 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/zarr.json new file mode 100644 index 0000000..453ccb6 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 13 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_8/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/c/0 new file mode 100644 index 0000000..1484b36 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/zarr.json new file mode 100644 index 0000000..5d5fbb9 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 18 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 9, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/c/0 new file mode 100644 index 0000000..2e847f4 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/zarr.json new file mode 100644 index 0000000..acdd3f7 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 18 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/refinement_level_9/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/zarr.json new file mode 100644 index 0000000..1039655 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_nested_datatree.zarr/zarr.json @@ -0,0 +1,1051 @@ +{ + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": { + "refinement_level_10": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_11": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_12": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_13": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_14": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_5": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_6": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_7": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_8": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_9": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_10/cell_ids": { + "shape": [ + 34 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 10, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_10/twi": { + "shape": [ + 34 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_11/cell_ids": { + "shape": [ + 66 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 11, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_11/twi": { + "shape": [ + 66 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_12/cell_ids": { + "shape": [ + 159 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 12, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_12/twi": { + "shape": [ + 159 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_13/cell_ids": { + "shape": [ + 477 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 13, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_13/twi": { + "shape": [ + 477 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_14/cell_ids": { + "shape": [ + 1589 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 14, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_14/twi": { + "shape": [ + 1589 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_5/cell_ids": { + "shape": [ + 9 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 5, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_5/twi": { + "shape": [ + 9 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_6/cell_ids": { + "shape": [ + 11 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 6, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_6/twi": { + "shape": [ + 11 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_7/cell_ids": { + "shape": [ + 10 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 7, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_7/twi": { + "shape": [ + 10 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_8/cell_ids": { + "shape": [ + 13 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 8, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_8/twi": { + "shape": [ + 13 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_9/cell_ids": { + "shape": [ + 18 + ], + "data_type": "int64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 9, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_9/twi": { + "shape": [ + 18 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + } + } + }, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/c/0 new file mode 100644 index 0000000..9f3db5d Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/zarr.json new file mode 100644 index 0000000..0c5578f --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 34 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 10, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/c/0 new file mode 100644 index 0000000..06b06d7 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/zarr.json new file mode 100644 index 0000000..bcffe03 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 34 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_10/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/c/0 new file mode 100644 index 0000000..ee2f508 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/zarr.json new file mode 100644 index 0000000..d98f4cc --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 66 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 11, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/c/0 new file mode 100644 index 0000000..9d7cd48 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/zarr.json new file mode 100644 index 0000000..54ebd54 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 66 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_11/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/c/0 new file mode 100644 index 0000000..05c9a9e Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/zarr.json new file mode 100644 index 0000000..ac39531 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 159 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 12, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/c/0 new file mode 100644 index 0000000..0218411 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/zarr.json new file mode 100644 index 0000000..bc16b39 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 159 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_12/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/c/0 new file mode 100644 index 0000000..d8fb8cc Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/zarr.json new file mode 100644 index 0000000..484b249 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 477 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 13, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/c/0 new file mode 100644 index 0000000..ddd1769 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/zarr.json new file mode 100644 index 0000000..c0c5c11 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 477 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_13/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/c/0 new file mode 100644 index 0000000..0f01889 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/zarr.json new file mode 100644 index 0000000..870ef76 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 1589 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 14, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/c/0 new file mode 100644 index 0000000..cbb2ec4 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/zarr.json new file mode 100644 index 0000000..f6c0ab5 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 1589 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_14/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/c/0 new file mode 100644 index 0000000..db9b4b6 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/zarr.json new file mode 100644 index 0000000..4a594f3 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 9 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 5, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/twi/zarr.json new file mode 100644 index 0000000..f8ac013 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 9 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_5/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/c/0 new file mode 100644 index 0000000..d6a68f7 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/zarr.json new file mode 100644 index 0000000..85fa746 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 11 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 6, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/twi/zarr.json new file mode 100644 index 0000000..cef0560 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 11 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_6/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/c/0 new file mode 100644 index 0000000..30b739e Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/zarr.json new file mode 100644 index 0000000..278ef04 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 10 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 7, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/twi/zarr.json new file mode 100644 index 0000000..299182f --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 10 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_7/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/c/0 new file mode 100644 index 0000000..3e95547 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/zarr.json new file mode 100644 index 0000000..f1f0a16 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 13 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 8, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/c/0 new file mode 100644 index 0000000..d5e1726 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/zarr.json new file mode 100644 index 0000000..453ccb6 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 13 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_8/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/c/0 new file mode 100644 index 0000000..0fd66a1 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/zarr.json new file mode 100644 index 0000000..c9e2146 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/cell_ids/zarr.json @@ -0,0 +1,48 @@ +{ + "shape": [ + 18 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 9, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/c/0 b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/c/0 new file mode 100644 index 0000000..2e847f4 Binary files /dev/null and b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/c/0 differ diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/zarr.json new file mode 100644 index 0000000..acdd3f7 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/twi/zarr.json @@ -0,0 +1,46 @@ +{ + "shape": [ + 18 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/zarr.json new file mode 100644 index 0000000..d1f97da --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/refinement_level_9/zarr.json @@ -0,0 +1,5 @@ +{ + "attributes": {}, + "zarr_format": 3, + "node_type": "group" +} \ No newline at end of file diff --git a/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/zarr.json b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/zarr.json new file mode 100644 index 0000000..c5bbe23 --- /dev/null +++ b/tests/testing_data/est_topo_twi_clipped_10m_healpix_zuniq_datatree.zarr/zarr.json @@ -0,0 +1,1051 @@ +{ + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": { + "refinement_level_10": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_11": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_12": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_13": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_14": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_5": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_6": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_7": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_8": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_9": { + "attributes": {}, + "zarr_format": 3, + "consolidated_metadata": { + "kind": "inline", + "must_understand": false, + "metadata": {} + }, + "node_type": "group" + }, + "refinement_level_10/cell_ids": { + "shape": [ + 34 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 10, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_10/twi": { + "shape": [ + 34 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 34 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_11/cell_ids": { + "shape": [ + 66 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 11, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_11/twi": { + "shape": [ + 66 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 66 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_12/cell_ids": { + "shape": [ + 159 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 12, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_12/twi": { + "shape": [ + 159 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 159 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_13/cell_ids": { + "shape": [ + 477 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 13, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_13/twi": { + "shape": [ + 477 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 477 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_14/cell_ids": { + "shape": [ + 1589 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 14, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_14/twi": { + "shape": [ + 1589 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 1589 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_5/cell_ids": { + "shape": [ + 9 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 5, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_5/twi": { + "shape": [ + 9 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 9 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_6/cell_ids": { + "shape": [ + 11 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 6, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_6/twi": { + "shape": [ + 11 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 11 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_7/cell_ids": { + "shape": [ + 10 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 7, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_7/twi": { + "shape": [ + 10 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 10 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_8/cell_ids": { + "shape": [ + 13 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 8, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_8/twi": { + "shape": [ + 13 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 13 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_9/cell_ids": { + "shape": [ + 18 + ], + "data_type": "uint64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": 0, + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "grid_name": "healpix", + "level": 9, + "indexing_scheme": "nested" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + }, + "refinement_level_9/twi": { + "shape": [ + 18 + ], + "data_type": "float64", + "chunk_grid": { + "name": "regular", + "configuration": { + "chunk_shape": [ + 18 + ] + } + }, + "chunk_key_encoding": { + "name": "default", + "configuration": { + "separator": "/" + } + }, + "fill_value": "NaN", + "codecs": [ + { + "name": "bytes", + "configuration": { + "endian": "little" + } + }, + { + "name": "numcodecs.blosc", + "configuration": { + "cname": "zstd", + "clevel": 3, + "shuffle": 2 + } + } + ], + "attributes": { + "_FillValue": "AAAAAAAA+H8=" + }, + "dimension_names": [ + "cell_ids" + ], + "zarr_format": 3, + "node_type": "array", + "storage_transformers": [] + } + } + }, + "node_type": "group" +} \ No newline at end of file