Repository: Open-EO/openeo-processes-dask (language: python)

Issue:
Implement load_stac



Discussion / hints:
@LukeWeidenwalker I'm waiting for the fixes about the openeo accessor for the dimensions and the merge of `filter_bbox` before I can create a PR for this.

Fix patch:
diff --git a/openeo_processes_dask/process_implementations/cubes/__init__.py b/openeo_processes_dask/process_implementations/cubes/__init__.py
index a6df05fc..aa4ade45 100644
--- a/openeo_processes_dask/process_implementations/cubes/__init__.py
+++ b/openeo_processes_dask/process_implementations/cubes/__init__.py
@@ -2,5 +2,6 @@
 from .aggregate import *
 from .apply import *
 from .general import *
+from .load import *
 from .merge import *
 from .reduce import *
diff --git a/openeo_processes_dask/process_implementations/cubes/load.py b/openeo_processes_dask/process_implementations/cubes/load.py
new file mode 100644
index 00000000..4e195079
--- /dev/null
+++ b/openeo_processes_dask/process_implementations/cubes/load.py
@@ -0,0 +1,164 @@
+import datetime
+import json
+import logging
+from collections.abc import Iterator
+from pathlib import PurePosixPath
+from typing import Any, Callable, Dict, List, Optional, Tuple, Union
+from urllib.parse import unquote, urljoin, urlparse
+
+import planetary_computer as pc
+import pyproj
+import pystac_client
+import stackstac
+import xarray as xr
+from openeo_pg_parser_networkx.pg_schema import BoundingBox, TemporalInterval
+from stac_validator import stac_validator
+
+from openeo_processes_dask.process_implementations.cubes._filter import (
+    _reproject_bbox,
+    filter_bands,
+    filter_bbox,
+    filter_temporal,
+)
+from openeo_processes_dask.process_implementations.data_model import RasterCube
+from openeo_processes_dask.process_implementations.exceptions import (
+    NoDataAvailable,
+    TemporalExtentEmpty,
+)
+
+# "NoDataAvailable": {
+#     "message": "There is no data available for the given extents."
+# },
+# "TemporalExtentEmpty": {
+#     "message": "The temporal extent is empty. The second instant in time must always be greater/later than the first instant in time."
+# }
+__all__ = ["load_stac"]
+
+logger = logging.getLogger(__name__)
+
+
+def _validate_stac(url):
+    logger.debug(f"Validating the provided STAC url: {url}")
+    stac = stac_validator.StacValidate(url)
+    is_valid_stac = stac.run()
+    if not is_valid_stac:
+        raise Exception(
+            f"The provided link is not a valid STAC. stac-validator message: {stac.message}"
+        )
+    if len(stac.message) == 1:
+        try:
+            asset_type = stac.message[0]["asset_type"]
+        except:
+            raise Exception(f"stac-validator returned an error: {stac.message}")
+    else:
+        raise Exception(
+            f"stac-validator returned multiple items, not supported yet. {stac.message}"
+        )
+    return asset_type
+
+
+def _search_for_parent_catalog(url):
+    parsed_url = urlparse(url)
+    root_url = parsed_url.scheme + "://" + parsed_url.netloc
+    catalog_url = root_url
+    url_parts = PurePosixPath(unquote(parsed_url.path)).parts
+    collection_id = url_parts[-1]
+    for p in url_parts:
+        if p != "/":
+            catalog_url = catalog_url + "/" + p
+        try:
+            asset_type = _validate_stac(catalog_url)
+        except Exception as e:
+            logger.debug(e)
+            continue
+        if asset_type == "CATALOG":
+            break
+    if asset_type != "CATALOG":
+        raise Exception(
+            "It was not possible to find the root STAC Catalog starting from the provided Collection."
+        )
+    return catalog_url, collection_id
+
+
+def load_stac(
+    url: str,
+    spatial_extent: Optional[BoundingBox] = None,
+    temporal_extent: Optional[TemporalInterval] = None,
+    bands: Optional[list[str]] = None,
+    properties: Optional[dict] = None,
+) -> RasterCube:
+    asset_type = _validate_stac(url)
+
+    if asset_type == "COLLECTION":
+        # If query parameters are passed, try to get the parent Catalog if possible/exists, to use the /search endpoint
+        if spatial_extent or temporal_extent or bands or properties:
+            # If query parameters are passed, try to get the parent Catalog if possible/exists, to use the /search endpoint
+            catalog_url, collection_id = _search_for_parent_catalog(url)
+
+            # Check if we are connecting to Microsoft Planetary Computer, where we need to sign the connection
+            modifier = pc.sign_inplace if "planetarycomputer" in catalog_url else None
+
+            catalog = pystac_client.Client.open(catalog_url, modifier=modifier)
+
+            query_params = {"collections": [collection_id]}
+
+            if spatial_extent is not None:
+                try:
+                    spatial_extent_4326 = spatial_extent
+                    if spatial_extent.crs is not None:
+                        if not pyproj.crs.CRS(spatial_extent.crs).equals("EPSG:4326"):
+                            spatial_extent_4326 = _reproject_bbox(
+                                spatial_extent, "EPSG:4326"
+                            )
+                    bbox = [
+                        spatial_extent_4326.west,
+                        spatial_extent_4326.south,
+                        spatial_extent_4326.east,
+                        spatial_extent_4326.north,
+                    ]
+                    query_params["bbox"] = bbox
+                except Exception as e:
+                    raise Exception(f"Unable to parse the provided spatial extent: {e}")
+
+            if temporal_extent is not None:
+                start_date = None
+                end_date = None
+                if temporal_extent[0] is not None:
+                    start_date = str(temporal_extent[0].to_numpy())
+                if temporal_extent[1] is not None:
+                    end_date = str(temporal_extent[1].to_numpy())
+                query_params["datetime"] = [start_date, end_date]
+
+            if properties is not None:
+                query_params["query"] = properties
+
+            items = catalog.search(**query_params).item_collection()
+
+        else:
+            # Load the whole collection wihout filters
+            raise Exception(
+                f"No parameters for filtering provided. Loading the whole STAC Collection is not supported yet."
+            )
+
+    elif asset_type == "ITEM":
+        stac_api = pystac_client.stac_api_io.StacApiIO()
+        stac_dict = json.loads(stac_api.read_text(url))
+        items = stac_api.stac_object_from_dict(stac_dict)
+
+    else:
+        raise Exception(
+            f"The provided URL is a STAC {asset_type}, which is not yet supported. Please provide a valid URL to a STAC Collection or Item."
+        )
+
+    if bands is not None:
+        stack = stackstac.stack(items, assets=bands)
+    else:
+        stack = stackstac.stack(items)
+
+    if spatial_extent is not None:
+        stack = filter_bbox(stack, spatial_extent)
+
+    if temporal_extent is not None and asset_type == "ITEM":
+        stack = filter_temporal(stack, temporal_extent)
+
+    return stack
diff --git a/openeo_processes_dask/process_implementations/exceptions.py b/openeo_processes_dask/process_implementations/exceptions.py
index 8e8f5947..42a67bd5 100644
--- a/openeo_processes_dask/process_implementations/exceptions.py
+++ b/openeo_processes_dask/process_implementations/exceptions.py
@@ -56,3 +56,11 @@ class DimensionMissing(OpenEOException):
 
 class BandFilterParameterMissing(OpenEOException):
     pass
