Température de surface terrestre Sentinel-3 SLSTR#

Mots-clés data used; sentinel-3,:index:datasets; sentinel-3

Aperçu#

Le produit de température de surface terrestre (LST) de niveau 2 Sentinel-3 SLSTR contient des données dérivées de l’instrument radiomètre de température de surface terrestre et marine (SLSTR). Les données sont disponibles à une résolution d’environ 1 km avec une fréquence de revisite d’environ un jour en combinant les deux satellites, ce qui les rend précieuses pour un large éventail d’applications, notamment :

  • Surveillance climatique

  • Planification et suivi du développement urbain

  • Surveillance de la santé et du stress de la végétation

  • Estimation de l’évapotranspiration

De plus amples informations sur le produit LST de niveau 2 Sentinel-3 SLSTR sont disponibles sur SentiWiki et dans le manuel de l’utilisateur des terres Sentinel-3 SLSTR. ***

Description#

Ce cahier couvrira les sujets suivants :

  1. Inspection des produits et des mesures disponibles dans le datacube

  2. Chargement des données Sentinel-3 SLSTR.

  3. Comprendre et appliquer le masque de bits.

  4. Tracer les résultats

  5. Conversion de Kelvin en Celsius


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]:
%matplotlib inline

import datacube
import geopandas as gpd
from odc.geo.geom import Geometry

from deafrica_tools.plotting import display_map
from datacube.utils import masking
from deafrica_tools.areaofinterest import define_area

Se connecter au datacube#

Connectez-vous au datacube pour que nous puissions accéder aux données de DE Africa.

[2]:
dc = datacube.Datacube(app="Sentinel_3")

Liste des produits#

Nous pouvons utiliser la fonctionnalité list_products du datacube pour inspecter les produits de DE Africa disponibles. Le tableau ci-dessous montre les noms de produits que nous utiliserons pour charger les données, une brève description des données et l’instrument satellite qui a acquis les données.

[3]:
dc.list_products().loc[dc.list_products()['description'].str.contains('Sentinel-3')]
[3]:
name description license default_crs default_resolution
name
s3_ol_2_wfr_nrt s3_ol_2_wfr_nrt Sentinel-3 Level 2 Water Full Resolution (WFR)... CC-BY-4.0 EPSG:4326 Resolution(x=0.003, y=-0.003)
s3_olci_l2_lfr s3_olci_l2_lfr Sentinel-3 OLCI L2 LAND CC-BY-4.0 EPSG:4326 Resolution(x=0.003, y=-0.003)
s3_olci_l2_wfr s3_olci_l2_wfr Sentinel-3 OLCI L2 WATER CC-BY-4.0 EPSG:4326 Resolution(x=0.003, y=-0.003)
s3_slstr_l2_lst s3_slstr_l2_lst Sentinel-3 LST CC-BY-4.0 EPSG:4326 Resolution(x=0.003, y=-0.003)
s3_syn_2_vg1 s3_syn_2_vg1 Sentinel-3 Level-2 VG1 SYN product CC-BY-4.0 EPSG:4326 Resolution(x=0.01, y=-0.01)

Veuillez choisir le produit en spécifiant son nom, avec le produit s3_slstr_l2_lst

[4]:
product = "s3_slstr_l2_lst"

Liste des mesures#

Nous pouvons inspecter davantage les données disponibles pour le produit terrestre Sentinel-3 s3_slstr_l2_lst en utilisant la fonctionnalité list_measurements de datacube. Le tableau ci-dessous répertorie chacune des mesures disponibles dans les données.

[5]:
measurements = dc.list_measurements()
measurements.loc[product]
[5]:
name dtype units nodata aliases flags_definition add_offset scale_factor
measurement
LST LST uint16 K 65535.0 [Land_surface_temperature] NaN 0.0 0.0100
LST_uncertainty LST_uncertainty uint16 K 65535.0 [Land_surface_temperature_uncertainty] NaN 0.0 0.0100
NDVI NDVI int16 1 32767.0 NaN NaN 0.0 0.0001
CONFIDENCE CONFIDENCE uint16 1 65535.0 [mask] {'day': {'bits': 10, 'values': {'0': False, '1... NaN NaN

Le produit terrestre Sentinel-3 comporte quatre mesures :

Mesure

Description

Application

LST (Température de surface terrestre)

Température de surface terrestre exprimée en degrés Kelvin.

De nombreuses applications dans la surveillance climatique, les évaluations de la couverture et de l’utilisation des terres, la détection des changements et la modélisation biophysique.

LST_uncertainty (Incertitude de la température de surface terrestre)

L’incertitude type totale de la mesure LST, exprimée en Kelvin.

Contrôle qualité et support pour l’estimation de l’incertitude en aval dans les flux de travail de modélisation.

NDVI (Indice de végétation par différence normalisée)

Mesure sans unité de la verdure et de la densité de la végétation.

Détection du stress des cultures, études du fonctionnement de la canopée, surveillance de la dynamique de la biomasse.

CONFIDENCE (CONFIANCE)

Couche de masque de bits signalant diverses conditions de pixels telles que les nuages et les reflets solaires.

Contrôle qualité et masquage.


Paramètres d’analyse#

La cellule suivante définit les paramètres qui définissent la zone d’intérêt sur laquelle effectuer l’analyse. #### Sélectionner l’emplacement Pour définir la zone d’intérêt, deux méthodes sont disponibles :

  1. En spécifiant la latitude, la longitude et la zone tampon, ou en séparant les zones tampons de latitude et de longitude, cette méthode vous permet de définir une zone d’intérêt autour d’un point central. Vous pouvez saisir la latitude centrale, la longitude centrale et une valeur de zone tampon en degrés pour créer une zone carrée autour du point central. Par exemple, « lat = 10.338 », « lon = -1.055 » et « buffer = 0.1 » sélectionneront une zone avec un rayon de 0,1 degré carré autour du point avec les coordonnées « (10.338, -1.055) ».

    Vous pouvez également fournir des valeurs de tampon distinctes pour la latitude et la longitude d’une zone rectangulaire. Par exemple, « lat = 10.338 », « lon = -1.055 » et « lat_buffer = 0.1 » et « lon_buffer = 0.08 » sélectionneront une zone rectangulaire s’étendant sur 0,1 degré au nord et au sud et 0,08 degré à l’est et à l’ouest à partir du point « (10.338, -1.055) ».

    Pour des temps de chargement raisonnables, définissez la mémoire tampon sur « 0,1 » ou moins.

  2. By uploading a polygon as a GeoJSON or Esri Shapefile. If you choose this option, you will need to upload the geojson or ESRI shapefile into the Sandbox using Upload Files button ee916b2978d1446d8e5bd488a1152224 in the top left corner of the Jupyter Notebook interface. ESRI shapefiles must be uploaded with all the related files (.cpg, .dbf, .shp, .shx). Once uploaded, you can use the shapefile or geojson to define the area of interest. Remember to update the code to call the file you have uploaded.

Pour utiliser l’une de ces méthodes, vous pouvez décommenter la ligne de code concernée et commenter l’autre. Pour commenter une ligne, ajoutez le symbole "#" avant le code que vous souhaitez commenter. Par défaut, la première option qui définit l’emplacement à l’aide de la latitude, de la longitude et du tampon est utilisée.

Si vous exécutez le notebook pour la première fois, conservez les paramètres par défaut ci-dessous. Cela démontrera le fonctionnement de l’analyse et fournira des résultats significatifs. L’exemple couvre le delta du fleuve Zambèze au Mozambique. Cette zone comprend des terres et des océans pour démontrer le masquage des océans, et connaît également une certaine couverture nuageuse. Il existe une certaine variation topographique dans la zone d’intérêt qui peut produire une variabilité de la température de surface terrestre.

Pour exécuter le notebook pour une zone différente, assurez-vous que les données Sentinel-3 OLCI Land sont disponibles pour la zone choisie à l’aide de DEAfrica Explorer.

[6]:
# Method 1: Specify the latitude, longitude, and buffer)
aoi = define_area(lat=-18.7, lon=36.4, buffer=0.9)

# Method 2: Use a polygon as a GeoJSON or Esri Shapefile.
# aoi = define_area(vector_path='aoi.shp')

#Create a geopolygon and geodataframe of the area of interest
geopolygon = Geometry(aoi["features"][0]["geometry"], crs="epsg:4326")
geopolygon_gdf = gpd.GeoDataFrame(geometry=[geopolygon], crs=geopolygon.crs)

# Get the latitude and longitude range of the geopolygon
lat_range = (geopolygon_gdf.total_bounds[1], geopolygon_gdf.total_bounds[3])
lon_range = (geopolygon_gdf.total_bounds[0], geopolygon_gdf.total_bounds[2])
[7]:
display_map(x=lon_range, y=lat_range)
[7]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Charger le jeu de données Sentinel-3 à l’aide de dc.load()#

Maintenant que nous savons quels produits et mesures sont disponibles pour le produit, nous pouvons charger des données à partir du datacube en utilisant dc.load. Nous chargerons des données à partir des bandes satellites spectrales. En spécifiant output_crs='EPSG:4326' et resolution=(-0.01, 0.01), nous interrogeons les données en degrés avec des pixels d’environ 1 km x 1 km, notant que ``EPSG:4326`` n’est pas une projection équivalente. Enfin, group_by='solar_day' garantit que les images superposées prises à quelques secondes d’intervalle lors du passage du satellite sont combinées en une seule étape temporelle dans les données. Nous pouvons voir que la requête renvoie huit étapes temporelles car nous avons interrogé les quinze premiers jours d’avril 2025.

[8]:
query = {
    'x': (lon_range),
    'y': (lat_range),
    'time':('2025-04-01', '2025-04-15'),
    'output_crs': 'EPSG:4326',
    'resolution': (-0.01, 0.01)}

ds_S3 = dc.load(product=product,
                group_by="solar_day",
                **query)

ds_S3
[8]:
<xarray.Dataset> Size: 4MB
Dimensions:          (time: 15, latitude: 180, longitude: 180)
Coordinates:
  * time             (time) datetime64[ns] 120B 2025-04-01T09:45:41.204500 .....
  * latitude         (latitude) float64 1kB -17.8 -17.82 ... -19.59 -19.59
  * longitude        (longitude) float64 1kB 35.51 35.52 35.53 ... 37.29 37.3
    spatial_ref      int32 4B 4326
Data variables:
    LST              (time, latitude, longitude) uint16 972kB 29764 ... 65535
    LST_uncertainty  (time, latitude, longitude) uint16 972kB 45 45 ... 65535
    NDVI             (time, latitude, longitude) int16 972kB 32767 ... 32767
    CONFIDENCE       (time, latitude, longitude) uint16 972kB 8 8 264 ... 258 2
Attributes:
    crs:           EPSG:4326
    grid_mapping:  spatial_ref

⚠️ Note : Certaines bandes terrestres Sentinel-3 SLSTR sont stockées sous forme d’entiers avec un facteur d’échelle (par exemple, 0,01) ou un décalage (par exemple, 100) appliqué. Cette mise à l’échelle est utilisée pour stocker efficacement les valeurs au format entier. Pour obtenir les valeurs de surface correctes, l’échelle ou le décalage doit être appliqué. Les cellules ci-dessous démontrent comment cela est appliqué aux mesures de température en utilisant le facteur d’échelle de 0,01 (visible lorsque les métadonnées sont développées dans le jeu de données ci-dessus).

Ensuite, nous stockons un objet scale_factor pour une utilisation dans des graphiques et des calculs ultérieurs. Le facteur d’échelle est extrait des attributs de la variable LST. Nous devrions obtenir le facteur d’échelle spécifique pour les variables d’incertitude ou NDVI si nous travaillions avec elles.

[9]:
scale_factor_LST = ds_S3['LST'].attrs.get('scale_factor')
scale_factor_LST_unc = ds_S3['LST_uncertainty'].attrs.get('scale_factor')

Comprendre la couche de confiance et le masquage de bits#

Les données LST de Sentinel-3 ne sont disponibles que sur terre (pas sur l’océan) et sont sensibles aux nuages et à d’autres interférences. Dans l’objet xarray ds_S3 ci-dessus, nous pouvons voir plusieurs valeurs 65535 dans la variable LST qui représentent nodata. Nous devons masquer efficacement le jeu de données avant de continuer.

La couche CONFIDENCE utilise un masque de bits pour encoder les indicateurs au niveau des pixels, tels que la présence de nuages ou les reflets solaires, en un seul entier. Le masque de bits fait référence aux chiffres binaires, où la position du chiffre dans une série est liée à un indicateur particulier. Dans la couche CONFIDENCE, les indicateurs sont marqués comme vrais ou faux avec des 1 et des 0 à des endroits spécifiques dans un entier. En regardant le tableau ci-dessous, un 1 à l’emplacement de bit 1 (notant l’indexation 0 et la lecture de gauche à droite, cela serait -1-------...) indiquerait que le pixel est au-dessus de l’océan, tandis qu’un 0 à l’emplacement de bit 3 (---0-----...) indiquerait que le pixel n’est pas au-dessus de la terre.

Chaque indicateur actif contribue à une valeur de \(2^{\text{position}}\) à l’entier total. Par exemple, si un pixel était au-dessus de la terre (position 3, valeur \(2^3=8\)), avait des défauts cosmétiques (position 8, valeur \(2^8=256\)), et était nuageux (position 14, valeur \(2^{14}=16384\)), l’entier résultant serait :

\[2^3 + 2^8 + 2^{14} = 16648\]

En regardant la bande CONFIDENCE dans l’objet ds_S3 ci-dessus, il y a quelques valeurs 16648. Nous devons travailler à rebours à partir de cette valeur pour trouver la combinaison unique de positions de bits avec des indicateurs activés. Heureusement, les ordinateurs font cela facilement et nous pouvons utiliser les fonctions de masking de datacube pour nous aider.

Le tableau ci-dessous montre les bits dans le produit LST Sentinel-3.

[10]:
# Display details of available flags
flags = masking.describe_variable_flags(ds_S3.CONFIDENCE)
flags
[10]:
bits values description
day 10 {'0': False, '1': True} Day
land 3 {'0': False, '1': True} Land
snow 13 {'0': False, '1': True} Snow
ocean 1 {'0': False, '1': True} Ocean
tidal 2 {'0': False, '1': True} Tidal
cosmetic 8 {'0': False, '1': True} Cosmetic defect
twilight 11 {'0': False, '1': True} Twilight
unfilled 5 {'0': False, '1': True} Unfilled
coastline 0 {'0': False, '1': True} Coastline
duplicate 9 {'0': False, '1': True} Duplicate
sun_glint 12 {'0': False, '1': True} Sun glint
inland_water 4 {'0': False, '1': True} Inland water
summary_cloud 14 {'0': False, '1': True} Summary cloud
summary_pointing 15 {'0': False, '1': True} Summary pointing

Appliquer le masque#

Ensuite, nous listons les indicateurs que nous voulons masquer dans un dictionnaire et appliquons la fonction make_mask avant de l’implémenter sur notre jeu de données. Dans ce cas, nous avons choisi trois indicateurs : nuage, océan, non rempli. Vous pouvez expérimenter en ajoutant et en supprimant d’autres indicateurs.

[11]:
clear = {"summary_cloud": False, "ocean": False, "unfilled": False}

mask = masking.make_mask(ds_S3.CONFIDENCE, **clear)

ds_S3_masked = ds_S3.where(mask == True)

Tracer la LST et l’incertitude en Kelvin#

Maintenant que nous avons appliqué le masque, nous pouvons tracer la LST et son incertitude associée, toutes deux exprimées en Kelvin. Il est important de noter que nous appliquons le facteur d’échelle dans les commandes de traçage.

Les températures de surface semblent plus élevées le long des côtes et dans les parties basses du delta, et plus fraîches dans la topographie plus élevée au nord-ouest de la zone d’intérêt. Cela est plus évident dans les images des 2 et 14 avril.

Nous pouvons également voir que les valeurs d’incertitude varient entre 0 et 5 Kelvin. Il est intéressant de noter que l’incertitude semble plus élevée au-dessus des eaux de surface (le fleuve Zambèze), en particulier pour les images des 2 et 5 avril.

[12]:
(ds_S3_masked.isel(time=[0,1,7,13]).LST*scale_factor_LST).plot(col='time', cmap = 'inferno')
[12]:
<xarray.plot.facetgrid.FacetGrid at 0x7f10faa11dc0>
../../../_images/sandbox_notebooks_Datasets_Sentinel_3_Land_Surface_Temperature_31_1.png
[13]:
(ds_S3_masked.isel(time=[0,1,7,13]).LST_uncertainty*scale_factor_LST_unc).plot(col='time', cmap = 'inferno')
[13]:
<xarray.plot.facetgrid.FacetGrid at 0x7f10faab7860>
../../../_images/sandbox_notebooks_Datasets_Sentinel_3_Land_Surface_Temperature_32_1.png

Convertir LST en Celsius#

Nous pouvons convertir Kelvin en Celsius en soustrayant 273,15 et tracer le résultat. L’utilisation du Celsius peut être plus parlante pour certains publics, en notant que la LST dans la zone et la période tracées varie entre environ 20 et 33 degrés Celsius, avec des températures plus fraîches observées dans l’image du 5 avril.

[14]:
# convert K to C and assign units as an attribute
ds_S3_masked['LST_C'] = (ds_S3_masked.LST*scale_factor_LST - 273.15).assign_attrs(units = "C")

(ds_S3_masked.isel(time=[0,1,7,13]).LST_C).plot(col='time', cmap = 'inferno')
[14]:
<xarray.plot.facetgrid.FacetGrid at 0x7f10f9d68c20>
../../../_images/sandbox_notebooks_Datasets_Sentinel_3_Land_Surface_Temperature_34_1.png

Conclusion et prochaines étapes#

Ce notebook a fourni une introduction au chargement, au masquage et au traçage de la température de surface terrestre (et de l’incertitude de sa mesure) en utilisant des principes de masquage binaire et en appliquant des facteurs d’échelle. Il pourrait être intéressant d’explorer différents paysages, topographies et saisons.


Informations Complémentaires#

Licence Le code de ce notebook 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 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 DE Africa <https://digitalearthafrica.slack.com/> ou sur le GIS Stack Exchange <https://gis.stackexchange.com/questions/ask?tags=open-data-cube> en utilisant la balise open-data-cube (vous pouvez consulter les questions posées précédemment `ici <https://gis.stackexchange.com/questions/tagged/open-data-

Si vous souhaitez signaler un problème avec ce notebook, vous pouvez en déposer un sur Github.

Version de Datacube compatible

[15]:
print(datacube.__version__)
1.9.13

Dernier test :

[16]:
from datetime import datetime
datetime.today().strftime('%Y-%m-%d')
[16]:
'2026-08-18'