Ce projet fournit un wrapper Python pour l'API Atmo Data ([https://admindata.atmo-france.org](https://admindata.atmo-france.org)), permettant d'accéder facilement aux données de qualité de l'air et de pollution des Associations agréées de surveillance de la qualité de l’air (AASQA) françaises.
Find a file
2025-07-14 21:24:55 +02:00
atmo_data_wrapper first commit 2025-07-14 17:56:57 +02:00
demos first commit 2025-07-14 17:56:57 +02:00
docs Remove files from repository 2025-07-14 21:24:55 +02:00
examples first commit 2025-07-14 17:56:57 +02:00
tests first commit 2025-07-14 17:56:57 +02:00
.gitignore Remove files from repository 2025-07-14 21:24:55 +02:00
credentials.json.example first commit 2025-07-14 17:56:57 +02:00
LICENSE Remove files from repository 2025-07-14 21:24:55 +02:00
MANIFEST.in Remove files from repository 2025-07-14 21:24:55 +02:00
pyproject.toml Remove files from repository 2025-07-14 21:24:55 +02:00
requirements-dev.txt first commit 2025-07-14 17:56:57 +02:00
requirements.txt first commit 2025-07-14 17:56:57 +02:00
setup.py Remove files from repository 2025-07-14 21:24:55 +02:00

Wrapper Python pour l'API Atmo Data

Ce projet fournit un wrapper Python pour l'API Atmo Data (https://admindata.atmo-france.org), permettant d'accéder facilement aux données de qualité de l'air et de pollution des Associations agréées de surveillance de la qualité de lair (AASQA) françaises. Atmo Data est un agrégateur national des données produites par les AASQA en accès libre et sous licence ODbL, géré par Atmo France (https://www.atmo-france.org), la Fédération des Associations agréées de surveillance de la qualité de l'air.

Elle met à disposition 6 flux agrégés sur les 4 thèmes suivants :

Chacun peut donc bénéficier gratuitement de ces données mises en open data sous licence ODbL, en indiquant la source "Atmo France et les Associations agréées de surveillance de la qualité de lair" ou "Atmo France / AASQA" dans sa version courte.

La documentation de l'API est disponible en ligne à l'adresse : https://admindata.atmo-france.org/api/doc/v2. La Notice technique et dinformation des données open data sur la qualité de lair disponibles sur Atmo Data (Version 1er avril 2025) est disponible en ligne à l'adresse : https://www.atmo-france.org/sites/federation/files/medias/documents/2025-04/notice_Atmo_Data_1eravril2025.pdf.

Structure du projet

atmo-data-wrapper/
├── atmo_data_wrapper/           # Package principal
│   ├── __init__.py             # Exports principaux du package
│   └── core/                   # Module central
│       ├── __init__.py         # Exports du module core
│       ├── client.py           # Client principal pour l'API
│       ├── models.py           # Classes pour les données typées
│       ├── constants.py        # Constantes et configurations
│       ├── utils.py            # Fonctions utilitaires
│       └── exceptions.py       # Exceptions personnalisées
├── examples/                   # Scripts d'exemples
│   ├── __init__.py
│   ├── example_usage.py        # Exemples d'utilisation des endpoints
│   ├── example_save_files.py   # Exemples de sauvegarde
│   ├── example_data_models.py  # Exemples avec objets typés
│   ├── example_aasqa_utilities.py # Exemples fonctions utilitaires AASQA
│   ├── example_aasqa_advanced.py # Analyses avancées AASQA
│   ├── example_synthese_nancy.py # Exemple synthèse complète
│   └── setup_credentials.py    # Configuration des credentials
├── demos/                      # Scripts de démonstration complète
│   ├── __init__.py
│   ├── demo_atmo_functions.py  # Démonstration complète IndiceAtmo
│   ├── demo_pollen_functions.py # Démonstration complète IndicePollen
│   ├── demo_emission_functions.py # Démonstration complète EmissionData
│   ├── demo_licence_atmo.py    # Démonstration licence Atmo France
│   └── demo_episode_functions.py # Démonstration complète EpisodePollution
├── tests/                      # Tests unitaires
│   ├── __init__.py
│   ├── test_validations.py     # Tests de validation
│   ├── test_save_functionality.py # Tests de sauvegarde
│   ├── test_typed_client.py    # Tests d'intégration modèles
│   ├── test_real_connection.py # Test de connexion réelle à l'API
│   └── test_credentials_system.py # Tests du système de credentials
├── docs/                       # Documentation
│   ├── README.md              # Documentation principale
│   ├── QUICKSTART.md          # Guide de démarrage rapide
│   ├── DOCUMENTATION_DEMOS.md # Documentation des scripts de démonstration
│   ├── JOURNAL.md             # Journal de développement
│   ├── notice_Atmo_Data_1eravril2025.md # Notice officielle API
│   └── swagger.json           # Spécification API
├── credentials.json.example    # Modèle de fichier credentials
├── credentials.json           # Vos identifiants (à créer, ignoré par git)
├── setup.py                   # Configuration du package
├── pyproject.toml            # Configuration moderne du package
├── requirements.txt          # Dépendances de production
├── requirements-dev.txt      # Dépendances de développement
├── MANIFEST.in              # Fichiers à inclure dans le package
├── LICENSE                  # Licence MIT
└── .gitignore              # Fichiers à ignorer par git

