Working With STAC¶
STAC: SpatioTemporal Asset Catalog¶
The SpatioTemporal Asset Catalog (STAC) specification aims to standardize the way geospatial assets are exposed online and queried. A 'spatiotemporal asset' is any file that represents information about the earth captured in a certain space and time. The initial focus is primarily remotely-sensed imagery (from satellites, but also planes, drones, balloons, etc), but the core is designed to be extensible to SAR, full motion video, point clouds, hyperspectral, LiDAR and derived data like NDVI, Digital Elevation Models, mosaics, etc.
Ref: https://github.com/radiantearth/stac-spechttps://github.com/radiantearth/stac-spec
Using STAC makes data indexation and discovery really easy. In addition to the Collection/Item/Asset (data) specifications, data providers are also encouraged to follow a STAC API specification: https://github.com/radiantearth/stac-api-spec
The API is compliant with the OGC API - Features standard (formerly known as OGC Web Feature Service 3), in that it defines many of the endpoints that STAC uses. A STAC API should be compatible and usable with any OGC API - Features clients. The STAC API can be thought of as a specialized Features API to search STAC Catalogs, where the features returned are STAC Items, that have common properties, links to their assets and geometries that represent the footprints of the geospatial assets.
Requirements¶
To be able to run this notebook you'll need the following requirements:
- folium
- httpx
- rasterio
!pip install folium httpx rasterio
# Uncomment this line if you need to install the dependencies
# !pip install folium requests rasterio
import httpx
from rasterio.features import bounds as featureBounds
from folium import Map, TileLayer, GeoJson
%pylab inline
%pylab is deprecated, use %matplotlib inline and import the required libraries. Populating the interactive namespace from numpy and matplotlib
titiler_endpoint = "https://titiler.xyz" # Developmentseed Demo endpoint. Please be kind.
stac_item = "https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2A_30TVT_20221112_0_L2A"
item = httpx.get(stac_item).json()
print(item)
{'type': 'Feature', 'stac_version': '1.0.0', 'id': 'S2A_30TVT_20221112_0_L2A', 'properties': {'created': '2022-11-14T06:54:49.284Z', 'platform': 'sentinel-2a', 'constellation': 'sentinel-2', 'instruments': ['msi'], 'eo:cloud_cover': 0.005979, 'proj:epsg': 32630, 'mgrs:utm_zone': 30, 'mgrs:latitude_band': 'T', 'mgrs:grid_square': 'VT', 'grid:code': 'MGRS-30TVT', 'view:sun_azimuth': 169.467826196677, 'view:sun_elevation': 24.259740600657594, 's2:degraded_msi_data_percentage': 0, 's2:nodata_pixel_percentage': 0.000226, 's2:saturated_defective_pixel_percentage': 0, 's2:dark_features_percentage': 0, 's2:cloud_shadow_percentage': 0.002296, 's2:vegetation_percentage': 10.348745, 's2:not_vegetated_percentage': 2.478484, 's2:water_percentage': 87.111628, 's2:unclassified_percentage': 0.002548, 's2:medium_proba_clouds_percentage': 0.003716, 's2:high_proba_clouds_percentage': 0.000508, 's2:thin_cirrus_percentage': 0.001755, 's2:snow_ice_percentage': 0.050325, 's2:product_type': 'S2MSI2A', 's2:processing_baseline': '04.00', 's2:product_uri': 'S2A_MSIL2A_20221112T111321_N0400_R137_T30TVT_20221112T145700.SAFE', 's2:generation_time': '2022-11-12T14:57:00.000000Z', 's2:datatake_id': 'GS2A_20221112T111321_038601_N04.00', 's2:datatake_type': 'INS-NOBS', 's2:datastrip_id': 'S2A_OPER_MSI_L2A_DS_ATOS_20221112T145700_S20221112T111315_N04.00', 's2:granule_id': 'S2A_OPER_MSI_L2A_TL_ATOS_20221112T145700_A038601_T30TVT_N04.00', 's2:reflectance_conversion_factor': 1.0193600036007, 'datetime': '2022-11-12T11:18:11.455000Z', 's2:sequence': '0', 'earthsearch:s3_path': 's3://sentinel-cogs/sentinel-s2-l2a-cogs/30/T/VT/2022/11/S2A_30TVT_20221112_0_L2A', 'earthsearch:payload_id': 'roda-sentinel2/workflow-sentinel2-to-stac/d5f624f4b32b7ca4b39180d6eceea7fd', 'earthsearch:boa_offset_applied': True, 'processing:software': {'sentinel2-to-stac': '0.1.0'}, 'updated': '2022-11-14T06:54:49.284Z'}, 'geometry': {'type': 'Polygon', 'coordinates': [[[-4.337121116089946, 47.8459059875105], [-2.86954302848021, 47.85361872923358], [-2.8719559380291044, 46.865637260938634], [-4.312398603410253, 46.85818510451771], [-4.337121116089946, 47.8459059875105]]]}, 'links': [{'rel': 'self', 'href': 'https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a/items/S2A_30TVT_20221112_0_L2A'}, {'rel': 'canonical', 'href': 's3://sentinel-cogs/sentinel-s2-l2a-cogs/30/T/VT/2022/11/S2A_30TVT_20221112_0_L2A/S2A_30TVT_20221112_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_30TVT_20221112_0_L1C', 'type': 'application/geo+json'}, {'rel': 'parent', 'href': 'https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a'}, {'rel': 'collection', 'href': 'https://earth-search.aws.element84.com/v1/collections/sentinel-2-l2a'}, {'rel': 'root', 'href': 'https://earth-search.aws.element84.com/v1/'}], 'assets': {'aot': {'href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -60, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -60, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/S2A_30TVT_20221112_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/30/T/VT/2022/11/S2A_30TVT_20221112_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/30/T/VT/2022/11/S2A_30TVT_20221112_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, 399960, 0, -10, 5300040], 'roles': ['visual']}, 'wvp': {'href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/30/T/VT/2022/11/S2A_30TVT_20221112_0_L2A/WVP.tif', 'type': 'image/tiff; application=geotiff; profile=cloud-optimized', 'title': 'Water vapour (WVP)', 'proj:shape': [5490, 5490], 'proj:transform': [20, 0, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/0/AOT.jp2', 'type': 'image/jp2', 'title': 'Aerosol optical thickness (AOT)', 'proj:shape': [5490, 5490], 'proj:transform': [20, 0, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -60, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -60, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -10, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/0/SCL.jp2', 'type': 'image/jp2', 'title': 'Scene classification map (SCL)', 'proj:shape': [5490, 5490], 'proj:transform': [20, 0, 399960, 0, -20, 5300040], 'raster:bands': [{'nodata': 0, 'data_type': 'uint8', 'spatial_resolution': 20}], 'roles': ['data', 'reflectance']}, 'swir16-jp2': {'href': 's3://sentinel-s2-l2a/tiles/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -20, 5300040], '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/30/T/VT/2022/11/12/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, 399960, 0, -10, 5300040], 'roles': ['visual']}, 'wvp-jp2': {'href': 's3://sentinel-s2-l2a/tiles/30/T/VT/2022/11/12/0/WVP.jp2', 'type': 'image/jp2', 'title': 'Water vapour (WVP)', 'proj:shape': [5490, 5490], 'proj:transform': [20, 0, 399960, 0, -20, 5300040], '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': [-4.337121116089946, 46.85818510451771, -2.86954302848021, 47.85361872923358], 'stac_extensions': ['https://stac-extensions.github.io/grid/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/projection/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'}
for it, asset in item["assets"].items():
print("Name:", it, "| Format:", asset["type"])
Name: aot | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: blue | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: coastal | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: granule_metadata | Format: application/xml Name: green | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: nir | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: nir08 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: nir09 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: red | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: rededge1 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: rededge2 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: rededge3 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: scl | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: swir16 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: swir22 | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: thumbnail | Format: image/jpeg Name: tileinfo_metadata | Format: application/json Name: visual | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: wvp | Format: image/tiff; application=geotiff; profile=cloud-optimized Name: aot-jp2 | Format: image/jp2 Name: blue-jp2 | Format: image/jp2 Name: coastal-jp2 | Format: image/jp2 Name: green-jp2 | Format: image/jp2 Name: nir-jp2 | Format: image/jp2 Name: nir08-jp2 | Format: image/jp2 Name: nir09-jp2 | Format: image/jp2 Name: red-jp2 | Format: image/jp2 Name: rededge1-jp2 | Format: image/jp2 Name: rededge2-jp2 | Format: image/jp2 Name: rededge3-jp2 | Format: image/jp2 Name: scl-jp2 | Format: image/jp2 Name: swir16-jp2 | Format: image/jp2 Name: swir22-jp2 | Format: image/jp2 Name: visual-jp2 | Format: image/jp2 Name: wvp-jp2 | Format: image/jp2
bounds = featureBounds(item)
m = Map(
tiles="OpenStreetMap",
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=8
)
geo_json = GeoJson(data=item)
geo_json.add_to(m)
m
# Get Tile URL
r = httpx.get(
f"{titiler_endpoint}/stac/info",
params = (
("url", stac_item),
# Get info for multiple assets
("assets","visual"), ("assets","red"), ("assets","blue"), ("assets","green"),
)
).json()
print(r)
{'visual': {'bounds': [-4.337134709547373, 46.85817595750231, -2.869529638083867, 47.85370180403547], 'minzoom': 7, 'maxzoom': 13, 'band_metadata': [['b1', {}], ['b2', {}], ['b3', {}]], 'band_descriptions': [['b1', ''], ['b2', ''], ['b3', '']], 'dtype': 'uint8', 'nodata_type': 'Nodata', 'colorinterp': ['red', 'green', 'blue'], 'height': 10980, 'driver': 'GTiff', 'overviews': [2, 4, 8, 16], 'count': 3, 'width': 10980, 'nodata_value': 0.0}, 'red': {'bounds': [-4.337134709547373, 46.85817595750231, -2.869529638083867, 47.85370180403547], 'minzoom': 7, 'maxzoom': 13, 'band_metadata': [['b1', {}]], 'band_descriptions': [['b1', '']], 'dtype': 'uint16', 'nodata_type': 'Nodata', 'colorinterp': ['gray'], 'height': 10980, 'driver': 'GTiff', 'overviews': [2, 4, 8, 16], 'count': 1, 'width': 10980, 'nodata_value': 0.0}, 'blue': {'bounds': [-4.337134709547373, 46.85817595750231, -2.869529638083867, 47.85370180403547], 'minzoom': 7, 'maxzoom': 13, 'band_metadata': [['b1', {}]], 'band_descriptions': [['b1', '']], 'dtype': 'uint16', 'nodata_type': 'Nodata', 'colorinterp': ['gray'], 'height': 10980, 'driver': 'GTiff', 'overviews': [2, 4, 8, 16], 'count': 1, 'width': 10980, 'nodata_value': 0.0}, 'green': {'bounds': [-4.337134709547373, 46.85817595750231, -2.869529638083867, 47.85370180403547], 'minzoom': 7, 'maxzoom': 13, 'band_metadata': [['b1', {}]], 'band_descriptions': [['b1', '']], 'dtype': 'uint16', 'nodata_type': 'Nodata', 'colorinterp': ['gray'], 'height': 10980, 'driver': 'GTiff', 'overviews': [2, 4, 8, 16], 'count': 1, 'width': 10980, 'nodata_value': 0.0}}
Display one asset¶
r = httpx.get(
f"{titiler_endpoint}/stac/tilejson.json",
params = {
"url": stac_item,
"assets": "visual",
"minzoom": 8, # By default titiler will use 0
"maxzoom": 14, # By default titiler will use 24
}
).json()
m = Map(
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=10
)
tiles = TileLayer(
tiles=r["tiles"][0],
min_zoom=r["minzoom"],
max_zoom=r["maxzoom"],
opacity=1,
attr="ESA"
)
tiles.add_to(m)
m
Select Indexes for assets¶
# Get Tile URL
r = httpx.get(
f"{titiler_endpoint}/stac/tilejson.json",
params = {
"url": stac_item,
"assets": "visual",
"asset_bidx": "visual|3,1,2",
"minzoom": 8, # By default titiler will use 0
"maxzoom": 14, # By default titiler will use 24
}
).json()
m = Map(
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=12
)
tiles = TileLayer(
tiles=r["tiles"][0],
min_zoom=r["minzoom"],
max_zoom=r["maxzoom"],
opacity=1,
attr="ESA"
)
tiles.add_to(m)
m
# Get Tile URL
r = httpx.get(
f"{titiler_endpoint}/stac/tilejson.json",
params = (
("url", stac_item),
("assets", "red"),
("assets", "green"),
("assets", "blue"),
# Most of the Sentinel L2A Assets have only one band
# So we don't have to pass the bidx
# ("assets_bidx", "red|1"),
# ("assets_bidx", "green|1"),
# ("assets_bidx", "blue|"),
("minzoom", 8),
("maxzoom", 14),
("rescale", "0,2000"),
)
).json()
m = Map(
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=11
)
tiles = TileLayer(
tiles=r["tiles"][0],
min_zoom=r["minzoom"],
max_zoom=r["maxzoom"],
opacity=1,
attr="ESA"
)
tiles.add_to(m)
m
Apply Expression between assets
# Get Tile URL
r = httpx.get(
f"{titiler_endpoint}/stac/tilejson.json",
params = (
("url", stac_item),
("expression", "(nir-red)/(nir+red)"), # NDVI
# We need to tell rio-tiler that each asset is a Band
# (so it will select the first band within each asset automatically)
("asset_as_band", True),
("rescale", "-1,1"),
("minzoom", 8),
("maxzoom", 14),
("colormap_name", "viridis"),
)
).json()
m = Map(
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=10
)
tiles = TileLayer(
tiles=r["tiles"][0],
min_zoom=r["minzoom"],
max_zoom=r["maxzoom"],
opacity=1,
attr="ESA"
)
tiles.add_to(m)
m
# Get Tile URL
r = httpx.get(
f"{titiler_endpoint}/stac/tilejson.json",
params = (
("url", stac_item),
# if you don't use `asset_as_band=True` option you need to pass the band indexes within the expression
("expression", "(nir_b1-red_b1)/(nir_b1+red_b1)"), # NDVI
("rescale", "-1,1"),
("minzoom", 8),
("maxzoom", 14),
("colormap_name", "viridis"),
)
).json()
m = Map(
location=((bounds[1] + bounds[3]) / 2,(bounds[0] + bounds[2]) / 2),
zoom_start=10
)
tiles = TileLayer(
tiles=r["tiles"][0],
min_zoom=r["minzoom"],
max_zoom=r["maxzoom"],
opacity=1,
attr="ESA"
)
tiles.add_to(m)
m