+
+
+class NoDataAvailable(OpenEOException):
+    pass
+
+
+class TemporalExtentEmpty(OpenEOException):
+    pass
diff --git a/openeo_processes_dask/specs/openeo-processes b/openeo_processes_dask/specs/openeo-processes
index 965bbaeb..bc6366f5 160000
--- a/openeo_processes_dask/specs/openeo-processes
+++ b/openeo_processes_dask/specs/openeo-processes
@@ -1,1 +1,1 @@
-Subproject commit 965bbaebd4d5984203a0437076c85a66a72a23e0
+Subproject commit bc6366f58eaddd80a37db81d6507fdcfc3a94662
diff --git a/pyproject.toml b/pyproject.toml
index 9a53dbd8..74eceec3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -33,6 +33,10 @@ rioxarray = { version = ">=0.12.0,<1", optional = true }
 odc-algo = { version = "==0.2.3", optional = true }
 openeo-pg-parser-networkx = { version = ">=2023.5.1", optional = true }
 odc-geo = { version = "^0.3.2", optional = true }
+stac_validator = { version = ">=3.3.1", optional = true }
+stackstac = { version = ">=0.4.3", optional = true }
+pystac_client = { version = ">=0.6.1", optional = true }
+planetary_computer = { version = ">=0.5.1", optional = true }
 
 [tool.poetry.group.dev.dependencies]
 pytest = "^7.2.0"