Installation

Installation depuis le repository local

# Cloner ou télécharger le project
git clone https://github.com/atmo-france/atmo-data-wrapper.git
cd atmo-data-wrapper

# Installation en mode développement
pip install -e .

# Ou installation normale
pip install .

Dépendances

Le package nécessite Python 3.7+ et les dépendances suivantes :

pip install requests>=2.25.0

Installation des dépendances de développement

pip install -r requirements-dev.txt

Configuration des credentials

0. Pré requis : Demander l'autorisation

L'accès aux données requiert l'autorisation d'un d'administrateur de l'application API Atmo Data. Vous pouvez réaliser une demande de création de compte à cette adresse : https://admindata.atmo-france.org/inscription-api.

Pour vous connecter à l'API Atmo Data, vous devez créer un fichier de configuration avec vos identifiants.

1. Créer le fichier credentials.json

# Copier le fichier exemple
cp credentials.json.example credentials.json

# Éditer avec vos identifiants
nano credentials.json

2. Format du fichier credentials.json

{
  "username": "votre_nom_utilisateur",
  "password": "votre_mot_de_passe",
  "api_url": "https://api.atmo-data.org"
}

Important :

  • Le fichier credentials.json est ajouté au .gitignore pour éviter de commiter vos identifiants
  • Remplacez les valeurs par vos vrais identifiants fournis par Atmo Data
  • L'URL de l'API peut être modifiée si nécessaire

Utilisation

Authentification

Méthode recommandée : Fichier credentials.json

from atmo_data_wrapper import AtmoDataClient, AASQA_CODES, POLLUANTS

# Connexion automatique avec credentials.json
client = AtmoDataClient()
client.auto_login()  # Utilise automatiquement credentials.json

Fonctions utilitaires AASQA

Le wrapper fournit des fonctions utilitaires pour faciliter la manipulation des codes AASQA et la recherche d'organismes :

from atmo_data_wrapper import (
    get_aasqa_by_department,
    get_aasqa_info,
    search_aasqa_by_name,
    get_departments_count,
    validate_department_coverage,
    get_aasqa_statistics
)

# Trouver l'AASQA d'un département
aasqa_code = get_aasqa_by_department("54")  # Nancy
print(f"Département 54 -> AASQA {aasqa_code}")  # "44" (Grand Est)

# Informations complètes d'une AASQA
info = get_aasqa_info("44")
print(f"Organisme: {info['organisme']}")     # "ATMO Grand-Est"
print(f"Site web: {info['site_web']}")       # URL officielle
print(f"Départements: {info['departements']}")  # Liste des départements

# Recherche par nom
resultats = search_aasqa_by_name("Atmo")
for r in resultats:
    print(f"{r['organisme']} - {r['region']}")

# Statistiques
stats = get_aasqa_statistics()
print(f"Nombre total d'AASQA: {stats['total_aasqa']}")
print(f"Couverture moyenne: {stats['average_coverage']:.1f} départements/AASQA")

Licence et mentions légales

Conformément aux exigences d'Atmo France, le wrapper fournit des fonctions pour afficher les mentions légales requises :

from atmo_data_wrapper import get_atmo_licence, print_atmo_licence

# Version courte (recommandée)
print(get_atmo_licence("courte"))
# "Atmo France / AASQA"

