Accueil Tutoriel Installer une software stack météo – Partie 3 – ECCodes et Magics (ECMWF)


Installer une software stack météo – Partie 3 – ECCodes et Magics (ECMWF)


Nous allons nous attarder sur les nombreux outils de l”ECMWF (European Center for Medium-range Weather Forecasts). Dans cet article, nous installerons ECCodes, Magics et Metview, et couvrirons une utilisation basique.

Installation

Les outils de l’ECMWF sont disponibles sous forme de sources, ou de packages conda. Je vous épargnerais la compilation des sources, ce qui serait fastidieux tant le nombre de dépendances est important. Nous nous focaliserons donc sur la méthode conda, qui est recommandée pour plus de simplicité.

Pour ceux souhaiteraient malgré tout installer manuellement à partir des sources, vous avez le choix de compiler ECCodes, Magics et Metview séparément, ou de compiler le Metview Bundle, qui automatise la compilation de tous les modules (recommandé). Lien ci-dessous :

https://confluence.ecmwf.int/display/METV/The+Metview+Source+Bundle

Conda est assez obèse et pose parfois des problèmes de dépendances. Il est souhaitable, mais pas obligatoire, de créer un environnement dédié :

conda create --name ecmwf python anaconda --channel conda-forge
conda activate ecmwf

Ensuite, l’installation est extrêmement basique :

 conda install -c conda-forge metview 

La commande se charge d’installer toutes les dépendances, dont ECCodes et Magics : voilà un moyen simple d’installer tout ce dont nous aurons besoin ! Il nous reste quand même un package à installer, qui dans mon cas s’est avéré manquant malgré tout :

 conda install -c anaconda openblas

Une fois ceci fait, vous êtes paré pour suivre les tutos suivants.

ECCodes

Ce package permet la manipulation de plusieurs formats de données, dont le GRIB et le BUFR, ainsi que des possibilités de conversion vers le format NetCDF. C’est un outil requis pour des outils tels que Magics.

On peut utiliser la commande grib_ls pour connaître le contenu d’un fichier GRIB. Exemple d’utilisation :

Autre commande qui peut être utile, la commande grib_dump qui permet d’extraire le contenu d’un fichier vers un autre format. Il est possible entre autres d’extraire vers du JSON. Attention la commande écrit sur la sortie standard, nous devrons rediriger vers un fichier. Exemple :

grib_dump -j gfs.t06z.pgrb2.0p50.f000 > dump.json

Enfin, il est possible de faire une conversion vers le format NetCDF. Attention, cette commande est assez pointilleuse sur le format d’entrée, il sera probablement nécessaire d’extraire des sous-parties du fichier GRIB avant de retraiter, avec la commande grib_dump par exemple.

grib_to_netcdf -o output.nc grib_file.grb2

Magics

Magics est une librairie de tracé de données météorologiques interfaçable avec Python. Cela permet de générer des cartes et toutes sortes de diagrammes. Si vous voyez des cartes issues de l’ECMWF, il y a de fortes chances qu’elles soient produites avec Magics.

Commençons par extraire le géopotentiel Z500 d’un fichier issu du modèle GFS, que nous avons sous la main.

Voici l’occasion de faire un petit exercice d’utilisation d’ECCodes. Nous allons devoir identifier le champ qui nous intéresse dans le fichier GRIB. Mais la commande par défaut ne nous affiche pas son id… Voici comment modifier l’affichage pour y parvenir :

grib_ls -p count,countTotal,shortName,typeOfLevel,level gfs.t06z.pgrb2.0p50.f003

Nous obtenons un affichage plus sympa qui affiche le champ “count”, correspondant au numéro de champ dans le fichier :

Bon, avouons que cela fait beaucoup de données d’affichées… Essayons de limiter la liste en ajoutant des clauses de sélection :

grib_ls -p count,countTotal,shortName,typeOfLevel,level -w shortName=gh,typeOfLevel=isobaricInhPa,level=500 gfs.t06z.pgrb2.0p50.f003

Voilà, c’est beaucoup plus clair, maintenant on a notre champ gh (pour Géopotential Height) au niveau isobare 500. Il s’agit du champ d’ID 222 :

Maintenant, on ne se prend pas la tête, on prend l’exemple fourni dans la doc de Magics et on adapte notre chargement de fichier (on précise grib_field_position=222). Enregistrez le script ci-après sous le nom magics-test.py :

from Magics.macro import *
 
#Definition of the output formats
formats = output(
    output_formats=['png','ps'],
    output_name='using_python02')
 
#Setting the coordinates of the geographical area
europe = mmap(
    subpage_upper_right_longitude= 65.,
    subpage_map_projection= "polar_stereographic",
    subpage_map_vertical_longitude= 0.,
    subpage_lower_left_longitude= -37.27,
    subpage_lower_left_latitude= 18.51,
    subpage_upper_right_latitude= 51.28)
 
coastlines = mcoast(map_coastline_land_shade= 'on',
    map_coastline_land_shade_colour= 'grey',
    map_coastline_sea_shade= 'on',
    map_coastline_sea_shade_colour= 'white')
 
#Import the z500 data
z500 = mgrib(grib_input_file_name = "gfs.t06z.pgrb2.0p50.f003",
  grib_field_position = 222
)
 
#Define the simple contouring for z500
z500_contour = mcont(
    contour_level_selection_type= "interval",
    contour_line_colour= "black",
    contour_hilo_height= 0.25,
    contour_line_thickness= 1,
    contour_highlight_colour= "red",
    contour_highlight_thickness= 2,
    contour_interval= 50.)
  
#Do the plot
plot(formats, europe, coastlines, z500, z500_contour)

Plus qu’à lancer la commande :

python magics-test.py

