Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utiliser directement l'API Météo-France plutôt que data.gouv.fr #24

Open
antoinetavant opened this issue Oct 21, 2024 · 4 comments
Open

Comments

@antoinetavant
Copy link
Collaborator

pourquoi

  1. début octobre, nous avons été gêné par data.gouv.fr qui était down. Notre service était également down, alors que la source original de la donné, météo-france, était up.
  2. les données de data.gouv.fr sont uniquement au format GRIB2, qui nécéssite une dépendance un peut embétante à installer : eeCodes. Alors que météofrance fourni également le format TIFF, qui est plus simple à lire avec des packages usuels. permet de résoudre Improve the installation of dependancies #17 également
  3. les données data.gouv.fr sont archivées : un seul fichier avec les données de toutes l'europes, et de toutes les variables, alors que nous n'utilisons que 2 variables sur le territoire français

Avantages

  • plus fiables (on demande à la source)
  • format plus générique (TIFF vs GRIB2)

Limitations

  • l'API météo-france ne fournit que des plans 2D longitude-latitude par requètes. Il y a 103 date à récupérer, et ce, pour deux variables (flux solair et vent). Donc, il faut réaliser 206 requêtes successives, plutôt qu'une seule. :/
  • L'API a une limitation de 50 requêtes par minutes, donc il faut limiter les requêtes, ça prendre 4 minutes environs (équivalent à ce qu'on a actuellement avec une seule requête à data.gouv.fr)
  • il faut concaténer les 103 fichiers TIFF en un seul XArray.DataArray avant de pouvoir le traiter.
  • il faut une clé API, gratuite, mais nécessite de la gérer.

Comment faire

J'ai créé une interface de l'api https://portail-api.meteofrance.fr/web/fr/api/ARPEGE sur https://github.com/antoinetavant/meteofranceapi. Elle est presque fonctionnelle (quelques paramètres à changer).

il ne faut presque rien changer pour que ça marche sans souci.

@guillaumepot
Copy link

guillaumepot commented Oct 23, 2024

Hello,

quid de l'API open-meteo ?

Avantages

  • Possibilité de selectionner plusieurs modèles dont ceux de meteo France (AROME et ARPEGE)
  • Format retourné en liste d'arrays numpy, facile à transformer vers d'autres tel que Json, DataFrame, etc..
  • Beaucoup de possibilités dont le fait d'avoir données horaire sur de nombreux paramètres
  • API très facile à mettre en place et propose également un package Python.
  • Le package Python utilise un cache (par défaut sur du .sqlite écrit en fichier) facilement configurable (ex: utiliser un Redis)
  • Ne necessite pas de clé API
  • Deux routes: Une pour le forecast (de -3 mois à j+16) et une pour les archives (remontant sur plusieurs années)

Limitations

  • En non commercial use, 10'000 requetes par jour.
  • Quelques transformations à prévoir

Documentation

https://open-meteo.com/en/docs

Exemple d'implémentation

Dépendances:

!pip install openmeteo-requests
!pip install requests-cache retry-requests numpy pandas

Import

import openmeteo_requests
import requests_cache
import pandas as pd
from retry_requests import retry

Cache

cache_session = requests_cache.CachedSession('.cache', expire_after = 3600)
retry_session = retry(cache_session, retries = 5, backoff_factor = 0.2)
openmeteo = openmeteo_requests.Client(session = retry_session)

-- Exemple de cache avec Redis:

async def setup_cache_session() -> requests_cache.CachedSession:
    redis_client = await get_redis_client()
    cache_session = requests_cache.CachedSession(
        backend = "redis",
        connection = redis_client,
        expire_after = 600
    )
    return cache_session


cache_session = asyncio.run(setup_cache_session())
retry_session = retry(cache_session, retries = 5, backoff_factor = 0.5)
openmeteo = openmeteo_requests.Client(session = retry_session)

Params

forecast_url = "https://api.open-meteo.com/v1/forecast"
historical_forecast_url = "https://historical-forecast-api.open-meteo.com/v1/forecast"
openmeteo_models = ["meteofrance_arpege_europe", "meteofrance_arome_france"] # Insérer ou supprimer des modèles

# Paramètres suivants à renseigner selon besoins et selon délais (actuel, par jour, par heure)
params_current_weather = ["temperature_2m", "relative_humidity_2m", "precipitation", "wind_speed_10m"]
params_daily_weather = ["temperature_2m_max", "temperature_2m_min", "sunrise", "sunset", "precipitation_sum"]
params_hourly_weather = ["temperature_2m", "precipitation_probability", "rain", "weather_code", "surface_pressure"]