# Version longue (officielle)
print(get_atmo_licence("longue"))
# "Atmo France et les Associations agréées de surveillance de la qualité de l'air"

# Version complète avec licence ODbL
print_atmo_licence("complete")
# Affiche les détails complets de la licence

# Utilisation dans un script
data = client.get_indices_atmo()
print(f"Source: {get_atmo_licence('courte')}")

Méthode alternative : Identifiants directs

# Connexion avec identifiants fournis directement
client = AtmoDataClient()
client.login("votre_username", "votre_password")

# Ou mélange des deux (override du fichier)
client.login(username="autre_user")  # password vient du fichier

Récupération des indices ATMO

# Indices d'aujourd'hui
indices = client.get_indices_atmo()

# Indices d'une date spécifique
indices = client.get_indices_atmo(date="2024-06-08")

# Indices pour une région spécifique (utilisation des constantes)
indices = client.get_indices_atmo(aasqa="11")  # AASQA_CODES['11'] = Île-de-France

Épisodes de pollution

# Épisodes en cours (3 jours)
episodes = client.get_episodes_3jours()

# Épisodes historiques
episodes = client.get_episodes_historique(date="2024-06-08")

# Filtre par polluant (utilisation des constantes)
episodes = client.get_episodes_3jours(polluant=POLLUANTS[2])  # PM10

Données d'émissions

# Émissions par région
emissions = client.get_emissions(echelle="region")

# Émissions par EPCI
emissions = client.get_emissions(echelle="epci", aasqa="11")

Indices pollen

# Indices pollen actuels
pollens = client.get_indices_pollens()

# Avec alertes uniquement
pollens = client.get_indices_pollens(alerte=True)

Objets typés et modèles de données

Le wrapper utilise des objets typés pour faciliter l'exploitation des données. Chaque type de données retourné par l'API est représenté par une classe spécialisée avec des méthodes helper.

Types de données disponibles

  • IndiceAtmo : Indices de qualité de l'air ATMO (0-7)
  • EpisodePollution : Épisodes de pollution atmosphérique
  • EmissionData : Données d'inventaires des émissions
  • IndicePollen : Indices polliniques (0-6)
  • AtmoDataCollection : Collection gérant plusieurs objets

Utilisation avec objets typés

from atmo_data_wrapper import AtmoDataClient, Coordinates

client = AtmoDataClient()
client.auto_login()  # Connexion avec credentials.json

# Les données GeoJSON retournent des objets typés
indices = client.get_indices_atmo(aasqa="11")  # Retourne AtmoDataCollection

# Parcourir les données avec méthodes helper
for indice in indices:
    print(f"Zone: {indice.lib_zone}")
    print(f"Qualité: {indice.get_qualificatif()}")
    print(f"Couleur: {indice.get_color()[0]}")  # Couleur hex
    
    if indice.is_poor_quality():
        worst_pol, code = indice.get_worst_pollutant()
        print(f"Attention: {worst_pol} élevé ({code})")

# Statistiques sur la collection
stats = indices.get_statistics()
print(f"Qualité moyenne: {stats['quality_stats']['moyenne']:.1f}")

# Filtrage géographique
paris = Coordinates(2.3522, 48.8566)
nearby = indices.filter_by_coordinates(paris, radius_km=20)

Classes et méthodes disponibles

IndiceAtmo

  • get_qualificatif() : Qualificatif textuel (Bon, Moyen, etc.)
  • get_color() : Couleur hex et RGB associée
  • is_good_quality() / is_poor_quality() : Tests de qualité
  • get_worst_pollutant() : Polluant le plus problématique
  • get_pollutants_summary() : Résumé de tous les polluants

EpisodePollution

  • is_alert_active() : Vérifie si une alerte est en cours
  • get_alert_level() : Niveau d'alerte (Information/Alerte/Aucune)
  • get_polluant_code() : Code du polluant principal

EmissionData

  • get_emission_density(polluant) : Densité d'émission par km²
  • get_emission_per_capita(polluant) : Émission par habitant
  • get_total_emissions() : Toutes les émissions
  • get_secteur_name() : Nom du secteur d'émission

IndicePollen

  • is_alert_active() : Alerte pollen active
  • get_highest_pollen() : Espèce avec l'indice le plus élevé
  • get_dangerous_pollens() : Liste des pollens à risque élevé
  • get_pollens_summary() : Détail par espèce avec émojis
  • get_responsible_pollens() : Taxons responsables selon l'API

AtmoDataCollection

  • filter_by_aasqa(code) : Filtrage par région
  • filter_by_coordinates(center, radius) : Filtrage géographique
  • get_statistics() : Statistiques de la collection
  • to_summary() : Résumé textuel

API Endpoints

  • get_indices_atmo() - Indices de qualité de l'air ATMO
  • get_episodes_3jours() - Épisodes de pollution sur 3 jours
  • get_episodes_historique() - Épisodes de pollution historiques
  • get_emissions() - Inventaires des émissions
  • get_indices_pollens() - Indices pollen

Codes AASQA

Le wrapper fournit des constantes enrichies avec sites web et départements couverts :

  • 01: Guadeloupe (Gwad'Air) - Département 971
  • 02: Martinique (Madininair) - Département 972
  • 03: Guyane (Atmo Guyane) - Département 973
  • 04: La Réunion (Atmo Réunion) - Département 974
  • 06: Mayotte (Hawa Mayotte) - Département 976
  • 11: Île-de-France (Airparif) - Départements 75, 77, 78, 91, 92, 93, 94, 95
  • 24: Centre-Val de Loire (Lig'Air) - Départements 18, 28, 36, 37, 41, 45
  • 27: Bourgogne-Franche-Comté (Atmo BFC) - Départements 21, 25, 39, 58, 70, 71, 89, 90
  • 28: Normandie (Atmo Normandie) - Départements 14, 27, 50, 61, 76
  • 32: Hauts-de-France (Atmo HDF) - Départements 02, 59, 60, 62, 80
  • 44: Grand Est (ATMO Grand-Est) - Départements 08, 10, 51, 52, 54, 55, 57, 67, 68, 88
  • 52: Pays de la Loire (Air Pays de la Loire) - Départements 44, 49, 53, 72, 85
  • 53: Bretagne (Air Breizh) - Départements 22, 29, 35, 56
  • 75: Nouvelle-Aquitaine (Atmo NA) - Départements 16, 17, 19, 23, 24, 33, 40, 47, 64, 79, 86, 87
  • 76: Occitanie (Atmo Occitanie) - Départements 09, 11, 12, 30, 31, 32, 34, 46, 48, 65, 66, 81, 82
  • 84: Auvergne-Rhône-Alpes (Atmo AURA) - Départements 01, 03, 07, 15, 26, 38, 42, 43, 63, 69, 73, 74
  • 93: Provence-Alpes-Côte d'Azur (AtmoSud) - Départements 04, 05, 06, 13, 83, 84
  • 94: Corse (Qualitair) - Départements 2A, 2B

Accès programmatique :

from atmo_data_wrapper import AASQA_CODES
info = AASQA_CODES['44']
print(f"Site web: {info['site_web']}")
print(f"Départements: {info['departements']}")

Gestion des erreurs

Le wrapper utilise des exceptions personnalisées pour gérer différents types d'erreurs :

from atmo_data_wrapper import AtmoDataClient, AtmoDataException

try:
    client = AtmoDataClient()
    client.auto_login()
    indices = client.get_indices_atmo()
except ValueError as e:
    print(f"Erreur de validation: {e}")
except AtmoDataException as e:
    print(f"Erreur API: {e}")
except Exception as e:
    print(f"Erreur inattendue: {e}")

Types d'exceptions disponibles

  • AtmoDataException : Exception de base
  • AuthenticationError : Erreur d'authentification
  • ValidationError : Erreur de validation des paramètres
  • APIError : Erreur de l'API Atmo Data
  • NetworkError : Erreur de réseau
  • DataError : Erreur dans le traitement des données

Validation des paramètres

Le wrapper valide automatiquement tous les paramètres avant d'envoyer les requêtes :

  • Formats : Seuls geojson et csv sont acceptés
  • Codes AASQA : Validation contre la liste des codes valides (01-94)
  • Polluants : Validation contre la liste des polluants supportés
  • Dates : Validation du format YYYY-MM-DD et de l'existence de la date
  • Indices : Validation des codes qualificatifs ATMO (0-7) et pollen (0-6)
  • Bounding box : Validation du format et de la cohérence des coordonnées

Exemple d'erreur de validation :

try:
    client.get_indices_atmo(format="xml")  # Format invalide
except ValueError as e:
    print(e)  # "Format invalide: xml. Formats valides: ['geojson', 'csv']"

Sauvegarde des données

Le wrapper permet de sauvegarder facilement les résultats de l'API dans différents formats :

# Récupérer des données
indices = client.get_indices_atmo(aasqa="11")

# Sauvegarder en JSON
json_file = client.save_to_file(indices, "data/indices_atmo", "json")

# Sauvegarder en CSV 
csv_file = client.save_to_file(indices, "data/indices_atmo", "csv")

# Sauvegarder en GeoJSON
geojson_file = client.save_to_file(indices, "data/indices_atmo", "geojson")

Formats supportés pour la sauvegarde :

  • json - Format JSON standard
  • csv - Format CSV avec extraction automatique des propriétés
  • geojson - Format GeoJSON (données géographiques)

Fonctionnalités :

  • Création automatique de répertoires : Les dossiers parents sont créés si nécessaire
  • Extensions automatiques : Les extensions (.json, .csv, .geojson) sont ajoutées automatiquement
  • Extraction CSV intelligente : Conversion automatique des données GeoJSON vers CSV avec coordonnées
  • Validation des formats : Vérification de la compatibilité des données avec le format choisi

Formats de sortie API

L'API supporte deux formats :

  • geojson (par défaut)
  • csv

Tests et Exemples

Scripts d'exemples

  • example_usage.py - Exemples d'utilisation des endpoints (données brutes)
  • example_save_files.py - Exemples de sauvegarde de données
  • example_data_models.py - Exemples avec objets typés et méthodes helper
  • example_aasqa_utilities.py - Exemples des fonctions utilitaires AASQA
  • example_aasqa_advanced.py - Analyses avancées et statistiques AASQA
  • demo_licence_atmo.py - Démonstration des fonctions de licence
  • example_synthese_tomblaine.py - Exemple de synthèse complète (Atmo + Pollen)

Scripts de démonstration complète

  • demo_atmo_functions.py - Démonstration complète de la classe IndiceAtmo
  • demo_pollen_functions.py - Démonstration complète de la classe IndicePollen
  • demo_emission_functions.py - Démonstration complète de la classe EmissionData
  • demo_episode_functions.py - Démonstration complète de la classe EpisodePollution

Ces scripts illustrent toutes les fonctionnalités de chaque classe avec des données réelles de l'API. Voir DOCUMENTATION_DEMOS.md pour une documentation détaillée.

Scripts de test

  • test_validations.py - Tests de validation des paramètres
  • test_save_functionality.py - Tests de sauvegarde de fichiers
  • test_typed_client.py - Tests d'intégration des modèles typés
  • test_real_connection.py - Test de connexion réelle à l'API

Test de votre configuration

# Vérifier la configuration et tester la connexion
python tests/test_real_connection.py

Ce script vérifie :

  • La présence et validité du fichier credentials.json
  • La connexion à l'API
  • Le bon fonctionnement des différents endpoints
  • Les objets typés et leurs méthodes

Exécution des scripts

# Scripts d'exemples
python examples/example_usage.py
python examples/example_data_models.py
python examples/example_aasqa_utilities.py
python examples/demo_licence_atmo.py

# Scripts de démonstration
python demos/demo_atmo_functions.py
python demos/demo_pollen_functions.py

# Tests
python -m pytest tests/

Nouvelles fonctionnalités

Architecture améliorée

  • Séparation des constantes et utilitaires : Les constantes sont dans constants.py, les fonctions utilitaires dans utils.py
  • Constantes enrichies : Les codes AASQA incluent maintenant sites web et départements
  • Mapping des codes : Constantes séparées pour les épisodes de pollution et les taxons de pollens

Fonctions utilitaires AASQA

  • Recherche par département ou nom d'organisme
  • Statistiques de couverture territoriale
  • Validation de l'intégrité des données
  • Analyses comparatives entre organismes

Conformité légale

  • Fonctions dédiées pour les mentions légales Atmo France
  • Respect de la licence ODbL
  • Intégration facilitée dans rapports et applications

Organisation du projet

  • Dossier archives/ pour l'historique des anciens scripts
  • Structure claire et maintenable
  • Documentation complète et à jour