py_atmo_data_wrapper/docs/README.md
2025-07-14 21:24:55 +02:00

536 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Wrapper Python pour l'API Atmo Data
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 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](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 :
- [indice ATMO de la qualité de l'air](https://www.atmo-france.org/article/lindice-atmo)
- [les épisodes de pollution](https://www.atmo-france.org/article/les-episodes-de-pollution)
- les émissions à l'échelle de la région et de l'établissement public de coopération intercommunale (EPCI)
- [l'indice pollen](https://www.atmo-france.org/article/indice-pollen)
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](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](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
```bash
# 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 :
```bash
pip install requests>=2.25.0
```
### Installation des dépendances de développement
```bash
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
```bash
# Copier le fichier exemple
cp credentials.json.example credentials.json
# Éditer avec vos identifiants
nano credentials.json
```
### 2. Format du fichier credentials.json
```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
```python
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 :
```python
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 :
```python
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
```python
# 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
```python
# 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
```python
# É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
```python
# Émissions par région
emissions = client.get_emissions(echelle="region")
# Émissions par EPCI
emissions = client.get_emissions(echelle="epci", aasqa="11")
```
### Indices pollen
```python
# 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
```python
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 :
```python
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 :
```python
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 :
```python
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 :
```python
# 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
```bash
# 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
```bash
# 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