diff --git a/CHANGES.md b/CHANGES.md index bc9d1603..ea253ff6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +# 7.2.0 (2024-11-05) + +* Ensure compatibility between XarrayReader and other Readers by adding `**kwargs` on class methods (https://github.com/cogeotiff/rio-tiler/pull/762) + +* add `STACReader.get_asset_list()` method to enable easier customization of the asset listing/validation (https://github.com/cogeotiff/rio-tiler/pull/762) + # 7.1.0 (2024-10-29) * Add `preview()` and `statistics()` methods to XarrayReader (https://github.com/cogeotiff/rio-tiler/pull/755) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 80ca1002..d7d90ee2 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -44,6 +44,7 @@ nav: - rio-tiler + STAC: 'examples/Using-rio-tiler-STACReader.ipynb' - Non-Earth dataset: 'examples/Using-nonEarth-dataset.ipynb' - Xarray + rio-tiler: 'examples/Using-rio-tiler-XarrayReader.ipynb' + - STAC + Xarray: 'examples/STAC_datacube_support.ipynb' - Migration Guides: - v1.0 -> v2.0: 'migrations/v2_migration.md' - v2.0 -> v3.0: 'migrations/v3_migration.md' diff --git a/docs/src/examples/STAC_datacube_support.ipynb b/docs/src/examples/STAC_datacube_support.ipynb new file mode 100644 index 00000000..db427932 --- /dev/null +++ b/docs/src/examples/STAC_datacube_support.ipynb @@ -0,0 +1,515 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Add support for STAC Datacube extension" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`rio-tiler` supports GDAL and Xarray Based dataset (DataArray) but supporting both together in a STACReader if tricky because a Xarray based reader might need some `reader_options` provider before openning the dataset. \n", + "\n", + "The goal of this notebook is to show how to create a STAC Reader which support the Datacube extension to avoid maximize the compatibility between all the dataset." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Requirements\n", + "\n", + "To be able to run this notebook you'll need the following requirements:\n", + "- rio-tiler~=7.0\n", + "- xarray\n", + "- rioxarray\n", + "- h5netcdf\n", + "- matplotlib" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1. Simple NetCDF reader" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import List\n", + "\n", + "import attr\n", + "import xarray\n", + "import rioxarray\n", + "from morecantile import TileMatrixSet\n", + "from rio_tiler.io import XarrayReader\n", + "from rio_tiler.constants import WEB_MERCATOR_TMS\n", + "\n", + "\n", + "@attr.s\n", + "class NetCDFReader(XarrayReader):\n", + " \"\"\"Reader: Open NetCDF file and access DataArray.\"\"\"\n", + "\n", + " src_path: str = attr.ib()\n", + " variable: str = attr.ib()\n", + "\n", + " tms: TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS)\n", + "\n", + " ds: xarray.Dataset = attr.ib(init=False)\n", + " input: xarray.DataArray = attr.ib(init=False)\n", + "\n", + " _dims: List = attr.ib(init=False, factory=list)\n", + "\n", + " def __attrs_post_init__(self):\n", + " \"\"\"Set bounds and CRS.\"\"\"\n", + " self.ds = xarray.open_dataset(self.src_path, decode_coords=\"all\")\n", + " da = self.ds[self.variable]\n", + "\n", + " # Make sure we have a valid CRS\n", + " crs = da.rio.crs or \"epsg:4326\"\n", + " da = da.rio.write_crs(crs)\n", + "\n", + " if \"time\" in da.dims:\n", + " da = da.isel(time=0)\n", + "\n", + " self.input = da\n", + "\n", + " super().__attrs_post_init__()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "bounds=(-170.085, -80.08, 169.914999999975, 79.91999999999659) crs='http://www.opengis.net/def/crs/EPSG/0/4326' band_metadata=[('b1', {})] band_descriptions=[('b1', 'value')] dtype='float64' nodata_type='Nodata' colorinterp=None scales=None offsets=None colormap=None name='dataset' count=1 width=2000 height=1000 attrs={'valid_min': 1.0, 'valid_max': 1000.0, 'fill_value': 0}\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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9957T/fdd58yMjJ08803y+PxaPHixaqtrVVubq7cbreWLFkiv9+vkpISSdKcOXNUVFSkBQsWaO3atQoEArr77rtVXV192orKmfQmth5zkpssAgBgiR51Sxpk5cX0w4033mjOPfdck5WVZc477zxz4403mrfffju6/aOPPjLf+c53zLhx48zo0aPN9ddfb9ra2mKe449//KOZO3euGTVqlJkwYYK5/fbbTXd3d3+aYd55553eCVxYWFhYWFhYLFuOHDnSr/P+JzmMsa9k0dnZqXHjxqm1tVUejyfZzUlLvQOkjxw5IrfbnezmpCWOQfJxDJKPY5B8/TkGxhgdO3ZM+fn5cjqdA3o9K+9V1PtmPR4Pv6hJ5na7OQZJxjFIPo5B8nEMku9sj8FgCw4DizsAAABJQHABAADWsDK4uFwu3Xffff26EgnxxTFIPo5B8nEMko9jkHyJPgZWDs4FAADpycqKCwAASE8EFwAAYA2CCwAAsAbBBQAAWIPgAgAArGFlcPnRj36kCy+8UCNHjlRxcbF2796d7CYNC/X19brssss0duxY5eXl6brrrlNLS0vMPidOnFB1dbXGjx+v7OxsVVRUqL29PWaf1tZWlZeXa/To0crLy9Py5cvV09OTyLcybKxZs0YOh0NLly6NruMYDL13331Xf//3f6/x48dr1KhRmj59ul599dXodmOM7r33Xp177rkaNWqUSktL9dZbb8U8x9GjRzV//ny53W7l5ORo8eLFOn78eKLfipXC4bDuueceTZw4UaNGjdLnPvc5PfjggzE35uMYxNeOHTv09a9/Xfn5+XI4HPrlL38Zsz1en/fvfvc7feELX9DIkSNVUFCgtWvX9r+xA77LUZJs2rTJZGVlmX/91381Bw4cMN/+9rdNTk6OaW9vT3bTrFdWVmY2bNhg9u/fb/bt22euvfZaU1hYaI4fPx7d59ZbbzUFBQWmsbHRvPrqq6akpMRcccUV0e09PT1m2rRpprS01Ozdu9f85je/MRMmTDB1dXXJeEtW2717t7nwwgvNjBkzzG233RZdzzEYWkePHjUXXHCB+eY3v2l27dpl/vCHP5hnn3025oaya9asMR6Px/zyl780r7/+uvnbv/1bM3HiRPPRRx9F9/nqV79qLrnkEvPKK6+Y//zP/zQXXXSRufnmm5PxlqyzatUqM378eLN161Zz+PBh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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "with NetCDFReader(\"data/dataset_2d.nc\", variable=\"dataset\") as src:\n", + " print(src.info())\n", + "\n", + " # NOTE: We can use the preview method because we know the data is relatively small\n", + " # but don't use this for large dataset stored on the cloud (because it would download the whole data)\n", + " img = src.preview()\n", + "\n", + "plt.imshow(img.data_as_image())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 2. Custom STAC reader" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Set, Type, Tuple, Dict\n", + "from rio_tiler.types import AssetInfo\n", + "from rio_tiler.io import STACReader, BaseReader\n", + "from rio_tiler.io.stac import STAC_ALTERNATE_KEY\n", + "\n", + "valid_types = {\n", + " \"image/tiff; application=geotiff\",\n", + " \"application/x-netcdf\",\n", + "}\n", + "\n", + "\n", + "@attr.s\n", + "class CustomSTACReader(STACReader):\n", + " include_asset_types: Set[str] = attr.ib(default=valid_types)\n", + "\n", + " def get_asset_list(self) -> List[str]:\n", + " \"\"\"Get valid asset list\"\"\"\n", + " include = self.include_assets\n", + " exclude = self.exclude_assets\n", + " include_asset_types = self.include_asset_types\n", + " exclude_asset_types = self.exclude_asset_types\n", + "\n", + " assets = []\n", + " for asset, asset_info in self.item.get_assets().items():\n", + " _type = asset_info.media_type\n", + "\n", + " if exclude and asset in exclude:\n", + " continue\n", + "\n", + " if (\n", + " _type\n", + " and (exclude_asset_types and _type in exclude_asset_types)\n", + " or (include and asset not in include)\n", + " ):\n", + " continue\n", + "\n", + " if (\n", + " _type\n", + " and (include_asset_types and _type not in include_asset_types)\n", + " or (include and asset not in include)\n", + " ):\n", + " continue\n", + "\n", + " # Here check for the datacube extension\n", + " extras = asset_info.extra_fields\n", + " if variables := extras.get(\"cube:variables\"):\n", + " assets += [f\"{asset}:{v}\" for v in list(variables)]\n", + " else:\n", + " assets.append(asset)\n", + "\n", + " return assets\n", + "\n", + " def _get_reader(self, asset_info: AssetInfo) -> Tuple[Type[BaseReader], Dict]:\n", + " \"\"\"Get Asset Reader.\"\"\"\n", + " asset_type = asset_info.get(\"media_type\", None)\n", + " if asset_type and asset_type in [\n", + " \"application/x-netcdf\",\n", + " ]:\n", + " return NetCDFReader, asset_info.get(\"reader_options\", {})\n", + "\n", + " return Reader, asset_info.get(\"reader_options\", {})\n", + "\n", + " def _get_asset_info(self, asset: str) -> AssetInfo:\n", + " \"\"\"Validate asset names and return asset's info.\n", + "\n", + " Args:\n", + " asset (str): STAC asset name.\n", + "\n", + " Returns:\n", + " AssetInfo: STAC asset info.\n", + "\n", + " \"\"\"\n", + " asset, vrt_options = self._parse_vrt_asset(asset)\n", + " if asset not in self.assets:\n", + " raise InvalidAssetName(\n", + " f\"'{asset}' is not valid, should be one of {self.assets}\"\n", + " )\n", + "\n", + " variable = None\n", + " if \":\" in asset:\n", + " asset, variable = asset.split(\":\")\n", + "\n", + " asset_info = self.item.assets[asset]\n", + " extras = asset_info.extra_fields\n", + "\n", + " info = AssetInfo(\n", + " url=asset_info.get_absolute_href() or asset_info.href,\n", + " metadata=extras if not vrt_options else None,\n", + " )\n", + "\n", + " if STAC_ALTERNATE_KEY and extras.get(\"alternate\"):\n", + " if alternate := extras[\"alternate\"].get(STAC_ALTERNATE_KEY):\n", + " info[\"url\"] = alternate[\"href\"]\n", + "\n", + " if asset_info.media_type:\n", + " info[\"media_type\"] = asset_info.media_type\n", + "\n", + " # https://github.com/stac-extensions/file\n", + " if head := extras.get(\"file:header_size\"):\n", + " info[\"env\"] = {\"GDAL_INGESTED_BYTES_AT_OPEN\": head}\n", + "\n", + " # https://github.com/stac-extensions/raster\n", + " if extras.get(\"raster:bands\") and not vrt_options:\n", + " bands = extras.get(\"raster:bands\")\n", + " stats = [\n", + " (b[\"statistics\"][\"minimum\"], b[\"statistics\"][\"maximum\"])\n", + " for b in bands\n", + " if {\"minimum\", \"maximum\"}.issubset(b.get(\"statistics\", {}))\n", + " ]\n", + " # check that stats data are all double and make warning if not\n", + " if (\n", + " stats\n", + " and all(isinstance(v, (int, float)) for stat in stats for v in stat)\n", + " and len(stats) == len(bands)\n", + " ):\n", + " info[\"dataset_statistics\"] = stats\n", + " else:\n", + " warnings.warn(\n", + " \"Some statistics data in STAC are invalid, they will be ignored.\"\n", + " )\n", + "\n", + " if vrt_options:\n", + " info[\"url\"] = f\"vrt://{info['url']}?{vrt_options}\"\n", + "\n", + " if variable is not None:\n", + " info[\"reader_options\"] = {\"variable\": variable}\n", + "\n", + " return info" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CustomSTACReader(bounds=(-170.085, 79.91999999999659, 169.91499999997504, -80.08), crs=CRS.from_epsg(4326), transform=[0.16999999999998752, 0, -170.085, 0, 0.1599999999999966, -80.08, 0, 0, 1], height=1000, width=2000, input='data/stac_netcdf.json', item=, tms=, reader_options={}, fetch_options={}, ctx=, include_asset_types={'application/x-netcdf', 'image/tiff; application=geotiff'})\n", + "['netcdf:dataset']\n", + "{'url': '/Users/vincentsarago/Dev/CogeoTiff/rio-tiler/docs/src/examples/data/dataset_2d.nc', 'metadata': {'cube:variables': {'dataset': {'dimensions': ['y', 'x'], 'type': 'data'}}}, 'media_type': 'application/x-netcdf', 'reader_options': {'variable': 'dataset'}}\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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9957T/fdd58yMjJ08803y+PxaPHixaqtrVVubq7cbreWLFkiv9+vkpISSdKcOXNUVFSkBQsWaO3atQoEArr77rtVXV192orKmfQmth5zkpssAgBgiR51Sxpk5cX0w4033mjOPfdck5WVZc477zxz4403mrfffju6/aOPPjLf+c53zLhx48zo0aPN9ddfb9ra2mKe449//KOZO3euGTVqlJkwYYK5/fbbTXd3d3+aYd55553eCVxYWFhYWFhYLFuOHDnSr/P+JzmMsa9k0dnZqXHjxqm1tVUejyfZzUlLvQOkjxw5IrfbnezmpCWOQfJxDJKPY5B8/TkGxhgdO3ZM+fn5cjqdA3o9K+9V1PtmPR4Pv6hJ5na7OQZJxjFIPo5B8nEMku9sj8FgCw4DizsAAABJQHABAADWsDK4uFwu3Xffff26EgnxxTFIPo5B8nEMko9jkHyJPgZWDs4FAADpycqKCwAASE8EFwAAYA2CCwAAsAbBBQAAWIPgAgAArGFlcPnRj36kCy+8UCNHjlRxcbF2796d7CYNC/X19brssss0duxY5eXl6brrrlNLS0vMPidOnFB1dbXGjx+v7OxsVVRUqL29PWaf1tZWlZeXa/To0crLy9Py5cvV09OTyLcybKxZs0YOh0NLly6NruMYDL13331Xf//3f6/x48dr1KhRmj59ul599dXodmOM7r33Xp177rkaNWqUSktL9dZbb8U8x9GjRzV//ny53W7l5ORo8eLFOn78eKLfipXC4bDuueceTZw4UaNGjdLnPvc5PfjggzE35uMYxNeOHTv09a9/Xfn5+XI4HPrlL38Zsz1en/fvfvc7feELX9DIkSNVUFCgtWvX9r+xA77LUZJs2rTJZGVlmX/91381Bw4cMN/+9rdNTk6OaW9vT3bTrFdWVmY2bNhg9u/fb/bt22euvfZaU1hYaI4fPx7d59ZbbzUFBQWmsbHRvPrqq6akpMRcccUV0e09PT1m2rRpprS01Ozdu9f85je/MRMmTDB1dXXJeEtW2717t7nwwgvNjBkzzG233RZdzzEYWkePHjUXXHCB+eY3v2l27dpl/vCHP5hnn3025oaya9asMR6Px/zyl780r7/+uvnbv/1bM3HiRPPRRx9F9/nqV79qLrnkEvPKK6+Y//zP/zQXXXSRufnmm5PxlqyzatUqM378eLN161Zz+PBh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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "with CustomSTACReader(\"data/stac_netcdf.json\") as src:\n", + " print(src)\n", + " print(src.assets)\n", + " print(src._get_asset_info(\"netcdf:dataset\"))\n", + " img = src.preview(assets=[\"netcdf:dataset\"])\n", + "\n", + "plt.imshow(img.data_as_image())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 3. Supporting NetCDF without datacube \n", + "\n", + "YOu can also support `NetCDF` files without the datacube extension by customizing the `_get_asset_info` and `_get_reader`. The customization consist by adding a `asset virtual format` (as we do for VRT) in form of `{asset_name}:{variable_name}`" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "from typing import Set, Type, Tuple, Dict\n", + "from rio_tiler.types import AssetInfo\n", + "from rio_tiler.io import STACReader, BaseReader\n", + "from rio_tiler.io.stac import STAC_ALTERNATE_KEY\n", + "\n", + "valid_types = {\n", + " \"image/tiff; application=geotiff\",\n", + " \"application/x-netcdf\",\n", + "}\n", + "\n", + "\n", + "@attr.s\n", + "class CustomSTACReader(STACReader):\n", + " include_asset_types: Set[str] = attr.ib(default=valid_types)\n", + "\n", + " def _get_reader(self, asset_info: AssetInfo) -> Tuple[Type[BaseReader], Dict]:\n", + " \"\"\"Get Asset Reader.\"\"\"\n", + " asset_type = asset_info.get(\"media_type\", None)\n", + " if asset_type and asset_type in [\n", + " \"application/x-netcdf\",\n", + " ]:\n", + " return NetCDFReader, asset_info.get(\"reader_options\", {})\n", + "\n", + " return Reader, asset_info.get(\"reader_options\", {})\n", + "\n", + " def _get_asset_info(self, asset: str) -> AssetInfo:\n", + " \"\"\"Validate asset names and return asset's info.\n", + "\n", + " Args:\n", + " asset (str): STAC asset name.\n", + "\n", + " Returns:\n", + " AssetInfo: STAC asset info.\n", + "\n", + " \"\"\"\n", + " asset, vrt_options = self._parse_vrt_asset(asset)\n", + "\n", + " # See how this is now before the asset validation\n", + " variable = None\n", + " if \":\" in asset:\n", + " asset, variable = asset.split(\":\")\n", + "\n", + " if asset not in self.assets:\n", + " raise InvalidAssetName(\n", + " f\"'{asset}' is not valid, should be one of {self.assets}\"\n", + " )\n", + "\n", + " asset_info = self.item.assets[asset]\n", + " extras = asset_info.extra_fields\n", + "\n", + " info = AssetInfo(\n", + " url=asset_info.get_absolute_href() or asset_info.href,\n", + " metadata=extras if not vrt_options else None,\n", + " )\n", + "\n", + " if STAC_ALTERNATE_KEY and extras.get(\"alternate\"):\n", + " if alternate := extras[\"alternate\"].get(STAC_ALTERNATE_KEY):\n", + " info[\"url\"] = alternate[\"href\"]\n", + "\n", + " if asset_info.media_type:\n", + " info[\"media_type\"] = asset_info.media_type\n", + "\n", + " # https://github.com/stac-extensions/file\n", + " if head := extras.get(\"file:header_size\"):\n", + " info[\"env\"] = {\"GDAL_INGESTED_BYTES_AT_OPEN\": head}\n", + "\n", + " # https://github.com/stac-extensions/raster\n", + " if extras.get(\"raster:bands\") and not vrt_options:\n", + " bands = extras.get(\"raster:bands\")\n", + " stats = [\n", + " (b[\"statistics\"][\"minimum\"], b[\"statistics\"][\"maximum\"])\n", + " for b in bands\n", + " if {\"minimum\", \"maximum\"}.issubset(b.get(\"statistics\", {}))\n", + " ]\n", + " # check that stats data are all double and make warning if not\n", + " if (\n", + " stats\n", + " and all(isinstance(v, (int, float)) for stat in stats for v in stat)\n", + " and len(stats) == len(bands)\n", + " ):\n", + " info[\"dataset_statistics\"] = stats\n", + " else:\n", + " warnings.warn(\n", + " \"Some statistics data in STAC are invalid, they will be ignored.\"\n", + " )\n", + "\n", + " if vrt_options:\n", + " info[\"url\"] = f\"vrt://{info['url']}?{vrt_options}\"\n", + "\n", + " if variable is not None:\n", + " info[\"reader_options\"] = {\"variable\": variable}\n", + "\n", + " return info" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CustomSTACReader(bounds=(-170.085, 79.91999999999659, 169.91499999997504, -80.08), crs=CRS.from_epsg(4326), transform=[0.16999999999998752, 0, -170.085, 0, 0.1599999999999966, -80.08, 0, 0, 1], height=1000, width=2000, input='data/stac_netcdf.json', item=, tms=, reader_options={}, fetch_options={}, ctx=, include_asset_types={'application/x-netcdf', 'image/tiff; application=geotiff'})\n", + "['netcdf']\n", + "{'url': '/Users/vincentsarago/Dev/CogeoTiff/rio-tiler/docs/src/examples/data/dataset_2d.nc', 'metadata': {'cube:variables': {'dataset': {'dimensions': ['y', 'x'], 'type': 'data'}}}, 'media_type': 'application/x-netcdf', 'reader_options': {'variable': 'dataset'}}\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi4AAAEoCAYAAAB/+3pfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy80BEi2AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAmJklEQVR4nO3df3RU9Z3/8ddMSIYfYSYEzIzRRNnKAhFQCpqMWtutKSmm3Spxv+phIaWc+jVNWCFKMdZfaCEsfs+62hZ0PV3sOStlS09pt1i0MSqsEgEjWAFJ1dINq5nELpsMqAzJzOf7B2bqGLAkmczMJ/N8nHOPzL03M5+ZG3Nf8/587uc6jDFGAAAAFnAmuwEAAABni+ACAACsQXABAADWILgAAABrEFwAAIA1CC4AAMAaBBcAAGANggsAALAGwQUAAFiD4AIAAKyR1ODyox/9SBdeeKFGjhyp4uJi7d69O5nNAQAAKS5pweXf//3fVVtbq/vuu0+vvfaaLrnkEpWVlamjoyNZTQIAACnOkaybLBYXF+uyyy7TD3/4Q0lSJBJRQUGBlixZojvvvPMzfzYSiei9997T2LFj5XA4EtFcAAAwSMYYHTt2TPn5+XI6B1Y7GRHnNp2VkydPqrm5WXV1ddF1TqdTpaWlampq6rN/KBRSKBSKPn733XdVVFSUkLYCAID4OnLkiM4///wB/WxSgsuf/vQnhcNheb3emPVer1eHDh3qs399fb1WrlzZZ/07zQUam834YgAAbHDseESfm3VEY8eOHfBzJCW49FddXZ1qa2ujj4PBoAoKCjQmW8oe+HsHAAAJFPn4v4MZ5pGU4DJhwgRlZGSovb09Zn17e7t8Pl+f/V0ul1wuV5/1YWMUTs4QHQAA0E/xOGcnJbhkZWVp1qxZamxs1HXXXSfp1IDbxsZG1dTUnPXzRBSJpjcAAJDa4nHWTlpXUW1trSorKzV79mxdfvnl+ud//md98MEHWrRo0Vk/R1hGYVFxAQDABvE4ZyctuNx44416//33de+99yoQCOjSSy/VM88802fA7mcxxihCVxEAAFaIxwwsSZvHZTCCwaA8Ho/eftOrsWO5qggAABscOxbRRVPb1dXVJbfbPaDnsOKqojPpNkbdA8xdGUxcBwBAQsVjXKrVwWUwuBoJAIDEsvaqongJf7wAAIDUF49zttXBJaL4lJ0AAMDQS/uuorA5tQAAgNQXj3O21cGlRw51Kz6DbDOYDwYAgCEVjzOt1cElbBwKm/gEl3CcAhCGXoaDkAkANorHudbq4BKRQxECR9qJxCmsYug5qWQC+IR4FBusDi5hOaiUACmM/z/tQXc5EiEexQarg0vEOPj2DQBxQPXaHk6Lu8vTvquIigsAIN3Ea2xnMnSn+1VFEYILAADWoKvIOBUx3GQRQGI4HUx5CSSb1cGFriIAiRQ2GcluwrDGAOHhL5LuXUVhORUWFRcAGA6491zqyYjzjXXSfnDuqauKCC4AAAyFSJyLA91m8PHU6uBCVxEAAPZI+4pL2DgVpuICAIAVwmbwg1ysDi5GzriXsQAAwNAwcRiAbXVwoasIAAB70FVEVxEAANZI+66iCF1FAABYI5L2XUVUXAAAsEbaV1wY4wIAgD3SfoxLRNyrCAAAW6R9V9Gpu0MTXAAAsEEkDrcQsDq4hI1DYUNXEQAANojHOdvq4MJVRQAA2CMe52yrgwtXFQEAYI94nLPtDi5yMsYFAABLxOOcbXVwiRiHIoxxAQDACvE4Z1sdXKi4AABgj7SvuBjDPC4AANjCMMaFmXMBALAFM+dScQEAwBrxOGdbHVyouAAAYA8qLsZBxQUAAEsk5aqiHTt26KGHHlJzc7Pa2tq0ZcsWXXfdddHtxhjdd999euKJJ9TZ2akrr7xS69ev16RJk6L7HD16VEuWLNGvf/1rOZ1OVVRU6JFHHlF2dna/2sIEdAAA2CMpE9B98MEHuuSSS/Stb31L8+bN67N97dq1evTRR/WTn/xEEydO1D333KOysjIdPHhQI0eOlCTNnz9fbW1tamhoUHd3txYtWqRbbrlFGzdu7FdbInIoQlcRAABWiMc522GMGfA9ph0OR0zFxRij/Px83X777brjjjskSV1dXfJ6vXryySd100036c0331RRUZH27Nmj2bNnS5KeeeYZXXvttfrv//5v5efn/8XXDQaD8ng8Wr7zWrmyMwfa/GHHGYfbhQMAMFRCx7v1j1dsU1dXl9xu94CeI65jXA4fPqxAIKDS0tLoOo/Ho+LiYjU1Nemmm25SU1OTcnJyoqFFkkpLS+V0OrVr1y5df/31fZ43FAopFApFHweDQUl0FX1aONkNwGfKcAz+du4AYLN4VFziGlwCgYAkyev1xqz3er3RbYFAQHl5ebGNGDFCubm50X0+rb6+XitXruyznin/YZOIyUh2E/AXOB1ULYGhlDY3Wayrq1NtbW30cTAYVEFBAVP+A4irMLml3zJEJRFnL+XuVeTz+SRJ7e3tOvfcc6Pr29vbdemll0b36ejoiPm5np4eHT16NPrzn+ZyueRyufqst6Hiwjc4AMMZXx7RHyl3r6KJEyfK5/OpsbExGlSCwaB27dqlqqoqSZLf71dnZ6eam5s1a9YsSdLzzz+vSCSi4uLifr2eDcEl1ds3VAhsAIBPS0rF5fjx43r77bejjw8fPqx9+/YpNzdXhYWFWrp0qb7//e9r0qRJ0cuh8/Pzo1ceTZ06VV/96lf17W9/W4899pi6u7tVU1Ojm2666ayuKPqkCF1FKYuSuz0o9QNIlKQEl1dffVV/8zd/E33cO/aksrJSTz75pL773e/qgw8+0C233KLOzk5dddVVeuaZZ6JzuEjSU089pZqaGl1zzTXRCegeffTRfjfehooLkOoiYtCwDahiYjiIxKHYMKh5XJKldx6XxS/+H2UxjwsAIEU4mfbgM5083q0nvvjz1JnHJdEiis814QAAxAPTHny2HjP4GcesDi5h41CYriIAAKwQj3O21cElYpzcHRoAAEvE45xteXBhcC4AALZIuQnoEo27QwMAYI+Uu1dRokXEGBcAAGxBcGGMCwAA1mCMC2NcAACwBmNcGOMCAIA16Cqi4gIAgDWouBBcAACwBsGF4AIAgDUILlxVBACANbiqiMG5AABYg8G5dBUBAGCNtO8qMiY+HwIAABh6xgz+OawOLlRcAACwBxUX45AhuAAAYIV4nLOtDi4MzgUAwB4MzqWrCAAAa6R9VxHBBQAAe6R9cGGMCwAA9mCMCxUXAACskfYVF4ILAAD2ILgYh8JDEFycjjjMkAMAAGLE4+xqdXAZqjEuQxGGcGYOgiIApIW0H+OC4YEB1gCQHtI+uETkkIOTHgAAVkj7Cei4HBoAAHukfcUlHHFIkdQNLozdAADgzyLpfnfoVK+4pHLb8GcETABIjLSvuEQMY1wQB/wOWYXpCgB7pX1wMYrPNeEA7MF0BfbgSOHT0n4CulTvKgKAdMYXS3skqsucCegILgAADFqizqWRiHPQz2F5cDm1AACA1BePc/YwCC5UXAAA6C9br6i0PLjQVQQAOMXWE3GyJOP8GY+KS786m+rr63XZZZdp7NixysvL03XXXaeWlpaYfU6cOKHq6mqNHz9e2dnZqqioUHt7e8w+ra2tKi8v1+jRo5WXl6fly5erp6en343v7SpiYWFhYWGJRBwsKbL0FhZOtwxWvyou27dvV3V1tS677DL19PTorrvu0pw5c3Tw4EGNGTNGkrRs2TI9/fTT2rx5szwej2pqajRv3jy9/PLLkqRwOKzy8nL5fD7t3LlTbW1tWrhwoTIzM7V69er+tZ6KCwAAKceYM6yPw2z3DmPO9PR/2fvvv6+8vDxt375dV199tbq6unTOOedo48aNuuGGGyRJhw4d0tSpU9XU1KSSkhJt27ZNX/va1/Tee+/J6/VKkh577DGtWLFC77//vrKysvq8TigUUigUij4OBoMqKCjQxA13yTl65ECbDwAAEijy4QkdXrRaXV1dcrvdA3qOQY1x6erqkiTl5uZKkpqbm9Xd3a3S0tLoPlOmTFFhYWE0uDQ1NWn69OnR0CJJZWVlqqqq0oEDBzRz5sw+r1NfX6+VK1f2bYBxiFlPAQCwRDInoItEIlq6dKmuvPJKTZs2TZIUCASUlZWlnJycmH29Xq8CgUB0n0+Glt7tvdtOp66uTrW1tdHHvRUXBucCAGCPpE75X11drf379+ull14adCP+EpfLJZfL1We9+XgBAACpLx7n7AEFl5qaGm3dulU7duzQ+eefH13v8/l08uRJdXZ2xlRd2tvb5fP5ovvs3r075vl6rzrq3ees0VUEAIA9El1xMcZoyZIl2rJli1588UVNnDgxZvusWbOUmZmpxsZGVVRUSJJaWlrU2toqv98vSfL7/Vq1apU6OjqUl5cnSWpoaJDb7VZRUVG/Gt97CRwAAEh98Thn9yu4VFdXa+PGjfrVr36lsWPHRsekeDwejRo1Sh6PR4sXL1Ztba1yc3Pldru1ZMkS+f1+lZSUSJLmzJmjoqIiLViwQGvXrlUgENDdd9+t6urq03YHfSb6igAAsEeig8v69eslSV/60pdi1m/YsEHf/OY3JUkPP/ywnE6nKioqFAqFVFZWpnXr1kX3zcjI0NatW1VVVSW/368xY8aosrJSDzzwQL8bb8TgXAAAbGGU5HlckiUYDMrj8ajg8XvlHMU8LgAA2CDy0Qkd+b8PJG8el6RjcC4AAPZI5uXQqYDBuQAA2CPhg3NTDhUXAADske4VF64qAgDAIlRcRHABAMAWBBe6igAAsAZdRaLiAgCALai4iOACAIAtCC50FQEAYI04nLOdcWgGAABAQlhecRFdRQAA2IKuIhFcAACwRboHF4dxyMEYFwAArBCPc7bVwYWKCwAAFkn3iosiHy+IL4pYAIChkPbBhcuhhwZVrNTn4CABsFC6BxeH+PuNNEVgtwaHCvgExriI6gCAlMaXK4sQModcPD5igguA4YGTDgaL88nQS/uuIsO3mXRCyR2fib8FQOpL9+BCxSW9EFItQcAEcAbx+DtueXDhqiIg5RAw7cA3ASRDugcXuooAYID40pfyhuUh4qoi8e0OADAsDccv5o44TBpLcAEAAImR9l1FYhwgAAC2YB4XKi4AANgj3SsuBBcAACyS7sGFq4oAALAH87hQcQEAwB4EFxFcAACwBcGFriIAAKxBcGHKfwAArJHuM+cyOBcAAHswOJcxLgAA2CPtg4tEcAEAII1YHVzoKgIAwB7xOGc7+7Pz+vXrNWPGDLndbrndbvn9fm3bti26/cSJE6qurtb48eOVnZ2tiooKtbe3xzxHa2urysvLNXr0aOXl5Wn58uXq6ekZWOsNCwsLCwsLi1XLIPWr4nL++edrzZo1mjRpkowx+slPfqJvfOMb2rt3ry6++GItW7ZMTz/9tDZv3iyPx6OamhrNmzdPL7/8siQpHA6rvLxcPp9PO3fuVFtbmxYuXKjMzEytXr26/62P04cAAAASIA7nbIcxZlBPk5ubq4ceekg33HCDzjnnHG3cuFE33HCDJOnQoUOaOnWqmpqaVFJSom3btulrX/ua3nvvPXm9XknSY489phUrVuj9999XVlbWWb1mMBiUx+PRpDtWK8M1cjDNBwAACRIOndBb/+8udXV1ye12D+g5BjzGJRwOa/Pmzfrggw/k9/vV3Nys7u5ulZaWRveZMmWKCgsLo8GlqalJ06dPj4YWSSorK1NVVZUOHDigmTNnnva1QqGQQqFQ9HEwGDz1DyouAADYIw7n7H6NcZGkN954Q9nZ2XK5XLr11lu1ZcsWFRUVKRAIKCsrSzk5OTH7e71eBQIBSVIgEIgJLb3be7edSX19vTweT3QpKCjob7MBAMAw0O+Ky+TJk7Vv3z51dXXp5z//uSorK7V9+/ahaFtUXV2damtro4+DwaAKCgq4qggAAIskZQK6rKwsXXTRRZKkWbNmac+ePXrkkUd044036uTJk+rs7IypurS3t8vn80mSfD6fdu/eHfN8vVcd9e5zOi6XSy6Xq+8GuooAALBHMoLLp0UiEYVCIc2aNUuZmZlqbGxURUWFJKmlpUWtra3y+/2SJL/fr1WrVqmjo0N5eXmSpIaGBrndbhUVFfX7tam4AABgj4RXXOrq6jR37lwVFhbq2LFj2rhxo1588UU9++yz8ng8Wrx4sWpra5Wbmyu3260lS5bI7/erpKREkjRnzhwVFRVpwYIFWrt2rQKBgO6++25VV1efvqLyl1BxAQDAHokOLh0dHVq4cKHa2trk8Xg0Y8YMPfvss/rKV74iSXr44YfldDpVUVGhUCiksrIyrVu3LvrzGRkZ2rp1q6qqquT3+zVmzBhVVlbqgQceGFjrCS4AANgjFeZxSYbeeVym1KTYPC6Dv1s3AADDVjh0Qod+kKR5XFJByo1xSaW2QIYgCQCpJRUG5ybVcO0q4oQbFykVagEAybkcGgnACRcAMBylfXAZrhUXAACGo3QPLo7IqSVt0IUEALBY2ncVOZRm4xjS6b0OAwwOBoBPSffgQlcRUllahWrbETKBhIjH/2oEFwDg74g9CJl2S/eKi8MYOeybPw8AMFD8ybeGcZwmZaZ7cKHiAgBAajpdYcERGfxJ2+rgknIz5wIAgDNK+6uKqLgAAGCRdA8uVFwAAEOB6QxSl9XBhYoLAGAo8KV4aMRj0liCCwAASAy6ikjFAADYgsG5VFwAALBHugcXKi4AANiDigsVFwAA7JHuwYWKCwAA9qDiQsUFAAB7pHtw4SaLAADYIx7nbKuDCxUXAAAskvYVFzHGBQAAW8TjTgpWBxcqLgAAWCTdKy7iqiIAAOxBcBEVFwAAbJHuwYV5XAAAsAfzuBhzagEAAKkv3S+HpuICAIA9qLgwxgUAAHuke3Ch4gIAgD2ouFBxAQDAHukeXLhXEQAA9uBeRVRcAACwR9pXXCKnFgAAkPricc62OrhQcQEAwCJUXBjjAgCALeJxznYO5ofXrFkjh8OhpUuXRtedOHFC1dXVGj9+vLKzs1VRUaH29vaYn2ttbVV5eblGjx6tvLw8LV++XD09Pf1vgJEUYUn5xbCwsLCwsHy8DNKAKy579uzR448/rhkzZsSsX7ZsmZ5++mlt3rxZHo9HNTU1mjdvnl5++WVJUjgcVnl5uXw+n3bu3Km2tjYtXLhQmZmZWr16db/awDwuluAYWcE4kt0CAMNesoLL8ePHNX/+fD3xxBP6/ve/H13f1dWlH//4x9q4caO+/OUvS5I2bNigqVOn6pVXXlFJSYl++9vf6uDBg3ruuefk9Xp16aWX6sEHH9SKFSt0//33Kysrq8/rhUIhhUKh6ONgMPjxv4y4VxEQH3wJsIiDlAk7JW0CuurqapWXl6u0tDQmuDQ3N6u7u1ulpaXRdVOmTFFhYaGamppUUlKipqYmTZ8+XV6vN7pPWVmZqqqqdODAAc2cObPP69XX12vlypV91lNxAZCW+MJmDSqZnzb4391+B5dNmzbptdde0549e/psCwQCysrKUk5OTsx6r9erQCAQ3eeToaV3e++206mrq1NtbW30cTAYVEFBgRQxpxYAAFJQWuQW59m/y4RXXI4cOaLbbrtNDQ0NGjly5OBf/Sy5XC65XK4+66m4wBZ86wIwbPWngBCHYkO/gktzc7M6Ojr0+c9/ProuHA5rx44d+uEPf6hnn31WJ0+eVGdnZ0zVpb29XT6fT5Lk8/m0e/fumOftveqod5+zFqcRysBQI2APAqEPGDYSXnG55ppr9MYbb8SsW7RokaZMmaIVK1aooKBAmZmZamxsVEVFhSSppaVFra2t8vv9kiS/369Vq1apo6NDeXl5kqSGhga53W4VFRX1q/HcqwhIA/wvnvIMg4VxthIdXMaOHatp06bFrBszZozGjx8fXb948WLV1tYqNzdXbrdbS5Yskd/vV0lJiSRpzpw5Kioq0oIFC7R27VoFAgHdfffdqq6uPm130Gei4gIASccXyBSWYpkyJW+y+PDDD8vpdKqiokKhUEhlZWVat25ddHtGRoa2bt2qqqoq+f1+jRkzRpWVlXrggQf6/VpUXAAA+Awpdop0xGGMi8MY+878wWBQHo9HV19xj0aMSNwgYQAAMHA9PSe0Y+eD6urqktvtHtBzWH2vIhkmoAMAwBqp2FWUSFwODQCAPZI2c27KoOICAIA90r3iwlVFAABYJN0rLlxVBACAPVLycuiE4l5FAADYI9FT/qcahxicCwCALeIxH57VwYXBuQAAWCTtu4qMCC4AANgi3QfnKqKUuw8DAAA4g8jgn8Lq4MJVRQAA2IOrihjjAgCAPQguBBcAAKyR9sGFMS4AANiDMS6McQEAwBaMcaGrCAAAexBcCC4AAFgj7YNLxDDnPwAAtkj3exVRcQEAwCJpX3EhuAAAYA+CC8EFAABrpHtwcRgjRxz6ywAAwNDjcuhIRHGZzSYVOJhJDwAwzKV9cBlOXUXD5X0MR4RKAIiPtA8uESOJEz6GGr9jCeckLALDUtoHFwDDE2PXgOGJeVyGUVcRAADDXdpXXMIRyYST3Qq7OZ3JbgEAIF2kfXCh4jJ4YYKfVRgoDMBm6d5VZIyRIbggnfD7bg0HIRPoK+0rLlxVBCBFGf422YOr2BImHsUGu4OLiZxaAAAYKHrMEycy+A/b8uDCGBcAAKxBxcUw3wMAALYguAyjexUBADDcxWF4h93BJWIkBxUXAACskO4VF2MMI/cBALBEwq8quv/++7Vy5cqYdZMnT9ahQ4ckSSdOnNDtt9+uTZs2KRQKqaysTOvWrZPX643u39raqqqqKr3wwgvKzs5WZWWl6uvrNWLEADJUJCI56CoCAMAKyegquvjii/Xcc8/9+Qk+ETiWLVump59+Wps3b5bH41FNTY3mzZunl19+WZIUDodVXl4un8+nnTt3qq2tTQsXLlRmZqZWr17d/9Yb5nEBAMAayegqGjFihHw+X5/1XV1d+vGPf6yNGzfqy1/+siRpw4YNmjp1ql555RWVlJTot7/9rQ4ePKjnnntOXq9Xl156qR588EGtWLFC999/v7KysvrXGCouAADYIxkVl7feekv5+fkaOXKk/H6/6uvrVVhYqObmZnV3d6u0tDS675QpU1RYWKimpiaVlJSoqalJ06dPj+k6KisrU1VVlQ4cOKCZM2ee9jVDoZBCoVD0cTAYlPTxNC5UXAAAsEI8pl7rV3ApLi7Wk08+qcmTJ6utrU0rV67UF77wBe3fv1+BQEBZWVnKycmJ+Rmv16tAICBJCgQCMaGld3vvtjOpr6/vM7ZGElcVAQBgk0R3Fc2dOzf67xkzZqi4uFgXXHCBfvazn2nUqFGDbsyZ1NXVqba2Nvo4GAyqoKCAeVwAALBJsudxycnJ0V//9V/r7bff1le+8hWdPHlSnZ2dMVWX9vb26JgYn8+n3bt3xzxHe3t7dNuZuFwuuVyuPutNxMhQcQEAwApJv8ni8ePH9c4772jBggWaNWuWMjMz1djYqIqKCklSS0uLWltb5ff7JUl+v1+rVq1SR0eH8vLyJEkNDQ1yu90qKirqfwOouAAAYI9EV1zuuOMOff3rX9cFF1yg9957T/fdd58yMjJ08803y+PxaPHixaqtrVVubq7cbreWLFkiv9+vkpISSdKcOXNUVFSkBQsWaO3atQoEArr77rtVXV192orKmfQmth5zkpssAgBgiR51Sxpk5cX0w4033mjOPfdck5WVZc477zxz4403mrfffju6/aOPPjLf+c53zLhx48zo0aPN9ddfb9ra2mKe449//KOZO3euGTVqlJkwYYK5/fbbTXd3d3+aYd55553eCVxYWFhYWFhYLFuOHDnSr/P+JzmMsa9k0dnZqXHjxqm1tVUejyfZzUlLvQOkjxw5IrfbnezmpCWOQfJxDJKPY5B8/TkGxhgdO3ZM+fn5cjqdA3o9K+9V1PtmPR4Pv6hJ5na7OQZJxjFIPo5B8nEMku9sj8FgCw4DizsAAABJQHABAADWsDK4uFwu3Xffff26EgnxxTFIPo5B8nEMko9jkHyJPgZWDs4FAADpycqKCwAASE8EFwAAYA2CCwAAsAbBBQAAWIPgAgAArGFlcPnRj36kCy+8UCNHjlRxcbF2796d7CYNC/X19brssss0duxY5eXl6brrrlNLS0vMPidOnFB1dbXGjx+v7OxsVVRUqL29PWaf1tZWlZeXa/To0crLy9Py5cvV09OTyLcybKxZs0YOh0NLly6NruMYDL13331Xf//3f6/x48dr1KhRmj59ul599dXodmOM7r33Xp177rkaNWqUSktL9dZbb8U8x9GjRzV//ny53W7l5ORo8eLFOn78eKLfipXC4bDuueceTZw4UaNGjdLnPvc5PfjggzE35uMYxNeOHTv09a9/Xfn5+XI4HPrlL38Zsz1en/fvfvc7feELX9DIkSNVUFCgtWvX9r+xA77LUZJs2rTJZGVlmX/91381Bw4cMN/+9rdNTk6OaW9vT3bTrFdWVmY2bNhg9u/fb/bt22euvfZaU1hYaI4fPx7d59ZbbzUFBQWmsbHRvPrqq6akpMRcccUV0e09PT1m2rRpprS01Ozdu9f85je/MRMmTDB1dXXJeEtW2717t7nwwgvNjBkzzG233RZdzzEYWkePHjUXXHCB+eY3v2l27dpl/vCHP5hnn3025oaya9asMR6Px/zyl780r7/+uvnbv/1bM3HiRPPRRx9F9/nqV79qLrnkEvPKK6+Y//zP/zQXXXSRufnmm5PxlqyzatUqM378eLN161Zz+PBh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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "with CustomSTACReader(\"data/stac_netcdf.json\") as src:\n", + " print(src)\n", + " print(src.assets)\n", + " print(src._get_asset_info(\"netcdf:dataset\"))\n", + " img = src.preview(assets=[\"netcdf:dataset\"])\n", + "\n", + "plt.imshow(img.data_as_image())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + }, + "vscode": { + "interpreter": { + "hash": "2590a9e34ee6c8bdce5141410f2a072bbabd2a859a8a48acdaa85720923a90ef" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/src/examples/data/dataset_2d.nc b/docs/src/examples/data/dataset_2d.nc new file mode 100644 index 00000000..2b0b42ad Binary files /dev/null and b/docs/src/examples/data/dataset_2d.nc differ diff --git a/docs/src/examples/data/stac_netcdf.json b/docs/src/examples/data/stac_netcdf.json new file mode 100644 index 00000000..3206ddcc --- /dev/null +++ b/docs/src/examples/data/stac_netcdf.json @@ -0,0 +1,111 @@ +{ + "type": "Feature", + "stac_version": "1.0.0", + "id": "my_stac", + "properties": { + "proj:epsg": 4326, + "proj:geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -170.085, + 79.91999999999659 + ], + [ + 169.91499999997504, + 79.91999999999659 + ], + [ + 169.91499999997504, + -80.08 + ], + [ + -170.085, + -80.08 + ], + [ + -170.085, + 79.91999999999659 + ] + ] + ] + }, + "proj:bbox": [ + -170.085, + 79.91999999999659, + 169.91499999997504, + -80.08 + ], + "proj:shape": [ + 1000, + 2000 + ], + "proj:transform": [ + 0.16999999999998752, + 0, + -170.085, + 0, + 0.1599999999999966, + -80.08, + 0, + 0, + 1 + ], + "datetime": "2024-11-05T09:03:47.523834Z" + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -170.085, + 79.91999999999659 + ], + [ + 169.91499999997504, + 79.91999999999659 + ], + [ + 169.91499999997504, + -80.08 + ], + [ + -170.085, + -80.08 + ], + [ + -170.085, + 79.91999999999659 + ] + ] + ] + }, + "links": [], + "assets": { + "netcdf": { + "href": "dataset_2d.nc", + "type": "application/x-netcdf", + "roles": ["data"], + "cube:variables": { + "dataset": { + "dimensions": [ + "y", + "x" + ], + "type": "data" + } + } + } + }, + "bbox": [ + -170.085, + -80.08, + 169.91499999997504, + 79.91999999999659 + ], + "stac_extensions": [ + "https://stac-extensions.github.io/projection/v1.1.0/schema.json", + "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" + ] +} diff --git a/pyproject.toml b/pyproject.toml index e1dbab57..a44e1a55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,7 @@ test = [ # XarrayReader "xarray", "rioxarray", + "h5netcdf", # S3 "boto3", # Some tests will fail with 5.0 diff --git a/rio_tiler/io/stac.py b/rio_tiler/io/stac.py index 95b55b8c..00ef144c 100644 --- a/rio_tiler/io/stac.py +++ b/rio_tiler/io/stac.py @@ -3,7 +3,18 @@ import json import os import warnings -from typing import Any, Dict, Iterator, Optional, Sequence, Set, Tuple, Type, Union +from typing import ( + Any, + Dict, + Iterator, + List, + Optional, + Sequence, + Set, + Tuple, + Type, + Union, +) from urllib.parse import urlparse import attr @@ -273,7 +284,13 @@ def __attrs_post_init__(self): self.minzoom = self.minzoom if self.minzoom is not None else self._minzoom self.maxzoom = self.maxzoom if self.maxzoom is not None else self._maxzoom - self.assets = list( + self.assets = self.get_asset_list() + if not self.assets: + raise MissingAssets("No valid asset found. Asset's media types not supported") + + def get_asset_list(self) -> List[str]: + """Get valid asset list""" + return list( _get_assets( self.item, include=self.include_assets, @@ -282,8 +299,6 @@ def __attrs_post_init__(self): exclude_asset_types=self.exclude_asset_types, ) ) - if not self.assets: - raise MissingAssets("No valid asset found. Asset's media types not supported") def _get_reader(self, asset_info: AssetInfo) -> Tuple[Type[BaseReader], Dict]: """Get Asset Reader.""" diff --git a/rio_tiler/io/xarray.py b/rio_tiler/io/xarray.py index fa843463..d5ae0369 100644 --- a/rio_tiler/io/xarray.py +++ b/rio_tiler/io/xarray.py @@ -3,7 +3,7 @@ from __future__ import annotations import warnings -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional import attr import numpy @@ -156,6 +156,7 @@ def statistics( percentiles: Optional[List[int]] = None, hist_options: Optional[Dict] = None, nodata: Optional[NoData] = None, + **kwargs: Any, ) -> Dict[str, BandStatistics]: """Return statistics from a dataset.""" hist_options = hist_options or {} @@ -188,6 +189,7 @@ def tile( reproject_method: WarpResampling = "nearest", auto_expand: bool = True, nodata: Optional[NoData] = None, + **kwargs: Any, ) -> ImageData: """Read a Web Map tile from a dataset. @@ -264,6 +266,7 @@ def part( height: Optional[int] = None, width: Optional[int] = None, resampling_method: RIOResampling = "nearest", + **kwargs: Any, ) -> ImageData: """Read part of a dataset. @@ -362,6 +365,7 @@ def preview( dst_crs: Optional[CRS] = None, reproject_method: WarpResampling = "nearest", resampling_method: RIOResampling = "nearest", + **kwargs: Any, ) -> ImageData: """Return a preview of a dataset. @@ -446,6 +450,7 @@ def point( lat: float, coord_crs: CRS = WGS84_CRS, nodata: Optional[NoData] = None, + **kwargs: Any, ) -> PointData: """Read a pixel value from a dataset. @@ -499,6 +504,7 @@ def feature( height: Optional[int] = None, width: Optional[int] = None, resampling_method: RIOResampling = "nearest", + **kwargs: Any, ) -> ImageData: """Read part of a dataset defined by a geojson feature. diff --git a/tests/fixtures/dataset_2d.nc b/tests/fixtures/dataset_2d.nc new file mode 100644 index 00000000..2b0b42ad Binary files /dev/null and b/tests/fixtures/dataset_2d.nc differ diff --git a/tests/fixtures/dataset_2d.tif b/tests/fixtures/dataset_2d.tif new file mode 100644 index 00000000..e7d4c102 Binary files /dev/null and b/tests/fixtures/dataset_2d.tif differ diff --git a/tests/fixtures/stac_netcdf.json b/tests/fixtures/stac_netcdf.json new file mode 100644 index 00000000..0ae52f99 --- /dev/null +++ b/tests/fixtures/stac_netcdf.json @@ -0,0 +1,106 @@ +{ + "type": "Feature", + "stac_version": "1.0.0", + "id": "my_stac", + "properties": { + "proj:epsg": 4326, + "proj:geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -170.085, + 79.91999999999659 + ], + [ + 169.91499999997504, + 79.91999999999659 + ], + [ + 169.91499999997504, + -80.08 + ], + [ + -170.085, + -80.08 + ], + [ + -170.085, + 79.91999999999659 + ] + ] + ] + }, + "proj:bbox": [ + -170.085, + 79.91999999999659, + 169.91499999997504, + -80.08 + ], + "proj:shape": [ + 1000, + 2000 + ], + "proj:transform": [ + 0.16999999999998752, + 0, + -170.085, + 0, + 0.1599999999999966, + -80.08, + 0, + 0, + 1 + ], + "datetime": "2024-11-05T09:03:47.523834Z" + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -170.085, + 79.91999999999659 + ], + [ + 169.91499999997504, + 79.91999999999659 + ], + [ + 169.91499999997504, + -80.08 + ], + [ + -170.085, + -80.08 + ], + [ + -170.085, + 79.91999999999659 + ] + ] + ] + }, + "links": [], + "assets": { + "geotiff": { + "href": "dataset_2d.tif", + "type": "image/tiff; application=geotiff", + "roles": ["data"] + }, + "netcdf": { + "href": "dataset_2d.nc", + "type": "application/x-netcdf", + "roles": ["data"] + } + }, + "bbox": [ + -170.085, + -80.08, + 169.91499999997504, + 79.91999999999659 + ], + "stac_extensions": [ + "https://stac-extensions.github.io/projection/v1.1.0/schema.json" + ] +} diff --git a/tests/test_io_stac.py b/tests/test_io_stac.py index a13eed6b..7932dfcb 100644 --- a/tests/test_io_stac.py +++ b/tests/test_io_stac.py @@ -3,7 +3,7 @@ import json import os import sys -from typing import Dict, Set, Tuple, Type +from typing import Dict, List, Set, Tuple, Type from unittest.mock import patch import attr @@ -11,9 +11,12 @@ import numpy import pytest import rasterio +import xarray +from morecantile import TileMatrixSet from rasterio._env import get_gdal_config from rasterio.crs import CRS +from rio_tiler.constants import WEB_MERCATOR_TMS from rio_tiler.errors import ( AssetAsBandError, ExpressionMixingWarning, @@ -36,6 +39,7 @@ STAC_WRONGSTATS_PATH = os.path.join(PREFIX, "stac_wrong_stats.json") STAC_ALTERNATE_PATH = os.path.join(PREFIX, "stac_alternate.json") STAC_GRIB_PATH = os.path.join(PREFIX, "stac_grib.json") +STAC_NETCDF_PATH = os.path.join(PREFIX, "stac_netcdf.json") with open(STAC_PATH) as f: item = json.loads(f.read()) @@ -987,8 +991,39 @@ def test_default_assets(rio): assert img.band_names == ["green_b1"] -def test_get_reader(): +def test_netcdf_reader(): """Should use the correct reader depending on the media type.""" + + @attr.s + class NetCDFReader(XarrayReader): + """Reader: Open NetCDF file and access DataArray.""" + + src_path: str = attr.ib() + variable: str = attr.ib() + + tms: TileMatrixSet = attr.ib(default=WEB_MERCATOR_TMS) + + ds: xarray.Dataset = attr.ib(init=False) + input: xarray.DataArray = attr.ib(init=False) + + _dims: List = attr.ib(init=False, factory=list) + + def __attrs_post_init__(self): + """Set bounds and CRS.""" + self.ds = xarray.open_dataset(self.src_path, decode_coords="all") + da = self.ds[self.variable] + + # Make sure we have a valid CRS + crs = da.rio.crs or "epsg:4326" + da = da.rio.write_crs(crs) + + if "time" in da.dims: + da = da.isel(time=0) + + self.input = da + + super().__attrs_post_init__() + valid_types = { "image/tiff; application=geotiff", "application/x-netcdf", @@ -1004,20 +1039,29 @@ def _get_reader(self, asset_info: AssetInfo) -> Tuple[Type[BaseReader], Dict]: if asset_type and asset_type in [ "application/x-netcdf", ]: - return XarrayReader, {} + return NetCDFReader, {} return Reader, {} - with CustomSTACReader(STAC_RASTER_PATH) as stac: - assert stac.assets == ["red", "green", "blue", "netcdf"] + with CustomSTACReader(STAC_NETCDF_PATH) as stac: + assert stac.assets == ["geotiff", "netcdf"] info = stac._get_asset_info("netcdf") assert info["media_type"] == "application/x-netcdf" - assert stac._get_reader(info) == (XarrayReader, {}) + assert stac._get_reader(info) == (NetCDFReader, {}) - info = stac._get_asset_info("red") + info = stac._get_asset_info("geotiff") assert info["media_type"] == "image/tiff; application=geotiff" assert stac._get_reader(info) == (Reader, {}) + with CustomSTACReader( + STAC_NETCDF_PATH, reader_options={"variable": "dataset"} + ) as stac: + info = stac.info(assets=["netcdf"]) + assert info["netcdf"].crs + + img = stac.preview(assets=["netcdf"]) + assert img.band_names == ["netcdf_value"] + @patch("rio_tiler.io.stac.STAC_ALTERNATE_KEY", "s3") def test_alternate_assets():