Des fichiers sont produits, un postscript, et un au format image PNG que voici :

Exemple de tracé de contours du géopotentiel 500hPa

Exemple plus avancé

Je vous propose maintenant en bonus un exemple plus avancé qui reprend le Z500 en plages colorées et la pression au niveau de la mer, avec la charte couleur du site Météo Blois. On va y voir plusieurs techniques utiles :

  • Mettre à l’échelle les données lorsque l’unité ne vous convient pas. Par exemple, les pressions sont données en pascal, alors qu’en météo on trace plutôt en hectopascal. On le précise au moment de charger le fichier de données.
  • Tracer des plages de couleur avec une charte de couleur personnalisée.
  • Ajouter une légende adaptée
  • Ajouter des titres

Voici l’exemple complet, il suffit de lire les commentaires et le source pour comprendre .

from Magics.macro import *
 
# On souhaite une sortie PNG
formats = output(
    output_formats=['png'],
    output_name='z500_prmsl')
 
# Définition de la projection
europe = mmap(
    subpage_upper_right_longitude= 65.,
    subpage_map_projection= "polar_stereographic",
    subpage_map_vertical_longitude= 0.,
    subpage_lower_left_longitude= -37.27,
    subpage_lower_left_latitude= 18.51,
    subpage_upper_right_latitude= 51.28)

# Ne pas colorier la carte car on va la superposer aux tracés
coastlines = mcoast(map_coastline_land_shade= 'off',
    map_coastline_land_shade_colour= 'grey',
    map_coastline_sea_shade= 'off',
    map_coastline_sea_shade_colour= 'white')
 
# Importe les données pression et géopotentiel
z500 = mgrib(grib_input_file_name = "gfs.t06z.pgrb2.0p50.f003",
	grib_field_position = 222,	
	grib_automatic_scaling='off',
    grib_scaling_factor=0.1  # Conversion des mètres en décamètres
)
prmsl = mgrib(grib_input_file_name = "gfs.t06z.pgrb2.0p50.f003",
	grib_field_position = 586,
	grib_automatic_scaling='off',
    grib_scaling_factor=0.01 # Conversion des Pa en hPa
)
 
# On souhaite tracer le Z500 avec les plages de couleur habituelles de Météo Blois
# Il nous faut spécifier les niveaux et les couleurs
z500_contour = mcont(
	contour_level_selection_type= "level_list",
	contour="off",
	contour_hilo= "off",
    contour_label="off",
	contour_level_list=[500., 504., 508., 512., 516., 520., 524., 528., 532., 536., 540., 
				544., 548., 552., 556., 560., 564., 568., 572., 576., 580., 584., 588., 
				592., 596., 600.],
	contour_shade= "on",
    contour_shade_method= "area_fill",
	contour_shade_colour_method= "list",
    contour_shade_colour_list= [
			"RGB(0.1569, 0, 0.1490)", 	
			"RGB(0.2902, 0, 0.3372)",
		 	"RGB(0.3372, 0, 0.5333)", 	
			"RGB(0.3059, 0, 0.7137)",
			"RGB(0.1804, 0, 0.9098)",
		 	"RGB(0.0157, 0, 1)",
	 		"RGB(0, 0.1804, 1)",
	 		"RGB(0, 0.4157, 1)",
	 		"RGB(0, 0.6314, 1)",
			"RGB(0, 0.8470, 1)",
	 		"RGB(0, 1, 0.9647)",
	 		"RGB(0, 1, 0.7490)",
	 		"RGB(0, 1, 0.3294)",
			"RGB(0, 1, 0.098)",
			"RGB(0.098, 1, 0)",
	 		"RGB(0.2980, 1, 0)",
	 		"RGB(0.5137, 1, 0)",
	 		"RGB(0.7333, 1, 0)",
			"RGB(0.9647, 1, 0)",
	 		"RGB(1, 0.8470, 0)",
	 		"RGB(1, 0.6470, 0)",
			"RGB(1, 0.4157, 0)",
	 		"RGB(1, 0.2157, 0)",
			"RGB(1, 0, 0)",
			"RGB(0.7294, 0, 0)",
	 		"RGB(0.5, 0, 0)",
 			"RGB(0.25, 0, 0)",
 			"RGB(0.125, 0, 0)"],
    legend='on',
    contour_legend_text="Géopotentiel 500hPa")


# Contour PRSML tous les 5 hPa, avec les labels pour "mini" et "maxi"
contour = mcont(contour_highlight_colour= "black",
                contour_highlight_thickness= 4,
                contour_hilo= "on",
                contour_interval= 5.,
                contour_label= "on",
                contour_label_frequency= 2,
                contour_label_height= 0.4,
                contour_level_selection_type= "interval",
                contour_line_colour= "black",
                contour_line_thickness= 2,
                legend='off',
                contour_legend_text= "Pression au niveau de la mer"
            )

# On rajoute une légende en plages continues pour le Z500
legend = mlegend(legend="on",
	legend_display_type="continuous",
	legend_text_colour="charcoal",
	legend_text_font_size=0.4
    )

# Quelques lignes de titre 
title = mtext(text_lines=['Pression et Géopotentiel 500hPa', 'Run GFS 06z du 24/11/2019', 'Pour le 24/11/2019 04:00 (+003h)'],
            text_font_size = 0.8,
            text_colour= "charcoal",
            text_font_style='bold',
        )

# Plus qu'à superposer tout ça
plot(formats, europe, z500, z500_contour, prmsl, contour, coastlines, legend, title)

Le résultat est tout simplement magics…

Exemple avancé avec Magics

Conclusion

Nous venons de faire une initiation à deux outils permettant d’extraire et tracer des données météo. Cet article étant déjà fort long, nous aborderons le prochain gros morceau ultérieurement : Metview.