#### Requetes sur l'api
``` python
params = {
    "latitude": latitude,
    "longitude": longitude,
    "daily": params_daily_weather,
    "hourly": params_hourly_weather,
    "current": params_current_weather,
    "models": openmeteo_models,
    "past_days": 0,
   "forecast_days": 3
}

responses = openmeteo.weather_api(url, params = params)
response = responses[0]

Transformation des données requetées (ici on retourne des dict)

 # Transform daily
daily = response.Daily()

daily_data = {"date": pd.date_range(
    start = pd.to_datetime(daily.Time(), unit = "s", utc = True),
    end = pd.to_datetime(daily.TimeEnd(), unit = "s", utc = True),
    freq = pd.Timedelta(seconds = daily.Interval()),
    inclusive = "left"
)}


for index, elt in enumerate(params_daily_weather):
    daily_data[elt] = daily.Variables(index).ValuesAsNumpy()

for key, value in daily_data.items():
    if isinstance(value, list) or isinstance(value, int):
        pass
    else:
        daily_data[key] = value.tolist()


  # Transform hourly
hourly = response.Hourly()

hourly_data = {"date": pd.date_range(
    start = pd.to_datetime(hourly.Time(), unit = "s", utc = True),
    end = pd.to_datetime(hourly.TimeEnd(), unit = "s", utc = True),
    freq = pd.Timedelta(seconds = hourly.Interval()),
    inclusive = "left"
)}

for index, elt in enumerate(params_hourly_weather):
    values = hourly.Variables(index).ValuesAsNumpy()
    hourly_data[elt] = [None if np.isnan(v) else v for v in values]

for key, value in hourly_data.items():
    if isinstance(value, int) or isinstance(value, list):
        pass
    else:
        hourly_data[key] = value.tolist()
        
    hourly_data[key] = [float(v) if isinstance(v, np.float32) else v for v in value]


  # Transform current
current = response.Current()
transformed_current = {}

for index, elt in enumerate(params_current_weather):
    transformed_current[f"current_{elt}"] = current.Variables(index).Value()

@antoinetavant
Copy link
Collaborator Author

Merci @guillaumepot pour cette réponse très riche ! J'étais effectivement tombé dessus, mais je n'avais pas pris le temps l'aller autant dans les détails de l'API.

Une limitation importante est le fait qu'une requête doit être faite pour une position latitude/longitude (ou bien fournir une liste exhaustive des positions). Aujourd'hui, on utilise toutes les positions disponibles sur le sol français, car on ne prend pas en considération la position des centrales ENR. Je préfèrerais pouvoir faire une requête pour un range de longitude/latitude, définissant ainsi une aire plutôt qu'un ou des points.

Cela dit, il pourrait à terme être pertinent de sélectionner les positions d'intérêt plutôt que de traiter toute la France. Je pense à deux approches pour le faire :

  • en non supervisée, en cherchant à réduire le nombre de positions nécessaire pour modéliser la production
  • en supervisée, en utilisant par exemple cette base de donnée pour sélectionner les zones avec le plus de production

@antoinetavant
Copy link
Collaborator Author

Un autre point intéressant d'utiliser Open-Météo, c'est que c'est une seulle API pour plusieur modèles, chacuns ayant des aventages différents.
On pourrait donc utiliser

  • AROME pour court-terme (J+1 & J+2)
  • ARPEGE pour le moyen terme (J+3 & J+4)
  • ICON pour le long terme (J+5 à J+7)
  • GFS pour le très long terme (J+8 & J+9)

Le tout, avec une seule API. ça serait vraiment sympa.

@guillaumepot
Copy link

Effectivement l'utilisation d'une aire de coordonnées complique l'utilisation de l'API open-meteo.
Dans ce cas, il faut soit envisager de "centrer" les coordonnées en un point (et réduire la granularité, à savoir s'il s'agit d'une granularité régionale, descendre quelques niveaux plus bas: departement, etc..)

En revanche, si à l'avenir l'implementation propose à un utilisateur de s'enregistrer et d'obtenir des informations, tout est est place:

  • L'utilisateur s'enregistre
  • L'utilisateur enregistre des points de surveillance (ex: coordonnées de son domicile pour un particulier, coordonnées des locaux d'une entreprise, etc..)
  • L'utilisateur est informé lorsque la statut change car un pipeline récupère les données météo des points utilisateurs, execute des prédictions et agit en fonction de la prédiction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants