Téléchargement et diffusion de données à l’aide des métadonnées STAC
Produits utilisés : s2_l2a
Mots-clés données utilisées; s2_l2adonnées utilisées; Sentinel-2
Aperçu
Digital Earth Africa stocke une gamme de produits de données sur le Simple Cloud Storage (S3) d’Amazon Web Service avec un accès public gratuit. Ces produits peuvent être consultés sur l’explorateur Sandbox interactif. Pour faciliter la recherche de données dans les archives de Digital Earth Africa, l’explorateur Sandbox fournit également un point de terminaison STAC (SpatioTemporal Asset Catalog) pour répertorier ou rechercher des métadonnées (https://explorer.digitalearth.africa/stac).
STAC est une spécification récemment développée qui fournit un langage commun pour décrire les informations géospatiales afin qu’elles puissent être indexées et découvertes plus facilement. Les métadonnées STAC de DEA peuvent être utilisées pour identifier rapidement toutes les données disponibles pour un produit, un emplacement ou une période donnée. Ces informations peuvent ensuite être utilisées pour télécharger efficacement des données du cloud sur un disque local ou pour diffuser des données directement dans un logiciel SIG de bureau comme QGIS <https://qgis.org/en/site/>`__.
Description
Ce carnet fournit une brève introduction à l’accès et à l’utilisation des métadonnées STAC de Digital Earth Africa :
Comment construire un appel d’API de métadonnées STAC
Comment rechercher des métadonnées STAC et charger les résultats dans Python
Comment inspecter et tracer les éléments STAC uniques contenus dans les métadonnées
Comment inspecter les actifs contenus dans un article STAC
Comment télécharger des données à l’aide des métadonnées STAC
Comment diffuser des données dans Python et QGIS à l’aide des métadonnées STAC (sans les télécharger au préalable)
Commencer
Pour exécuter cette analyse, exécutez toutes les cellules du bloc-notes, en commençant par la cellule « Charger les packages ».
Charger des paquets
Importez les packages Python utilisés pour l’analyse.
[1]:
# Force GeoPandas to use Shapely instead of PyGEOS
# In a future release, GeoPandas will switch to using Shapely by default.
import os
os.environ['USE_PYGEOS'] = '0'
import datacube
import urllib.request, json
import geopandas as gpd
import rioxarray
import odc.aws
from pprint import pprint
from datacube.testutils.io import rio_slurp_xarray
Se connecter au datacube
[2]:
dc = datacube.Datacube(app='Downloading_data_with_STAC')
Recherche de métadonnées STAC
Construire l’appel API STAC
Nous devons d’abord définir certains paramètres d’analyse qui seront utilisés pour rechercher des métadonnées. Cela inclut « product », qui est le même nom de produit utilisé pour charger les données directement à l’aide de « dc.load » (voir « Introduction au chargement des données <../Beginners_guide/03_Loading_data.ipynb> »). Dans cet exemple, nous choisirons une petite zone sur Madagascar.
Pour une liste complète des produits disponibles, parcourez le DE Africa Sandbox Explorer.
[3]:
product = 's2_l2a'
start_time = '2020-01-01'
end_time = '2020-01-31'
bbox = [45.0,-20.1, 47.0, -19.8]
Nous pouvons maintenant combiner les paramètres ci-dessus pour créer une URL qui sera utilisée pour interroger les métadonnées STAC de Digital Earth Africa. Ces métadonnées peuvent être prévisualisées dans un autre onglet en cliquant sur l’URL.
[4]:
root_url = 'https://explorer.digitalearth.africa/stac'
stac_url = f'{root_url}/search?collection={product}&time={start_time}/{end_time}&bbox={str(bbox).replace(" ", "")}&limit=6'
print(stac_url)
https://explorer.digitalearth.africa/stac/search?collection=s2_l2a&time=2020-01-01/2020-01-31&bbox=[45.0,-20.1,47.0,-19.8]&limit=6
Charger les métadonnées STAC
Nous pouvons maintenant charger les métadonnées de l’URL ci-dessus dans Python. Les métadonnées STAC sont stockées au format JSON, que nous pouvons lire dans des dictionnaires Python imbriqués à l’aide du module Python json
.
[5]:
with urllib.request.urlopen(stac_url) as url:
data = json.loads(url.read().decode())
pprint(data, depth=1)
{'context': {...},
'features': [...],
'links': [...],
'numberMatched': 72,
'numberReturned': 6,
'stac_version': '1.0.0',
'type': 'FeatureCollection'}
Inspection des éléments STAC
Dans la sortie ci-dessus, la valeur « numberReturned » indique que notre recherche a renvoyé six résultats uniques. Ces résultats sont connus sous le nom d’éléments STAC <https://stacspec.org/core.html>`__. Il s’agit d’une collection atomique de données et de métadonnées indissociables, comme un ensemble de données satellite unique.
Les données de chaque élément STAC sont contenues dans la liste des « fonctionnalités » des métadonnées :
[6]:
pprint(data['features'], depth=2)
[{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': '7202d52a-0f63-5caa-b6c9-76b6c81cc5ed',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'},
{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': '55c9f67a-85c9-5bd0-a643-e79803ec5f37',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'},
{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': '57b95ad3-ef6f-5292-b679-2132d6839611',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'},
{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': 'b72d17d3-0662-5628-a71c-6203543c897e',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'},
{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': 'af3d247a-f5ce-5489-858b-8eb6ab21b6d4',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'},
{'assets': {...},
'bbox': [...],
'collection': 's2_l2a',
'geometry': {...},
'id': '9dc01d64-d562-5ded-ab77-8d37b7ebceb9',
'links': [...],
'properties': {...},
'stac_extensions': [...],
'stac_version': '1.0.0',
'type': 'Feature'}]
Les « fonctionnalités » de STAC sont stockées sous le format « GeoJSON <https://geojson.org/> », un format de fichier largement utilisé pour stocker des données vectorielles géospatiales. Cela signifie que nous pouvons facilement le convertir en objet spatial à l’aide du module Python « geopandas ». Cela nous permet de tracer et d’inspecter les étendues spatiales de nos données :
[7]:
# Convert features to a GeoDataFrame
gdf = gpd.GeoDataFrame.from_features(data['features'])
# Plot the footprints of each dataset
gdf.plot(alpha=0.8, edgecolor='black')
[7]:
<Axes: >
Si nous imprimons le GeoDataFrame lui-même, nous pouvons voir qu’il contient des champs de métadonnées utiles qui fournissent des informations sur chaque ensemble de données :
[8]:
gdf.head(1)
[8]:
geometry | title | gsd | created | updated | proj:epsg | platform | view:off_nadir | data_coverage | instruments | ... | sentinel:utm_zone | sentinel:product_id | sentinel:grid_square | sentinel:data_coverage | sentinel:latitude_band | sentinel:valid_cloud_cover | proj:shape | proj:transform | datetime | cubedash:region_code | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | POLYGON ((46.91100 -19.97450, 46.89992 -19.028... | S2B_MSIL2A_20200101T070219_N0213_R120_T38KQD_2... | 10 | 2020-08-19T00:49:03.181000Z | 2020-08-19T00:49:03.181Z | 32738 | sentinel-2b | 0 | 99.97 | [msi] | ... | 38 | S2B_MSIL2A_20200101T070219_N0213_R120_T38KQD_2... | QD | 99.97 | K | True | [10980, 10980] | [10.0, 0.0, 699960.0, 0.0, -10.0, 7900000.0, 0... | 2020-01-01T07:05:01Z | 38KQD |
1 rows × 25 columns
Nous pouvons utiliser cela pour en savoir plus sur nos données. Par exemple, nous pouvons tracer nos ensembles de données en utilisant le champ « eo:cloud_cover » pour afficher le pourcentage de chaque ensemble de données qui a été masqué par les nuages (jaune = couverture nuageuse élevée) :
[9]:
# Colour features by cloud cover
gdf.plot(column='eo:cloud_cover',
cmap='viridis',
alpha=0.8,
edgecolor='black',
legend=True)
[9]:
<Axes: >
Inspection des actifs
Chaque élément STAC répertorié dans « Fonctionnalités » peut contenir plusieurs « actifs ». Ces actifs représentent des fichiers ou des couches de données uniques, par exemple des bandes de télédétection individuelles. Pour les produits Sentinel-2 de Digital Earth Africa, ceux-ci peuvent inclure les bandes, les métadonnées, etc.
[10]:
stac_item = data['features'][0]
pprint(stac_item['assets'], depth=1)
{'AOT': {...},
'B01': {...},
'B02': {...},
'B03': {...},
'B04': {...},
'B05': {...},
'B06': {...},
'B07': {...},
'B08': {...},
'B09': {...},
'B11': {...},
'B12': {...},
'B8A': {...},
'SCL': {...},
'WVP': {...},
'info': {...},
'metadata': {...},
'overview': {...},
'thumbnail': {...},
'visual': {...}}
Il est important de noter que chaque ressource (par exemple, « B05 ») fournit une URL unique (« href ») qui peut être utilisée pour accéder aux données ou les télécharger. Dans ce cas, le préfixe « s3:// » indique que nos données sont stockées dans le cloud sur Amazon S3.
[11]:
pprint(stac_item['assets']['B05'])
{'eo:bands': [{'name': 'B05'}],
'href': 's3://deafrica-sentinel-2/sentinel-s2-l2a-cogs/38/K/QD/2020/1/S2B_38KQD_20200101_0_L2A/B05.tif',
'proj:epsg': 32738,
'proj:shape': [5490, 5490],
'proj:transform': [20.0, 0.0, 699960.0, 0.0, -20.0, 7900000.0, 0.0, 0.0, 1.0],
'roles': ['data'],
'title': 'B05',
'type': 'image/tiff; application=geotiff; profile=cloud-optimized'}
Téléchargement de fichiers à l’aide de STAC
Maintenant que nous avons une URL, nous pouvons l’utiliser pour télécharger des données sur notre disque local. Par exemple, nous pouvons vouloir télécharger des données pour la bande satellite « B05 » dans notre élément STAC. Nous pouvons le faire en utilisant la fonction « s3_download » de « odc.aws » :
[12]:
# Get URL then download
url = stac_item['assets']['B05']['href']
odc.aws.s3_download(url)
[12]:
'B05.tif'
Pour vérifier que ce fichier a été téléchargé correctement, nous pouvons le charger dans notre notebook en tant que « xarray.Dataset() » en utilisant « rioxarray.open_rasterio » :
[13]:
# Load data as an xarray.Dataset()
downloaded_ds = rioxarray.open_rasterio('B05.tif')
# Plot a small subset of the data
downloaded_ds.isel(x=slice(2000, 3000), y=slice(2000, 3000)).plot(robust=True)
[13]:
<matplotlib.collections.QuadMesh at 0x7f75379de5c0>
Remarque : si ce bloc-notes est exécuté sur le bac à sable DE Africa, le fichier enregistré apparaîtra dans le répertoire « Frequently_used_code » du navigateur de fichiers JupyterLab. Pour l’enregistrer sur votre ordinateur local, faites un clic droit sur le fichier et cliquez sur « Télécharger ».
Téléchargement de plusieurs fichiers
Pour télécharger les données de la bande « B05 » pour chacun des six éléments STAC renvoyés par notre recherche :
# Get list of all URLs for the 'B05' band
asset = 'B05'
urls = [stac_item['assets'][asset]['href'] for stac_item in data['features']]
# Download each URL
for url in urls:
print(url)
odc.aws.s3_download(url)
Pour télécharger toutes les bandes disponibles (c’est-à-dire les « ressources ») pour un seul élément STAC :
# Get list of all URLs for all assets in the first STAC Item
stac_item = data['features'][0]
urls = [asset['href'] for asset in stac_item['assets'].values()]
# Download each URL
for url in urls:
print(url)
odc.aws.s3_download(url)
Diffusion de données en continu sans téléchargement
En raison de la taille croissante des jeux de données satellite, le téléchargement des données directement sur votre propre disque local peut prendre du temps et être lent. Parfois, il est préférable de diffuser les données directement depuis le cloud sans les télécharger au préalable. Cela peut être particulièrement efficace pour les données stockées au format Cloud Optimised GeoTIFF (COG) qui est optimisé pour diffuser efficacement de petits morceaux d’une image à la fois.
Cette section montre comment les données peuvent être diffusées directement depuis le cloud vers Python et le logiciel SIG QGIS (v3.14) <https://qgis.org/en/site/>`__. Dans un premier temps, nous devons convertir notre URL Amazon S3 (par exemple s3://
) au format HTTPS (par exemple https://
) afin qu’elle puisse être lue plus facilement :
[14]:
# Get URL
url = stac_item['assets']['B05']['href']
# Get https URL
bucket, key = odc.aws.s3_url_parse(url)
https_url = f'https://deafrica-sentinel-2.s3.af-south-1.amazonaws.com/{key}'
https_url
[14]:
'https://deafrica-sentinel-2.s3.af-south-1.amazonaws.com/sentinel-s2-l2a-cogs/38/K/QD/2020/1/S2B_38KQD_20200101_0_L2A/B05.tif'
Diffusion de données en Python
Pour diffuser des données directement depuis le cloud dans un format « xarray.Dataset() » afin qu’elles puissent être analysées en Python, nous pouvons fournir l’URL HTTPS ci-dessus directement à la fonction « rioxarray.open_rasterio » :
[15]:
# Load data as an xarray.Dataset()
streamed_ds = rioxarray.open_rasterio(https_url)
# Plot a small subset of the data
streamed_ds.isel(x=slice(2000, 3000), y=slice(2000, 3000)).plot(robust=True)
[15]:
<matplotlib.collections.QuadMesh at 0x7f75349a4fa0>
Diffusion et reprojection de données
Le code ci-dessus diffusera l’ensemble de données du cloud dans un « xarray.Dataset() ». Parfois, cependant, nous pouvons vouloir diffuser uniquement une partie d’un grand ensemble de données dans une grille spatiale (par exemple, la résolution et le système de référence de coordonnées) qui correspond exactement aux données que nous avons déjà chargées à l’aide de Datacube.
Par exemple, nous avons peut-être déjà utilisé « dc.load » pour charger des exemples de données du datacube dans la projection conique à aire égale d’Albers en Afrique et une résolution de pixels de 5 000 m :
[16]:
# Load data from datacube
ds = dc.load(product='s2_l2a',
time=('2020-01-01', '2020-01-31'),
x=(46.8, 48.0),
y=(-19.8, -19.4),
resolution=(-5000, 5000),
output_crs='epsg:6933',
dask_chunks={})
ds
[16]:
<xarray.Dataset> Dimensions: (time: 33, y: 11, x: 24) Coordinates: * time (time) datetime64[ns] 2020-01-01T07:04:57 ... 2020-01-31T07:... * y (y) float64 -2.428e+06 -2.432e+06 ... -2.472e+06 -2.478e+06 * x (x) float64 4.518e+06 4.522e+06 ... 4.628e+06 4.632e+06 spatial_ref int32 6933 Data variables: (12/15) B01 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B02 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B03 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B04 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B05 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B06 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> ... ... B09 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B11 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> B12 (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> SCL (time, y, x) uint8 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> AOT (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> WVP (time, y, x) uint16 dask.array<chunksize=(1, 11, 24), meta=np.ndarray> Attributes: crs: epsg:6933 grid_mapping: spatial_ref
Nous pouvons maintenant utiliser la fonction « rio_slurp_xarray » pour diffuser les données que nous avons identifiées à l’aide de STAC dans un format cohérent avec les données « ds » que nous avons chargées à l’aide du Datacube. Notez que « gbox=ds.geobox » indique à la fonction de charger les données pour qu’elles correspondent aux caractéristiques de « ds ». La sortie devrait donc apparaître beaucoup plus pixelisée que les tracés précédents :
[17]:
# Load data as an xarray.Dataset()
streamed_ds = rio_slurp_xarray(https_url, gbox=ds.geobox)
# Verify that data contains an Open Data Cube geobox
streamed_ds.plot(robust=True)
[17]:
<matplotlib.collections.QuadMesh at 0x7f7537e423e0>
[18]:
ds.geobox == streamed_ds.geobox
[18]:
True
Remarque : pour plus d’informations sur la reprojection des données, consultez le bloc-notes « Reprojection des données de cube de données et de raster <Reprojecting_data.ipynb> ».
Diffusion de données dans QGIS
Pour diffuser des données directement dans un logiciel SIG comme QGIS sans avoir à les télécharger, sélectionnez d’abord et copiez l’URL HTTPS ci-dessus (par exemple 'https://dea-public-data...
) dans notre presse-papiers, puis ouvrez QGIS. Dans QGIS, cliquez sur Couche > Ajouter une couche > Ajouter une couche raster
:
Dans la boîte de dialogue « Gestionnaire de sources de données | Raster », cliquez sur « Protocole : HTTP(S), cloud, etc. ». Assurez-vous que « Type » est défini sur « HTTP/HTTPS/FTP » et collez l’URL que vous avez copiée dans la zone « URI » :
Cliquez sur « Ajouter », puis sur « Fermer ». Après quelques instants, l’image que nous avons identifiée à l’aide de STAC apparaîtra sur la carte. Ces données sont diffusées directement depuis le cloud ; aucun téléchargement n’est requis !
Informations Complémentaires
Licence : Le code de ce carnet est sous licence Apache, version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>. Les données de Digital Earth Africa sont sous licence Creative Commons par attribution 4.0 <https://creativecommons.org/licenses/by/4.0/>.
Contact : Si vous avez besoin d’aide, veuillez poster une question sur le canal Slack Open Data Cube <http://slack.opendatacube.org/>`__ ou sur le GIS Stack Exchange en utilisant la balise open-data-cube
(vous pouvez consulter les questions posées précédemment ici). Si vous souhaitez signaler un problème avec ce bloc-notes, vous pouvez en déposer un sur Github.
Version de Datacube compatible :
[19]:
print(datacube.__version__)
1.8.15
Dernier test :
[20]:
from datetime import datetime
datetime.today().strftime('%Y-%m-%d')
[20]:
'2023-08-14'