@@ -45,7 +49,7 @@ pre-commit = "^2.20.0"
 pytest-cov = "^4.0.0"
 
 [tool.poetry.extras]
-implementations = ["geopandas", "xarray", "dask", "rasterio", "dask-geopandas", "rioxarray", "openeo-pg-parser-networkx", "odc-geo"]
+implementations = ["geopandas", "xarray", "dask", "rasterio", "dask-geopandas", "rioxarray", "openeo-pg-parser-networkx", "odc-geo", "stackstac", "planetary_computer", "pystac_client", "stac_validator"]
 experimental = ["odc-algo"]
 ml = ["xgboost"]
 


Test patch:
diff --git a/tests/data/stac/s2_l2a_test_item.json b/tests/data/stac/s2_l2a_test_item.json
new file mode 100644
index 00000000..911fa09a
--- /dev/null
+++ b/tests/data/stac/s2_l2a_test_item.json
@@ -0,0 +1,1411 @@
+{
+  "type": "Feature",
+  "stac_version": "1.0.0",
+  "id": "S2A_32TPS_20230602_0_L2A",
+  "properties": {
+    "created": "2023-06-02T21:15:52.254Z",
+    "platform": "sentinel-2a",
+    "constellation": "sentinel-2",
+    "instruments": [
+      "msi"
+    ],
+    "eo:cloud_cover": 31.735489,
+    "proj:epsg": 32632,
+    "mgrs:utm_zone": 32,
+    "mgrs:latitude_band": "T",
+    "mgrs:grid_square": "PS",
+    "grid:code": "MGRS-32TPS",
+    "view:sun_azimuth": 150.260515978055,
+    "view:sun_elevation": 63.2305935349323,
+    "s2:degraded_msi_data_percentage": 0.1128,
+    "s2:nodata_pixel_percentage": 0,
+    "s2:saturated_defective_pixel_percentage": 0,
+    "s2:dark_features_percentage": 0.851427,
+    "s2:cloud_shadow_percentage": 5.519527,
+    "s2:vegetation_percentage": 44.695824,
+    "s2:not_vegetated_percentage": 6.347982,
+    "s2:water_percentage": 0.271986,
+    "s2:unclassified_percentage": 0.524517,
+    "s2:medium_proba_clouds_percentage": 9.545068,
+    "s2:high_proba_clouds_percentage": 21.567261,
+    "s2:thin_cirrus_percentage": 0.62316,
+    "s2:snow_ice_percentage": 10.053248,
+    "s2:product_type": "S2MSI2A",
+    "s2:processing_baseline": "05.09",
+    "s2:product_uri": "S2A_MSIL2A_20230602T100601_N0509_R022_T32TPS_20230602T162001.SAFE",
+    "s2:generation_time": "2023-06-02T16:20:01.000000Z",
+    "s2:datatake_id": "GS2A_20230602T100601_041489_N05.09",
+    "s2:datatake_type": "INS-NOBS",
+    "s2:datastrip_id": "S2A_OPER_MSI_L2A_DS_2APS_20230602T162001_S20230602T100832_N05.09",
+    "s2:granule_id": "S2A_OPER_MSI_L2A_TL_2APS_20230602T162001_A041489_T32TPS_N05.09",
+    "s2:reflectance_conversion_factor": 0.973537588529029,
+    "datetime": "2023-06-02T10:18:03.169000Z",
+    "s2:sequence": "0",
+    "earthsearch:s3_path": "s3://sentinel-cogs/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A",
+    "earthsearch:payload_id": "roda-sentinel2/workflow-sentinel2-to-stac/862356d8ee275d311b2b78123d5998be",
+    "earthsearch:boa_offset_applied": true,
+    "processing:software": {
+      "sentinel2-to-stac": "0.1.0"
+    },
+    "updated": "2023-06-02T21:15:52.254Z"
+  },
+  "geometry": {
+    "type": "Polygon",
+    "coordinates": [
+      [
+        [
+          10.31404819699118,
+          46.94615910623302
+        ],
+        [
+          11.755571336057699,
+          46.92052771524623
+        ],
+        [
+          11.706241885992638,
+          45.933505800162294
+        ],
+        [
+          10.290497179167554,
+          45.958273370339676
+        ],
+        [
+          10.31404819699118,
+          46.94615910623302
+        ]
+      ]
+    ]
+  },
+  "links": [
+    {
+      "rel": "self",
+      "type": "application/geo+json",
+      "href": "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2A_32TPS_20230602_0_L2A"
+    },
+    {
+      "rel": "canonical",
+      "href": "s3://sentinel-cogs/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/S2A_32TPS_20230602_0_L2A.json",
+      "type": "application/json"
+    },
+    {
+      "rel": "license",
+      "href": "https://sentinel.esa.int/documents/247904/690755/Sentinel_Data_Legal_Notice"
+    },
+    {
+      "rel": "derived_from",
+      "href": "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l1c/items/S2A_32TPS_20230602_0_L1C",
+      "type": "application/geo+json"
+    },
+    {
+      "rel": "parent",
+      "type": "application/json",
+      "href": "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a"
+    },
+    {
+      "rel": "collection",
+      "type": "application/json",
+      "href": "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a"
+    },
+    {
+      "rel": "root",
+      "type": "application/json",
+      "href": "https://earth-search.aws.element84.com/v1"
+    },
+    {
+      "rel": "thumbnail",
+      "href": "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2A_32TPS_20230602_0_L2A/thumbnail"
+    }
+  ],
+  "assets": {
+    "aot": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/AOT.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Aerosol optical thickness (AOT)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.001,
+          "offset": 0
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "blue": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B02.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Blue (band 2) - 10m",
+      "eo:bands": [
+        {
+          "name": "blue",
+          "common_name": "blue",
+          "description": "Blue (band 2)",
+          "center_wavelength": 0.49,
+          "full_width_half_max": 0.098
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "coastal": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B01.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Coastal aerosol (band 1) - 60m",
+      "eo:bands": [
+        {
+          "name": "coastal",
+          "common_name": "coastal",
+          "description": "Coastal aerosol (band 1)",
+          "center_wavelength": 0.443,
+          "full_width_half_max": 0.027
+        }
+      ],
+      "gsd": 60,
+      "proj:shape": [
+        1830,
+        1830
+      ],
+      "proj:transform": [
+        60,
+        0,
+        600000,
+        0,
+        -60,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 60,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "granule_metadata": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/granule_metadata.xml",
+      "type": "application/xml",
+      "roles": [
+        "metadata"
+      ]
+    },
+    "green": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B03.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Green (band 3) - 10m",
+      "eo:bands": [
+        {
+          "name": "green",
+          "common_name": "green",
+          "description": "Green (band 3)",
+          "center_wavelength": 0.56,
+          "full_width_half_max": 0.045
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B08.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "NIR 1 (band 8) - 10m",
+      "eo:bands": [
+        {
+          "name": "nir",
+          "common_name": "nir",
+          "description": "NIR 1 (band 8)",
+          "center_wavelength": 0.842,
+          "full_width_half_max": 0.145
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir08": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B8A.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "NIR 2 (band 8A) - 20m",
+      "eo:bands": [
+        {
+          "name": "nir08",
+          "common_name": "nir08",
+          "description": "NIR 2 (band 8A)",
+          "center_wavelength": 0.865,
+          "full_width_half_max": 0.033
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir09": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B09.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "NIR 3 (band 9) - 60m",
+      "eo:bands": [
+        {
+          "name": "nir09",
+          "common_name": "nir09",
+          "description": "NIR 3 (band 9)",
+          "center_wavelength": 0.945,
+          "full_width_half_max": 0.026
+        }
+      ],
+      "gsd": 60,
+      "proj:shape": [
+        1830,
+        1830
+      ],
+      "proj:transform": [
+        60,
+        0,
+        600000,
+        0,
+        -60,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 60,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "red": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B04.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Red (band 4) - 10m",
+      "eo:bands": [
+        {
+          "name": "red",
+          "common_name": "red",
+          "description": "Red (band 4)",
+          "center_wavelength": 0.665,
+          "full_width_half_max": 0.038
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge1": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B05.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Red edge 1 (band 5) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge1",
+          "common_name": "rededge",
+          "description": "Red edge 1 (band 5)",
+          "center_wavelength": 0.704,
+          "full_width_half_max": 0.019
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge2": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B06.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Red edge 2 (band 6) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge2",
+          "common_name": "rededge",
+          "description": "Red edge 2 (band 6)",
+          "center_wavelength": 0.74,
+          "full_width_half_max": 0.018
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge3": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B07.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Red edge 3 (band 7) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge3",
+          "common_name": "rededge",
+          "description": "Red edge 3 (band 7)",
+          "center_wavelength": 0.783,
+          "full_width_half_max": 0.028
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "scl": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/SCL.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Scene classification map (SCL)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint8",
+          "spatial_resolution": 20
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "swir16": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B11.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "SWIR 1 (band 11) - 20m",
+      "eo:bands": [
+        {
+          "name": "swir16",
+          "common_name": "swir16",
+          "description": "SWIR 1 (band 11)",
+          "center_wavelength": 1.61,
+          "full_width_half_max": 0.143
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "swir22": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/B12.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "SWIR 2 (band 12) - 20m",
+      "eo:bands": [
+        {
+          "name": "swir22",
+          "common_name": "swir22",
+          "description": "SWIR 2 (band 12)",
+          "center_wavelength": 2.19,
+          "full_width_half_max": 0.242
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "thumbnail": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/thumbnail.jpg",
+      "type": "image/jpeg",
+      "title": "Thumbnail image",
+      "roles": [
+        "thumbnail"
+      ]
+    },
+    "tileinfo_metadata": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/tileinfo_metadata.json",
+      "type": "application/json",
+      "roles": [
+        "metadata"
+      ]
+    },
+    "visual": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/TCI.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "True color image",
+      "eo:bands": [
+        {
+          "name": "red",
+          "common_name": "red",
+          "description": "Red (band 4)",
+          "center_wavelength": 0.665,
+          "full_width_half_max": 0.038
+        },
+        {
+          "name": "green",
+          "common_name": "green",
+          "description": "Green (band 3)",
+          "center_wavelength": 0.56,
+          "full_width_half_max": 0.045
+        },
+        {
+          "name": "blue",
+          "common_name": "blue",
+          "description": "Blue (band 2)",
+          "center_wavelength": 0.49,
+          "full_width_half_max": 0.098
+        }
+      ],
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "roles": [
+        "visual"
+      ]
+    },
+    "wvp": {
+      "href": "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/32/T/PS/2023/6/S2A_32TPS_20230602_0_L2A/WVP.tif",
+      "type": "image/tiff; application=geotiff; profile=cloud-optimized",
+      "title": "Water vapour (WVP)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "unit": "cm",
+          "scale": 0.001,
+          "offset": 0
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "aot-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/AOT.jp2",
+      "type": "image/jp2",
+      "title": "Aerosol optical thickness (AOT)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.001,
+          "offset": 0
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "blue-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B02.jp2",
+      "type": "image/jp2",
+      "title": "Blue (band 2) - 10m",
+      "eo:bands": [
+        {
+          "name": "blue",
+          "common_name": "blue",
+          "description": "Blue (band 2)",
+          "center_wavelength": 0.49,
+          "full_width_half_max": 0.098
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "coastal-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B01.jp2",
+      "type": "image/jp2",
+      "title": "Coastal aerosol (band 1) - 60m",
+      "eo:bands": [
+        {
+          "name": "coastal",
+          "common_name": "coastal",
+          "description": "Coastal aerosol (band 1)",
+          "center_wavelength": 0.443,
+          "full_width_half_max": 0.027
+        }
+      ],
+      "gsd": 60,
+      "proj:shape": [
+        1830,
+        1830
+      ],
+      "proj:transform": [
+        60,
+        0,
+        600000,
+        0,
+        -60,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 60,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "green-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B03.jp2",
+      "type": "image/jp2",
+      "title": "Green (band 3) - 10m",
+      "eo:bands": [
+        {
+          "name": "green",
+          "common_name": "green",
+          "description": "Green (band 3)",
+          "center_wavelength": 0.56,
+          "full_width_half_max": 0.045
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B08.jp2",
+      "type": "image/jp2",
+      "title": "NIR 1 (band 8) - 10m",
+      "eo:bands": [
+        {
+          "name": "nir",
+          "common_name": "nir",
+          "description": "NIR 1 (band 8)",
+          "center_wavelength": 0.842,
+          "full_width_half_max": 0.145
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir08-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B8A.jp2",
+      "type": "image/jp2",
+      "title": "NIR 2 (band 8A) - 20m",
+      "eo:bands": [
+        {
+          "name": "nir08",
+          "common_name": "nir08",
+          "description": "NIR 2 (band 8A)",
+          "center_wavelength": 0.865,
+          "full_width_half_max": 0.033
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "nir09-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B09.jp2",
+      "type": "image/jp2",
+      "title": "NIR 3 (band 9) - 60m",
+      "eo:bands": [
+        {
+          "name": "nir09",
+          "common_name": "nir09",
+          "description": "NIR 3 (band 9)",
+          "center_wavelength": 0.945,
+          "full_width_half_max": 0.026
+        }
+      ],
+      "gsd": 60,
+      "proj:shape": [
+        1830,
+        1830
+      ],
+      "proj:transform": [
+        60,
+        0,
+        600000,
+        0,
+        -60,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 60,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "red-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B04.jp2",
+      "type": "image/jp2",
+      "title": "Red (band 4) - 10m",
+      "eo:bands": [
+        {
+          "name": "red",
+          "common_name": "red",
+          "description": "Red (band 4)",
+          "center_wavelength": 0.665,
+          "full_width_half_max": 0.038
+        }
+      ],
+      "gsd": 10,
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 10,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge1-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B05.jp2",
+      "type": "image/jp2",
+      "title": "Red edge 1 (band 5) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge1",
+          "common_name": "rededge",
+          "description": "Red edge 1 (band 5)",
+          "center_wavelength": 0.704,
+          "full_width_half_max": 0.019
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge2-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B06.jp2",
+      "type": "image/jp2",
+      "title": "Red edge 2 (band 6) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge2",
+          "common_name": "rededge",
+          "description": "Red edge 2 (band 6)",
+          "center_wavelength": 0.74,
+          "full_width_half_max": 0.018
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "rededge3-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B07.jp2",
+      "type": "image/jp2",
+      "title": "Red edge 3 (band 7) - 20m",
+      "eo:bands": [
+        {
+          "name": "rededge3",
+          "common_name": "rededge",
+          "description": "Red edge 3 (band 7)",
+          "center_wavelength": 0.783,
+          "full_width_half_max": 0.028
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "scl-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/SCL.jp2",
+      "type": "image/jp2",
+      "title": "Scene classification map (SCL)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint8",
+          "spatial_resolution": 20
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "swir16-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B11.jp2",
+      "type": "image/jp2",
+      "title": "SWIR 1 (band 11) - 20m",
+      "eo:bands": [
+        {
+          "name": "swir16",
+          "common_name": "swir16",
+          "description": "SWIR 1 (band 11)",
+          "center_wavelength": 1.61,
+          "full_width_half_max": 0.143
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "swir22-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/B12.jp2",
+      "type": "image/jp2",
+      "title": "SWIR 2 (band 12) - 20m",
+      "eo:bands": [
+        {
+          "name": "swir22",
+          "common_name": "swir22",
+          "description": "SWIR 2 (band 12)",
+          "center_wavelength": 2.19,
+          "full_width_half_max": 0.242
+        }
+      ],
+      "gsd": 20,
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "scale": 0.0001,
+          "offset": -0.1
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    },
+    "visual-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/TCI.jp2",
+      "type": "image/jp2",
+      "title": "True color image",
+      "eo:bands": [
+        {
+          "name": "red",
+          "common_name": "red",
+          "description": "Red (band 4)",
+          "center_wavelength": 0.665,
+          "full_width_half_max": 0.038
+        },
+        {
+          "name": "green",
+          "common_name": "green",
+          "description": "Green (band 3)",
+          "center_wavelength": 0.56,
+          "full_width_half_max": 0.045
+        },
+        {
+          "name": "blue",
+          "common_name": "blue",
+          "description": "Blue (band 2)",
+          "center_wavelength": 0.49,
+          "full_width_half_max": 0.098
+        }
+      ],
+      "proj:shape": [
+        10980,
+        10980
+      ],
+      "proj:transform": [
+        10,
+        0,
+        600000,
+        0,
+        -10,
+        5200020
+      ],
+      "roles": [
+        "visual"
+      ]
+    },
+    "wvp-jp2": {
+      "href": "s3://sentinel-s2-l2a/tiles/32/T/PS/2023/6/2/0/WVP.jp2",
+      "type": "image/jp2",
+      "title": "Water vapour (WVP)",
+      "proj:shape": [
+        5490,
+        5490
+      ],
+      "proj:transform": [
+        20,
+        0,
+        600000,
+        0,
+        -20,
+        5200020
+      ],
+      "raster:bands": [
+        {
+          "nodata": 0,
+          "data_type": "uint16",
+          "bits_per_sample": 15,
+          "spatial_resolution": 20,
+          "unit": "cm",
+          "scale": 0.001,
+          "offset": 0
+        }
+      ],
+      "roles": [
+        "data",
+        "reflectance"
+      ]
+    }
+  },
+  "bbox": [
+    10.290497179167554,
+    45.933505800162294,
+    11.755571336057699,
+    46.94615910623302
+  ],
+  "stac_extensions": [
+    "https://stac-extensions.github.io/grid/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/projection/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/eo/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/mgrs/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/processing/v1.1.0/schema.json",
+    "https://stac-extensions.github.io/view/v1.0.0/schema.json",
+    "https://stac-extensions.github.io/raster/v1.1.0/schema.json"
+  ],
+  "collection": "sentinel-2-l2a"
+}
diff --git a/tests/test_load_stac.py b/tests/test_load_stac.py
new file mode 100644
index 00000000..cce93573
--- /dev/null
+++ b/tests/test_load_stac.py
@@ -0,0 +1,18 @@
+import pytest
+
+from openeo_processes_dask.process_implementations.cubes.load import load_stac
+
+
+def test_load_stac(bounding_box):
+    url = "./tests/data/stac/s2_l2a_test_item.json"
+    output_cube = load_stac(
+        url=url,
+        spatial_extent=bounding_box,
+        bands=["red"],
+    )
+
+    assert output_cube.openeo is not None
+    assert len(output_cube[output_cube.openeo.x_dim]) > 0
+    assert len(output_cube[output_cube.openeo.y_dim]) > 0
+    assert len(output_cube[output_cube.openeo.band_dims[0]]) > 0
+    assert len(output_cube[output_cube.openeo.temporal_dims[0]]) > 0