first commit
This commit is contained in:
commit
a233e18c0b
48 changed files with 55300 additions and 0 deletions
3
examples/__init__.py
Normal file
3
examples/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
Examples package for Atmo Data Wrapper
|
||||
"""
|
276
examples/example_aasqa_advanced.py
Normal file
276
examples/example_aasqa_advanced.py
Normal file
|
@ -0,0 +1,276 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Démonstration des fonctions utilitaires AASQA avancées
|
||||
===================================================
|
||||
|
||||
Ce script illustre l'utilisation des nouvelles fonctions utilitaires
|
||||
avancées pour analyser et rechercher dans les données AASQA.
|
||||
|
||||
Fonctionnalités:
|
||||
- Recherche par nom d'organisme ou région
|
||||
- Statistiques détaillées sur la couverture
|
||||
- Validation de l'intégrité des données
|
||||
- Analyses comparatives
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au PYTHONPATH pour importer le package local
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from atmo_data_wrapper import (
|
||||
search_aasqa_by_name,
|
||||
get_departments_count,
|
||||
validate_department_coverage,
|
||||
get_aasqa_statistics,
|
||||
get_aasqa_info
|
||||
)
|
||||
|
||||
def demo_search_functionality():
|
||||
"""Démonstration de la recherche par nom"""
|
||||
print("🔍 RECHERCHE PAR NOM D'ORGANISME OU RÉGION")
|
||||
print("=" * 55)
|
||||
|
||||
search_terms = ['Atmo', 'Air', 'France', 'Sud', 'Grand']
|
||||
|
||||
for term in search_terms:
|
||||
results = search_aasqa_by_name(term)
|
||||
print(f"🔎 Recherche '{term}' → {len(results)} résultat(s)")
|
||||
|
||||
for result in results[:3]: # Limiter à 3 résultats pour la démo
|
||||
print(f" • {result['organisme']} ({result['region']})")
|
||||
|
||||
if len(results) > 3:
|
||||
print(f" ... et {len(results) - 3} autre(s)")
|
||||
print()
|
||||
|
||||
def demo_department_statistics():
|
||||
"""Démonstration des statistiques départementales"""
|
||||
print("📊 STATISTIQUES DÉPARTEMENTALES")
|
||||
print("=" * 55)
|
||||
|
||||
dept_counts = get_departments_count()
|
||||
|
||||
# Tri par nombre de départements (décroissant)
|
||||
sorted_counts = sorted(dept_counts.items(), key=lambda x: x[1], reverse=True)
|
||||
|
||||
print("Classement par nombre de départements couverts:")
|
||||
print()
|
||||
|
||||
for i, (aasqa_code, count) in enumerate(sorted_counts, 1):
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
organisme = aasqa_info['organisme']
|
||||
region = aasqa_info['region']
|
||||
|
||||
if i <= 5: # Top 5
|
||||
print(f"{i:2d}. {organisme:<30} : {count:2d} département(s) ({region})")
|
||||
elif i == 6:
|
||||
print(" ...")
|
||||
elif i >= len(sorted_counts) - 2: # Bottom 3
|
||||
print(f"{i:2d}. {organisme:<30} : {count:2d} département(s) ({region})")
|
||||
|
||||
print()
|
||||
|
||||
def demo_validation_report():
|
||||
"""Démonstration du rapport de validation"""
|
||||
print("✅ RAPPORT DE VALIDATION")
|
||||
print("=" * 55)
|
||||
|
||||
validation = validate_department_coverage()
|
||||
|
||||
print("Intégrité des données AASQA:")
|
||||
print()
|
||||
print(f"📊 Total d'entrées départements: {validation['total_departments']}")
|
||||
print(f"📊 Départements uniques: {validation['unique_departments']}")
|
||||
print(f"📊 Couverture complète: {'✅ Oui' if validation['coverage_complete'] else '❌ Non'}")
|
||||
print(f"📊 Doublons détectés: {'❌ Oui' if validation['has_duplicates'] else '✅ Non'}")
|
||||
|
||||
if validation['duplicates']:
|
||||
print(f"⚠️ Départements en doublon: {', '.join(validation['duplicates'])}")
|
||||
|
||||
print()
|
||||
|
||||
def demo_comprehensive_statistics():
|
||||
"""Démonstration des statistiques complètes"""
|
||||
print("📈 STATISTIQUES COMPLÈTES")
|
||||
print("=" * 55)
|
||||
|
||||
stats = get_aasqa_statistics()
|
||||
|
||||
print("Vue d'ensemble:")
|
||||
print(f" • Nombre total d'AASQA: {stats['total_aasqa']}")
|
||||
print(f" • Départements couverts: {stats['total_departments_covered']}")
|
||||
print(f" • Départements uniques: {stats['unique_departments']}")
|
||||
print(f" • Couverture moyenne: {stats['average_coverage']:.1f} départements/AASQA")
|
||||
print()
|
||||
|
||||
print("Couverture maximale:")
|
||||
max_info = stats['max_coverage']
|
||||
print(f" • {max_info['count']} départements")
|
||||
print(f" • Organisme(s): {', '.join(max_info['aasqa_names'])}")
|
||||
print()
|
||||
|
||||
print("Couverture minimale:")
|
||||
min_info = stats['min_coverage']
|
||||
print(f" • {min_info['count']} département(s)")
|
||||
print(f" • Organisme(s): {', '.join(min_info['aasqa_names'])}")
|
||||
print()
|
||||
|
||||
print(f"Anomalies: {'❌ Détectées' if stats['has_anomalies'] else '✅ Aucune'}")
|
||||
print()
|
||||
|
||||
def demo_practical_analysis():
|
||||
"""Démonstration d'analyses pratiques"""
|
||||
print("🎯 ANALYSES PRATIQUES")
|
||||
print("=" * 55)
|
||||
|
||||
# Analyse 1: Organismes DOM-TOM
|
||||
print("1️⃣ Analyse DOM-TOM:")
|
||||
dom_tom_codes = ['971', '972', '973', '974', '976']
|
||||
|
||||
from atmo_data_wrapper import get_aasqa_by_department
|
||||
|
||||
for code in dom_tom_codes:
|
||||
aasqa_code = get_aasqa_by_department(code)
|
||||
if aasqa_code:
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
print(f" • {code}: {aasqa_info['region']} → {aasqa_info['organisme']}")
|
||||
print()
|
||||
|
||||
# Analyse 2: Régions métropolitaines les plus étendues
|
||||
print("2️⃣ Grandes régions métropolitaines:")
|
||||
dept_counts = get_departments_count()
|
||||
metro_counts = {}
|
||||
|
||||
for aasqa_code, count in dept_counts.items():
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
# Exclure DOM-TOM (codes postaux 97x)
|
||||
if not any(dept.startswith('97') for dept in aasqa_info['departements']):
|
||||
metro_counts[aasqa_code] = count
|
||||
|
||||
top_metro = sorted(metro_counts.items(), key=lambda x: x[1], reverse=True)[:3]
|
||||
|
||||
for i, (aasqa_code, count) in enumerate(top_metro, 1):
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
print(f" {i}. {aasqa_info['region']}: {count} départements ({aasqa_info['organisme']})")
|
||||
print()
|
||||
|
||||
# Analyse 3: Organismes avec URL atmo vs autres
|
||||
print("3️⃣ Analyse des noms d'organismes:")
|
||||
|
||||
from atmo_data_wrapper import AASQA_CODES
|
||||
|
||||
atmo_orgs = []
|
||||
other_orgs = []
|
||||
|
||||
for aasqa_code, aasqa_data in AASQA_CODES.items():
|
||||
if 'atmo' in aasqa_data['organisme'].lower():
|
||||
atmo_orgs.append(aasqa_data['organisme'])
|
||||
else:
|
||||
other_orgs.append(aasqa_data['organisme'])
|
||||
|
||||
print(f" • Organismes 'Atmo': {len(atmo_orgs)} ({len(atmo_orgs)/len(AASQA_CODES)*100:.0f}%)")
|
||||
print(f" • Autres noms: {len(other_orgs)} ({len(other_orgs)/len(AASQA_CODES)*100:.0f}%)")
|
||||
print(f" • Noms alternatifs: {', '.join(other_orgs[:3])}{'...' if len(other_orgs) > 3 else ''}")
|
||||
print()
|
||||
|
||||
def demo_data_quality_checks():
|
||||
"""Démonstration des vérifications de qualité"""
|
||||
print("🔬 VÉRIFICATIONS DE QUALITÉ DES DONNÉES")
|
||||
print("=" * 55)
|
||||
|
||||
from atmo_data_wrapper import AASQA_CODES
|
||||
|
||||
print("1️⃣ Vérification des URLs:")
|
||||
urls_https = 0
|
||||
urls_http = 0
|
||||
|
||||
for aasqa_data in AASQA_CODES.values():
|
||||
url = aasqa_data['site_web']
|
||||
if url.startswith('https://'):
|
||||
urls_https += 1
|
||||
elif url.startswith('http://'):
|
||||
urls_http += 1
|
||||
|
||||
print(f" • URLs HTTPS: {urls_https}/{len(AASQA_CODES)} ({urls_https/len(AASQA_CODES)*100:.0f}%)")
|
||||
if urls_http > 0:
|
||||
print(f" ⚠️ URLs HTTP: {urls_http}")
|
||||
else:
|
||||
print(f" ✅ Toutes les URLs sont sécurisées (HTTPS)")
|
||||
print()
|
||||
|
||||
print("2️⃣ Vérification des codes départementaux:")
|
||||
|
||||
valid_formats = 0
|
||||
invalid_formats = []
|
||||
|
||||
for aasqa_code, aasqa_data in AASQA_CODES.items():
|
||||
for dept in aasqa_data['departements']:
|
||||
# Vérifier le format (2 chiffres, 3 chiffres pour DOM-TOM, ou 2A/2B pour Corse)
|
||||
if (dept.isdigit() and len(dept) in [2, 3]) or dept in ['2A', '2B']:
|
||||
valid_formats += 1
|
||||
else:
|
||||
invalid_formats.append(dept)
|
||||
|
||||
print(f" • Codes valides: {valid_formats}")
|
||||
if invalid_formats:
|
||||
print(f" ⚠️ Codes invalides: {invalid_formats}")
|
||||
else:
|
||||
print(f" ✅ Tous les codes départementaux sont valides")
|
||||
print()
|
||||
|
||||
print("3️⃣ Cohérence des descriptions:")
|
||||
consistent = 0
|
||||
inconsistent = []
|
||||
|
||||
for aasqa_code, aasqa_data in AASQA_CODES.items():
|
||||
expected_desc = f"{aasqa_data['region']} | {aasqa_data['organisme']}"
|
||||
if aasqa_data['description'] == expected_desc:
|
||||
consistent += 1
|
||||
else:
|
||||
inconsistent.append(aasqa_code)
|
||||
|
||||
print(f" • Descriptions cohérentes: {consistent}/{len(AASQA_CODES)}")
|
||||
if inconsistent:
|
||||
print(f" ⚠️ Incohérences: {inconsistent}")
|
||||
else:
|
||||
print(f" ✅ Toutes les descriptions sont cohérentes")
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
print("DÉMONSTRATION DES FONCTIONS UTILITAIRES AASQA AVANCÉES")
|
||||
print("=" * 65)
|
||||
print("Nouvelles analyses et vérifications de qualité des données")
|
||||
print()
|
||||
|
||||
try:
|
||||
demo_search_functionality()
|
||||
demo_department_statistics()
|
||||
demo_validation_report()
|
||||
demo_comprehensive_statistics()
|
||||
demo_practical_analysis()
|
||||
demo_data_quality_checks()
|
||||
|
||||
print("=" * 65)
|
||||
print("✅ TOUTES LES ANALYSES TERMINÉES AVEC SUCCÈS")
|
||||
print()
|
||||
print("🎯 Fonctions utilitaires démontrées:")
|
||||
print(" • search_aasqa_by_name(): Recherche textuelle")
|
||||
print(" • get_departments_count(): Comptage par AASQA")
|
||||
print(" • validate_department_coverage(): Validation intégrité")
|
||||
print(" • get_aasqa_statistics(): Statistiques complètes")
|
||||
print(" • Analyses qualité et cohérence des données")
|
||||
print()
|
||||
print("📁 Fichiers concernés:")
|
||||
print(" • constants.py: Données pures (sites web, départements)")
|
||||
print(" • utils.py: Fonctions utilitaires (nouvelle architecture)")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de l'exécution: {e}")
|
||||
import traceback
|
||||
print("\nDétails de l'erreur:")
|
||||
print(traceback.format_exc())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
250
examples/example_aasqa_utilities.py
Normal file
250
examples/example_aasqa_utilities.py
Normal file
|
@ -0,0 +1,250 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Démonstration des nouvelles fonctionnalités AASQA
|
||||
==============================================
|
||||
|
||||
Ce script illustre l'utilisation des nouvelles données enrichies
|
||||
des AASQA : sites web, départements, et fonctions utilitaires.
|
||||
|
||||
Fonctionnalités démontrées:
|
||||
- Recherche AASQA par département
|
||||
- Informations complètes des organismes
|
||||
- Sites web et contacts
|
||||
- Nouvelles méthodes des classes de données
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au PYTHONPATH pour importer le package local
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from atmo_data_wrapper import (
|
||||
AtmoDataClient,
|
||||
AASQA_CODES,
|
||||
get_aasqa_by_department,
|
||||
get_aasqa_info,
|
||||
get_aasqa_website,
|
||||
list_departments_by_aasqa
|
||||
)
|
||||
|
||||
def demo_department_search():
|
||||
"""Démonstration de la recherche par département"""
|
||||
print("🔍 RECHERCHE D'AASQA PAR DÉPARTEMENT")
|
||||
print("=" * 50)
|
||||
|
||||
departments_test = ['54', '75', '13', '2A', '974', '99']
|
||||
|
||||
for dept in departments_test:
|
||||
aasqa_code = get_aasqa_by_department(dept)
|
||||
if aasqa_code:
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
print(f"📍 Département {dept}: {aasqa_info['organisme']} ({aasqa_info['region']})")
|
||||
else:
|
||||
print(f"❌ Département {dept}: Non trouvé")
|
||||
|
||||
print()
|
||||
|
||||
def demo_aasqa_details():
|
||||
"""Démonstration des informations détaillées AASQA"""
|
||||
print("📋 INFORMATIONS DÉTAILLÉES DES AASQA")
|
||||
print("=" * 50)
|
||||
|
||||
# Quelques AASQA représentatives
|
||||
aasqa_samples = ['44', '11', '93', '01', '94']
|
||||
|
||||
for aasqa_code in aasqa_samples:
|
||||
info = get_aasqa_info(aasqa_code)
|
||||
if info:
|
||||
print(f"🏢 {info['organisme']}")
|
||||
print(f" 📍 Région: {info['region']}")
|
||||
print(f" 🌐 Site web: {info['site_web']}")
|
||||
print(f" 📋 Départements: {', '.join(info['departements'])}")
|
||||
print(f" 📊 Nombre de départements: {len(info['departements'])}")
|
||||
print()
|
||||
|
||||
def demo_website_access():
|
||||
"""Démonstration de l'accès aux sites web"""
|
||||
print("🌐 SITES WEB DES AASQA")
|
||||
print("=" * 50)
|
||||
|
||||
all_aasqa = list(AASQA_CODES.keys())
|
||||
|
||||
print("Liste des sites web par région:")
|
||||
print()
|
||||
|
||||
for aasqa_code in all_aasqa:
|
||||
website = get_aasqa_website(aasqa_code)
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
|
||||
if website and aasqa_info:
|
||||
print(f"• {aasqa_info['region']:<25} → {website}")
|
||||
|
||||
print()
|
||||
|
||||
def demo_department_coverage():
|
||||
"""Démonstration de la couverture départementale"""
|
||||
print("🗺️ COUVERTURE DÉPARTEMENTALE")
|
||||
print("=" * 50)
|
||||
|
||||
# Statistiques sur la couverture
|
||||
total_departments = 0
|
||||
largest_coverage = 0
|
||||
largest_aasqa = ""
|
||||
|
||||
print("Couverture par AASQA:")
|
||||
print()
|
||||
|
||||
for aasqa_code in AASQA_CODES.keys():
|
||||
departments = list_departments_by_aasqa(aasqa_code)
|
||||
aasqa_info = get_aasqa_info(aasqa_code)
|
||||
|
||||
total_departments += len(departments)
|
||||
|
||||
if len(departments) > largest_coverage:
|
||||
largest_coverage = len(departments)
|
||||
largest_aasqa = aasqa_info['organisme']
|
||||
|
||||
print(f"📊 {aasqa_info['organisme']:<30} : {len(departments):2d} département(s)")
|
||||
|
||||
print()
|
||||
print(f"📈 Statistiques:")
|
||||
print(f" • Total départements couverts: {total_departments}")
|
||||
print(f" • Plus grande couverture: {largest_aasqa} ({largest_coverage} départements)")
|
||||
print()
|
||||
|
||||
def demo_enhanced_data_models():
|
||||
"""Démonstration des nouvelles méthodes dans les modèles de données"""
|
||||
print("🎯 NOUVELLES MÉTHODES DES MODÈLES")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
# Connexion et récupération de données
|
||||
client = AtmoDataClient()
|
||||
success = client.auto_login()
|
||||
|
||||
if not success:
|
||||
print("❌ Échec de la connexion API")
|
||||
return
|
||||
|
||||
print("✅ Connexion API réussie")
|
||||
print()
|
||||
|
||||
# Récupération d'indices ATMO pour test
|
||||
print("📥 Récupération de données de test...")
|
||||
atmo_data = client.get_indices_atmo(aasqa="44", format="geojson") # Grand Est
|
||||
|
||||
if atmo_data and len(atmo_data) > 0:
|
||||
indice = atmo_data[0]
|
||||
|
||||
print(f"🎯 Données exemple: {indice.lib_zone}")
|
||||
print()
|
||||
print("🆕 Nouvelles méthodes AASQA:")
|
||||
print(f" • get_aasqa_name(): {indice.get_aasqa_name()}")
|
||||
print(f" • get_aasqa_website(): {indice.get_aasqa_website()}")
|
||||
print(f" • get_aasqa_region(): {indice.get_aasqa_region()}")
|
||||
print(f" • get_aasqa_organisme(): {indice.get_aasqa_organisme()}")
|
||||
print()
|
||||
|
||||
# Trouver l'AASQA depuis un département fictif
|
||||
dept_example = "54" # Meurthe-et-Moselle
|
||||
aasqa_found = get_aasqa_by_department(dept_example)
|
||||
print(f"🔍 Recherche par département {dept_example}: AASQA {aasqa_found}")
|
||||
|
||||
if aasqa_found:
|
||||
deps = list_departments_by_aasqa(aasqa_found)
|
||||
print(f" • Départements couverts: {', '.join(deps)}")
|
||||
|
||||
else:
|
||||
print("❌ Aucune donnée récupérée")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur: {e}")
|
||||
|
||||
print()
|
||||
|
||||
def demo_practical_usage():
|
||||
"""Démonstration d'usage pratique"""
|
||||
print("💡 EXEMPLES D'USAGE PRATIQUE")
|
||||
print("=" * 50)
|
||||
|
||||
print("1️⃣ Trouver l'organisme responsable d'un département:")
|
||||
print()
|
||||
|
||||
# Exemples pratiques
|
||||
examples = [
|
||||
("Nancy (54)", "54"),
|
||||
("Paris (75)", "75"),
|
||||
("Marseille (13)", "13"),
|
||||
("Ajaccio (2A)", "2A"),
|
||||
("Saint-Denis (974)", "974")
|
||||
]
|
||||
|
||||
for ville, dept in examples:
|
||||
aasqa_code = get_aasqa_by_department(dept)
|
||||
if aasqa_code:
|
||||
info = get_aasqa_info(aasqa_code)
|
||||
print(f" {ville:<15} → {info['organisme']}")
|
||||
print(f" {'':>15} Site: {info['site_web']}")
|
||||
else:
|
||||
print(f" {ville:<15} → Non trouvé")
|
||||
print()
|
||||
|
||||
print("2️⃣ Vérification de cohérence:")
|
||||
print()
|
||||
|
||||
# Vérification que tous les départements français sont couverts
|
||||
all_covered_depts = []
|
||||
for aasqa_code in AASQA_CODES.keys():
|
||||
all_covered_depts.extend(list_departments_by_aasqa(aasqa_code))
|
||||
|
||||
print(f" • Départements uniques couverts: {len(set(all_covered_depts))}")
|
||||
print(f" • Total d'entrées départements: {len(all_covered_depts)}")
|
||||
|
||||
# Recherche de doublons
|
||||
seen = set()
|
||||
duplicates = set()
|
||||
for dept in all_covered_depts:
|
||||
if dept in seen:
|
||||
duplicates.add(dept)
|
||||
seen.add(dept)
|
||||
|
||||
if duplicates:
|
||||
print(f" ⚠️ Départements en doublon: {duplicates}")
|
||||
else:
|
||||
print(f" ✅ Aucun doublon détecté")
|
||||
|
||||
print()
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
print("DÉMONSTRATION DES FONCTIONNALITÉS AASQA ENRICHIES")
|
||||
print("=" * 60)
|
||||
print("Nouvelles données : sites web, départements, fonctions utilitaires")
|
||||
print()
|
||||
|
||||
try:
|
||||
demo_department_search()
|
||||
demo_aasqa_details()
|
||||
demo_website_access()
|
||||
demo_department_coverage()
|
||||
demo_enhanced_data_models()
|
||||
demo_practical_usage()
|
||||
|
||||
print("=" * 60)
|
||||
print("✅ TOUTES LES DÉMONSTRATIONS TERMINÉES AVEC SUCCÈS")
|
||||
print()
|
||||
print("📋 Nouvelles fonctionnalités disponibles:")
|
||||
print(" • Structure AASQA enrichie (sites web, départements)")
|
||||
print(" • Fonctions utilitaires de recherche")
|
||||
print(" • Nouvelles méthodes dans les modèles de données")
|
||||
print(" • Usage simplifié par département")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de l'exécution: {e}")
|
||||
import traceback
|
||||
print("\nDétails de l'erreur:")
|
||||
print(traceback.format_exc())
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
367
examples/example_data_models.py
Normal file
367
examples/example_data_models.py
Normal file
|
@ -0,0 +1,367 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Exemples d'utilisation des nouveaux modèles de données typés
|
||||
"""
|
||||
|
||||
from atmo_data_wrapper import AtmoDataClient
|
||||
from atmo_data_wrapper import Coordinates
|
||||
|
||||
def example_indices_atmo():
|
||||
"""Exemple d'utilisation des indices ATMO avec objets typés"""
|
||||
print("=== Exemple Indices ATMO avec objets typés ===\n")
|
||||
|
||||
client = AtmoDataClient()
|
||||
|
||||
# Connexion automatique avec credentials.json
|
||||
# Décommentez les lignes suivantes pour une vraie connexion API :
|
||||
# try:
|
||||
# client.auto_login()
|
||||
# indices = client.get_indices_atmo(aasqa="11") # Données réelles
|
||||
# except Exception as e:
|
||||
# print(f"Erreur de connexion: {e}")
|
||||
# print("Utilisation de données de test...")
|
||||
# # Fallback sur données de test...
|
||||
|
||||
# Récupération des indices ATMO - maintenant retourne AtmoDataCollection
|
||||
try:
|
||||
# indices = client.get_indices_atmo(aasqa="11") # Île-de-France
|
||||
|
||||
# Pour la démonstration, créons des données de test
|
||||
test_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.3522, 48.8566]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code_qual": 3,
|
||||
"lib_qual": "Moyen",
|
||||
"coul_qual": "#FFFF00",
|
||||
"lib_zone": "Paris Centre",
|
||||
"date_dif": "2024-07-07",
|
||||
"code_no2": 2,
|
||||
"code_so2": 1,
|
||||
"code_o3": 3,
|
||||
"code_pm10": 2,
|
||||
"code_pm25": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.4522, 48.9566]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code_qual": 5,
|
||||
"lib_qual": "Mauvais",
|
||||
"coul_qual": "#FF0000",
|
||||
"lib_zone": "Banlieue Nord",
|
||||
"date_dif": "2024-07-07",
|
||||
"code_no2": 4,
|
||||
"code_so2": 2,
|
||||
"code_o3": 5,
|
||||
"code_pm10": 4,
|
||||
"code_pm25": 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Créer une collection typée
|
||||
from atmo_data_wrapper import AtmoDataCollection
|
||||
indices = AtmoDataCollection(test_data, 'indices')
|
||||
|
||||
print(f"Collection: {len(indices)} indices récupérés")
|
||||
print(f"Résumé: {indices.to_summary()}\n")
|
||||
|
||||
# Parcourir les indices avec les objets typés
|
||||
for i, indice in enumerate(indices):
|
||||
print(f"Indice {i+1}:")
|
||||
print(f" Zone: {indice.lib_zone}")
|
||||
print(f" AASQA: {indice.get_aasqa_name()}")
|
||||
print(f" Qualité: {indice.get_qualificatif()} (code: {indice.code_qual})")
|
||||
|
||||
# Utiliser les méthodes helper
|
||||
hex_color, rgb_color = indice.get_color()
|
||||
print(f" Couleur: {hex_color} (RGB: {rgb_color})")
|
||||
print(f" Bonne qualité: {'Oui' if indice.is_good_quality() else 'Non'}")
|
||||
print(f" Mauvaise qualité: {'Oui' if indice.is_poor_quality() else 'Non'}")
|
||||
|
||||
# Polluant le plus problématique
|
||||
worst_pol, worst_code = indice.get_worst_pollutant()
|
||||
print(f" Pire polluant: {worst_pol} (code: {worst_code})")
|
||||
|
||||
# Coordonnées
|
||||
if indice.has_coordinates():
|
||||
print(f" Coordonnées: {indice.coordinates}")
|
||||
|
||||
print()
|
||||
|
||||
# Statistiques sur la collection
|
||||
stats = indices.get_statistics()
|
||||
print("Statistiques de la collection:")
|
||||
for key, value in stats.items():
|
||||
print(f" {key}: {value}")
|
||||
print()
|
||||
|
||||
# Filtrage par qualité
|
||||
print("=== Filtrage et analyse ===")
|
||||
mauvaise_qualite = [indice for indice in indices if indice.is_poor_quality()]
|
||||
print(f"Zones avec mauvaise qualité: {len(mauvaise_qualite)}")
|
||||
for indice in mauvaise_qualite:
|
||||
print(f" - {indice.lib_zone}: {indice.get_qualificatif()}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
def example_episodes_pollution():
|
||||
"""Exemple d'utilisation des épisodes de pollution avec objets typés"""
|
||||
print("\n=== Exemple Épisodes de Pollution avec objets typés ===\n")
|
||||
|
||||
# Données de test pour épisodes
|
||||
test_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [[[2.0, 48.0], [3.0, 48.0], [3.0, 49.0], [2.0, 49.0], [2.0, 48.0]]]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code_pol": "5",
|
||||
"lib_pol": "PM10",
|
||||
"lib_zone": "Île-de-France",
|
||||
"date_dif": "2024-07-07",
|
||||
"etat": "INFORMATION ET RECOMMANDATIONS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "MultiPolygon",
|
||||
"coordinates": [[[1.0, 47.0], [2.0, 47.0], [2.0, 48.0], [1.0, 48.0], [1.0, 47.0]]]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "24",
|
||||
"code_pol": "3",
|
||||
"lib_pol": "Ozone",
|
||||
"lib_zone": "Centre-Val de Loire",
|
||||
"date_dif": "2024-07-07",
|
||||
"etat": "ALERTE"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
from atmo_data_wrapper import AtmoDataCollection
|
||||
episodes = AtmoDataCollection(test_data, 'episodes')
|
||||
|
||||
print(f"Collection: {len(episodes)} épisodes récupérés")
|
||||
print(f"Résumé: {episodes.to_summary()}\n")
|
||||
|
||||
for i, episode in enumerate(episodes):
|
||||
print(f"Épisode {i+1}:")
|
||||
print(f" Zone: {episode.lib_zone}")
|
||||
print(f" Polluant: {episode.lib_pol} (code: {episode.get_polluant_code()})")
|
||||
print(f" État: {episode.etat}")
|
||||
print(f" Alerte active: {'Oui' if episode.is_alert_active() else 'Non'}")
|
||||
print(f" Niveau d'alerte: {episode.get_alert_level()}")
|
||||
print(f" Géométrie complexe: {'Oui' if episode.is_geometry_complex() else 'Non'}")
|
||||
print()
|
||||
|
||||
def example_emissions_data():
|
||||
"""Exemple d'utilisation des données d'émissions avec objets typés"""
|
||||
print("=== Exemple Données d'Émissions avec objets typés ===\n")
|
||||
|
||||
# Données de test pour émissions
|
||||
test_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.3522, 48.8566]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code": "75056",
|
||||
"name": "Paris",
|
||||
"population": 2165423,
|
||||
"superficie": 105.4,
|
||||
"nox": 15420.5,
|
||||
"pm10": 890.2,
|
||||
"pm25": 623.8,
|
||||
"ges": 12345678.9,
|
||||
"code_pcaet": "7"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
from atmo_data_wrapper import AtmoDataCollection
|
||||
emissions = AtmoDataCollection(test_data, 'emissions')
|
||||
|
||||
print(f"Collection: {len(emissions)} données d'émissions récupérées\n")
|
||||
|
||||
for emission in emissions:
|
||||
print(f"Territoire: {emission.name}")
|
||||
print(f" Population: {emission.population:,} habitants")
|
||||
print(f" Superficie: {emission.superficie} km²")
|
||||
print(f" Secteur: {emission.get_secteur_name()}")
|
||||
print()
|
||||
|
||||
# Émissions totales
|
||||
total_emissions = emission.get_total_emissions()
|
||||
print(" Émissions totales:")
|
||||
for polluant, valeur in total_emissions.items():
|
||||
print(f" {polluant}: {valeur:,.1f} t/an")
|
||||
print()
|
||||
|
||||
# Densités et per capita
|
||||
print(" Densités d'émission (t/km²):")
|
||||
for polluant in ['nox', 'pm10', 'pm25']:
|
||||
density = emission.get_emission_density(polluant)
|
||||
print(f" {polluant.upper()}: {density:.2f}")
|
||||
|
||||
print(" Émissions par habitant (kg/hab):")
|
||||
for polluant in ['nox', 'pm10', 'pm25']:
|
||||
per_capita = emission.get_emission_per_capita(polluant) * 1000 # Convert to kg
|
||||
print(f" {polluant.upper()}: {per_capita:.2f}")
|
||||
print()
|
||||
|
||||
def example_pollen_indices():
|
||||
"""Exemple d'utilisation des indices pollen avec objets typés"""
|
||||
print("=== Exemple Indices Pollen avec objets typés ===\n")
|
||||
|
||||
# Données de test pour pollens
|
||||
test_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.3522, 48.8566]
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"alerte": True,
|
||||
"code_ambr": 5,
|
||||
"code_arm": 2,
|
||||
"code_aul": 1,
|
||||
"code_boul": 4,
|
||||
"code_gram": 3,
|
||||
"code_oliv": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
from atmo_data_wrapper import AtmoDataCollection
|
||||
pollens = AtmoDataCollection(test_data, 'pollens')
|
||||
|
||||
print(f"Collection: {len(pollens)} indices pollen récupérés\n")
|
||||
|
||||
for pollen in pollens:
|
||||
print(f"Station pollen:")
|
||||
print(f" Alerte active: {'Oui' if pollen.is_alert_active() else 'Non'}")
|
||||
|
||||
# Pollen le plus élevé
|
||||
highest_pollen, highest_code = pollen.get_highest_pollen()
|
||||
print(f" Plus haut niveau: {highest_pollen} (code: {highest_code})")
|
||||
|
||||
# Résumé de tous les pollens
|
||||
summary = pollen.get_pollens_summary()
|
||||
print(" Détail par espèce:")
|
||||
for code, info in summary.items():
|
||||
print(f" {info['espece']}: {info['qualificatif']} (code: {info['code']})")
|
||||
|
||||
# Pollens dangereux
|
||||
dangerous = pollen.get_dangerous_pollens()
|
||||
if dangerous:
|
||||
print(f" Pollens à risque élevé: {', '.join(dangerous)}")
|
||||
else:
|
||||
print(" Aucun pollen à risque élevé")
|
||||
print()
|
||||
|
||||
def example_geographic_filtering():
|
||||
"""Exemple de filtrage géographique"""
|
||||
print("=== Exemple Filtrage Géographique ===\n")
|
||||
|
||||
# Créer des données avec différentes localisations
|
||||
test_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.3522, 48.8566] # Paris
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code_qual": 3,
|
||||
"lib_zone": "Paris Centre"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.2945, 48.8584] # Proche de Paris
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "11",
|
||||
"code_qual": 2,
|
||||
"lib_zone": "Boulogne"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [5.3698, 43.2965] # Marseille (loin)
|
||||
},
|
||||
"properties": {
|
||||
"aasqa": "93",
|
||||
"code_qual": 4,
|
||||
"lib_zone": "Marseille"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
from atmo_data_wrapper import AtmoDataCollection, Coordinates
|
||||
indices = AtmoDataCollection(test_data, 'indices')
|
||||
|
||||
print(f"Collection initiale: {len(indices)} éléments")
|
||||
|
||||
# Définir un point central (Paris)
|
||||
paris_center = Coordinates(2.3522, 48.8566)
|
||||
|
||||
# Filtrer dans un rayon de 10 km autour de Paris
|
||||
nearby = indices.filter_by_coordinates(paris_center, 10.0)
|
||||
print(f"Dans un rayon de 10km de Paris: {len(nearby)} éléments")
|
||||
|
||||
for item in nearby:
|
||||
if item.has_coordinates():
|
||||
distance = item.coordinates.distance_to(paris_center)
|
||||
print(f" {item.lib_zone}: {distance:.2f} km de Paris")
|
||||
|
||||
print()
|
||||
|
||||
if __name__ == "__main__":
|
||||
example_indices_atmo()
|
||||
example_episodes_pollution()
|
||||
example_emissions_data()
|
||||
example_pollen_indices()
|
||||
example_geographic_filtering()
|
185
examples/example_save_files.py
Normal file
185
examples/example_save_files.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Exemples d'utilisation de la fonctionnalité de sauvegarde du wrapper AtmoDataClient
|
||||
"""
|
||||
|
||||
from atmo_data_wrapper import AtmoDataClient, AtmoDataException
|
||||
from atmo_data_wrapper import AASQA_CODES, POLLUANTS
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
|
||||
def main():
|
||||
"""Exemples de sauvegarde de données"""
|
||||
print("=== Exemples de sauvegarde de données API Atmo ===\n")
|
||||
|
||||
# Initialisation du client
|
||||
client = AtmoDataClient()
|
||||
|
||||
# Note: Pour ces exemples, nous utilisons des données factices
|
||||
# car nous n'avons pas d'authentification réelle
|
||||
|
||||
# Données d'exemple au format GeoJSON (structure typique de l'API)
|
||||
sample_geojson_data = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.3522, 48.8566] # Paris
|
||||
},
|
||||
"properties": {
|
||||
"code_zone": "75056",
|
||||
"nom_zone": "Paris",
|
||||
"aasqa": "11",
|
||||
"nom_aasqa": "Airparif",
|
||||
"date": "2024-07-07",
|
||||
"code_qualificatif": "2",
|
||||
"qualificatif": "Moyen",
|
||||
"polluant_principal": "PM10",
|
||||
"valeur": 45.2
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [2.2945, 48.8584] # Boulogne
|
||||
},
|
||||
"properties": {
|
||||
"code_zone": "92012",
|
||||
"nom_zone": "Boulogne-Billancourt",
|
||||
"aasqa": "11",
|
||||
"nom_aasqa": "Airparif",
|
||||
"date": "2024-07-07",
|
||||
"code_qualificatif": "3",
|
||||
"qualificatif": "Dégradé",
|
||||
"polluant_principal": "NO2",
|
||||
"valeur": 52.8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Exemple 1: Sauvegarde en JSON
|
||||
print("1. Sauvegarde en format JSON...")
|
||||
try:
|
||||
json_file = client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename="data/indices_atmo",
|
||||
file_format="json"
|
||||
)
|
||||
print(f"✅ Fichier JSON sauvegardé: {json_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur JSON: {e}")
|
||||
|
||||
# Exemple 2: Sauvegarde en GeoJSON
|
||||
print("\n2. Sauvegarde en format GeoJSON...")
|
||||
try:
|
||||
geojson_file = client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename="data/indices_atmo_geo",
|
||||
file_format="geojson"
|
||||
)
|
||||
print(f"✅ Fichier GeoJSON sauvegardé: {geojson_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur GeoJSON: {e}")
|
||||
|
||||
# Exemple 3: Sauvegarde en CSV
|
||||
print("\n3. Sauvegarde en format CSV...")
|
||||
try:
|
||||
csv_file = client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename="data/indices_atmo",
|
||||
file_format="csv"
|
||||
)
|
||||
print(f"✅ Fichier CSV sauvegardé: {csv_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur CSV: {e}")
|
||||
|
||||
# Exemple 4: Sauvegarde avec chemin complet
|
||||
print("\n4. Sauvegarde avec chemin personnalisé...")
|
||||
try:
|
||||
custom_file = client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename="exports/qualite_air/paris_2024",
|
||||
file_format="json"
|
||||
)
|
||||
print(f"✅ Fichier personnalisé sauvegardé: {custom_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur sauvegarde personnalisée: {e}")
|
||||
|
||||
# Exemple 5: Gestion d'erreurs - format invalide
|
||||
print("\n5. Test de validation - format invalide...")
|
||||
try:
|
||||
client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename="test",
|
||||
file_format="xml" # Format non supporté
|
||||
)
|
||||
print("❌ Validation échouée - format invalide accepté")
|
||||
except ValueError as e:
|
||||
print(f"✅ Validation réussie: {e}")
|
||||
|
||||
# Exemple 6: Workflow complet avec récupération de données
|
||||
print("\n6. Exemple de workflow complet (simulation)...")
|
||||
try:
|
||||
# Simulation d'un appel API réel
|
||||
print(" - Récupération des indices ATMO (simulé)...")
|
||||
# indices = client.get_indices_atmo(aasqa="11", date="2024-07-07")
|
||||
|
||||
# Utilisation des données d'exemple
|
||||
print(" - Sauvegarde des données...")
|
||||
workflow_file = client.save_to_file(
|
||||
data=sample_geojson_data,
|
||||
filename=f"exports/daily/indices_atmo_{datetime.now().strftime('%Y%m%d')}",
|
||||
file_format="csv"
|
||||
)
|
||||
print(f"✅ Workflow terminé: {workflow_file}")
|
||||
|
||||
# Affichage des informations sur le fichier
|
||||
if os.path.exists(workflow_file):
|
||||
size = os.path.getsize(workflow_file)
|
||||
print(f" - Taille du fichier: {size} bytes")
|
||||
print(f" - Nombre de lignes: {len(sample_geojson_data['features']) + 1}") # +1 pour l'en-tête
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur workflow: {e}")
|
||||
|
||||
# Exemple 7: Données sans géométrie (pour test CSV)
|
||||
print("\n7. Test CSV sans coordonnées...")
|
||||
sample_data_no_geom = {
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"geometry": None,
|
||||
"properties": {
|
||||
"code_zone": "75056",
|
||||
"nom_zone": "Paris",
|
||||
"date": "2024-07-07",
|
||||
"indice_atmo": 3,
|
||||
"qualificatif": "Dégradé"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
try:
|
||||
no_geom_file = client.save_to_file(
|
||||
data=sample_data_no_geom,
|
||||
filename="data/indices_sans_coordonnees",
|
||||
file_format="csv"
|
||||
)
|
||||
print(f"✅ CSV sans géométrie sauvegardé: {no_geom_file}")
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur CSV sans géométrie: {e}")
|
||||
|
||||
print("\n=== Exemples terminés ===")
|
||||
print("\nFichiers créés dans:")
|
||||
print("- ./data/")
|
||||
print("- ./exports/")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
324
examples/example_synthese_nancy.py
Normal file
324
examples/example_synthese_nancy.py
Normal file
|
@ -0,0 +1,324 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Vue synthétique combinée : Qualité de l'air et Pollen pour Nancy
|
||||
================================================================
|
||||
|
||||
Ce script combine les données d'indices ATMO (qualité de l'air) et
|
||||
d'indices Pollen pour la ville de Nancy (54395) afin de fournir
|
||||
une vue synthétique de la situation environnementale.
|
||||
|
||||
Fonctionnalités:
|
||||
- Récupération simultanée des indices ATMO et Pollen
|
||||
- Analyse croisée qualité air / risque pollinique
|
||||
- Vue synthétique avec recommandations
|
||||
- Affichage avec émojis et couleurs
|
||||
- Détection des risques combinés
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# Ajouter le répertoire parent au PYTHONPATH pour importer le package local
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from atmo_data_wrapper import AtmoDataClient, AASQA_CODES
|
||||
|
||||
def get_risk_level_combined(atmo_code: int, pollen_max: int, pollen_alert: bool) -> dict:
|
||||
"""Détermine le niveau de risque combiné air + pollen"""
|
||||
|
||||
# Conversion des codes en niveaux de risque (0-4)
|
||||
atmo_risk = min(atmo_code, 4) if atmo_code > 0 else 0
|
||||
pollen_risk = min(pollen_max, 4) if pollen_max > 0 else 0
|
||||
|
||||
# Bonus si alerte pollen active
|
||||
if pollen_alert:
|
||||
pollen_risk = min(pollen_risk + 1, 4)
|
||||
|
||||
# Calcul du risque combiné (moyenne pondérée)
|
||||
combined_risk = int((atmo_risk * 0.6 + pollen_risk * 0.4))
|
||||
|
||||
risk_levels = {
|
||||
0: {"level": "Très faible", "emoji": "🟢", "color": "#50F0E6", "advice": "Conditions excellentes"},
|
||||
1: {"level": "Faible", "emoji": "🟡", "color": "#50CCAA", "advice": "Conditions favorables"},
|
||||
2: {"level": "Modéré", "emoji": "🟠", "color": "#F0E641", "advice": "Prudence pour personnes sensibles"},
|
||||
3: {"level": "Élevé", "emoji": "🔴", "color": "#FF5050", "advice": "Éviter activités extérieures prolongées"},
|
||||
4: {"level": "Très élevé", "emoji": "🟣", "color": "#A020F0", "advice": "Rester à l'intérieur si possible"}
|
||||
}
|
||||
|
||||
result = risk_levels.get(combined_risk, risk_levels[2])
|
||||
result["risk_score"] = combined_risk
|
||||
result["atmo_contribution"] = atmo_risk
|
||||
result["pollen_contribution"] = pollen_risk
|
||||
|
||||
return result
|
||||
|
||||
def format_pollutants_summary(atmo_indice) -> str:
|
||||
"""Formate un résumé des polluants"""
|
||||
summary = atmo_indice.get_pollutants_summary()
|
||||
parts = []
|
||||
|
||||
for polluant, data in summary.items():
|
||||
if data['code'] > 2: # Seulement les polluants problématiques
|
||||
parts.append(f"{polluant}({data['code']})")
|
||||
|
||||
return ", ".join(parts) if parts else "Aucun polluant problématique"
|
||||
|
||||
def format_pollens_summary(pollen_indice) -> str:
|
||||
"""Formate un résumé des pollens"""
|
||||
summary = pollen_indice.get_pollens_summary()
|
||||
parts = []
|
||||
|
||||
for code_taxon, data in summary.items():
|
||||
if data['code'] >= 3: # Pollens avec indice moyen à élevé
|
||||
espece = data['espece']
|
||||
niveau = data['code']
|
||||
emoji = data['emoji']
|
||||
parts.append(f"{espece} {emoji}({niveau})")
|
||||
|
||||
return ", ".join(parts) if parts else "Tous pollens à niveau faible"
|
||||
|
||||
def get_detailed_recommendations(atmo_indice, pollen_indice, combined_risk: dict) -> list:
|
||||
"""Génère des recommandations détaillées"""
|
||||
recommendations = []
|
||||
|
||||
# Recommandations basées sur la qualité de l'air
|
||||
if atmo_indice.is_poor_quality():
|
||||
worst_pol, code = atmo_indice.get_worst_pollutant()
|
||||
recommendations.append(f"🌬️ Qualité air dégradée ({worst_pol}: niveau {code})")
|
||||
|
||||
if code >= 4:
|
||||
recommendations.append(" → Éviter le sport en extérieur")
|
||||
recommendations.append(" → Aérer pendant les pics de trafic")
|
||||
|
||||
# Recommandations basées sur les pollens
|
||||
if pollen_indice.is_alert_active():
|
||||
recommendations.append("🌸 Alerte pollen active")
|
||||
recommendations.append(" → Éviter sorties tôt le matin")
|
||||
recommendations.append(" → Garder fenêtres fermées")
|
||||
|
||||
dangerous_pollens = pollen_indice.get_dangerous_pollens()
|
||||
if dangerous_pollens:
|
||||
pollens_str = ", ".join(dangerous_pollens)
|
||||
recommendations.append(f"🤧 Pollens à risque élevé: {pollens_str}")
|
||||
recommendations.append(" → Prévoir antihistaminiques si nécessaire")
|
||||
|
||||
# Recommandations combinées
|
||||
if combined_risk["risk_score"] >= 3:
|
||||
recommendations.append("⚠️ Risque combiné élevé")
|
||||
recommendations.append(" → Limiter activités extérieures")
|
||||
recommendations.append(" → Privilégier intérieur climatisé/filtré")
|
||||
|
||||
# Recommandations positives
|
||||
if combined_risk["risk_score"] <= 1:
|
||||
recommendations.append("✅ Conditions favorables")
|
||||
recommendations.append(" → Profitez des activités extérieures")
|
||||
recommendations.append(" → Idéal pour aérer le logement")
|
||||
|
||||
return recommendations
|
||||
|
||||
def display_synthesis_header():
|
||||
"""Affiche l'en-tête de la synthèse"""
|
||||
print("=" * 70)
|
||||
print("🌍 SYNTHÈSE ENVIRONNEMENTALE - Nancy")
|
||||
print("=" * 70)
|
||||
print(f"📅 Date: {datetime.now().strftime('%d/%m/%Y à %H:%M')}")
|
||||
print(f"📍 Ville: Nancy (54395) - Région Grand Est")
|
||||
print()
|
||||
|
||||
def display_section_header(title: str, emoji: str = "📊"):
|
||||
"""Affiche un en-tête de section"""
|
||||
print(f"{emoji} {title}")
|
||||
print("-" * 50)
|
||||
|
||||
def main():
|
||||
"""Fonction principale"""
|
||||
display_synthesis_header()
|
||||
|
||||
try:
|
||||
# Connexion au client
|
||||
print("🔗 Connexion à l'API Atmo Data...")
|
||||
client = AtmoDataClient()
|
||||
success = client.auto_login()
|
||||
|
||||
if not success:
|
||||
print("❌ Échec de la connexion")
|
||||
return
|
||||
|
||||
print("✅ Connexion réussie")
|
||||
print()
|
||||
|
||||
# === RÉCUPÉRATION DES DONNÉES ===
|
||||
print("📥 Récupération des données...")
|
||||
|
||||
# Données ATMO spécifiques à Nancy (code INSEE 54395)
|
||||
atmo_data = client.get_indices_atmo(
|
||||
code_zone="54395", # Code INSEE de Nancy
|
||||
format="geojson"
|
||||
)
|
||||
|
||||
# Données Pollen pour Nancy
|
||||
pollen_data = client.get_indices_pollens(
|
||||
code_zone="54395",
|
||||
format="geojson"
|
||||
)
|
||||
|
||||
if not atmo_data or len(atmo_data) == 0:
|
||||
print("❌ Aucune donnée ATMO trouvée pour Nancy (54395)")
|
||||
print("ℹ️ Essai avec les données régionales...")
|
||||
|
||||
# Fallback: récupérer les données régionales du Grand Est
|
||||
atmo_data = client.get_indices_atmo(aasqa="44", format="geojson")
|
||||
|
||||
if not atmo_data or len(atmo_data) == 0:
|
||||
print("❌ Aucune donnée ATMO trouvée pour la région Grand Est")
|
||||
return
|
||||
else:
|
||||
print(f"✅ Données régionales récupérées ({len(atmo_data)} stations)")
|
||||
|
||||
if not pollen_data or len(pollen_data) == 0:
|
||||
print("❌ Aucune donnée Pollen trouvée pour Nancy")
|
||||
return
|
||||
|
||||
# Sélection des données pertinentes
|
||||
# Pour ATMO: prendre la première donnée (spécifique à Nancy si disponible)
|
||||
atmo_indice = atmo_data[0]
|
||||
|
||||
# Pour Pollen: prendre la première donnée
|
||||
pollen_indice = pollen_data[0]
|
||||
|
||||
print(f"✅ Données récupérées - ATMO: {atmo_indice.lib_zone}, Pollen: {pollen_indice.lib_zone}")
|
||||
print()
|
||||
|
||||
# === ANALYSE QUALITÉ DE L'AIR ===
|
||||
display_section_header("QUALITÉ DE L'AIR", "🌬️")
|
||||
|
||||
print(f"Zone: {atmo_indice.lib_zone}")
|
||||
print(f"Indice global: {atmo_indice.get_qualificatif()} {atmo_indice.get_emoji()} (niveau {atmo_indice.code_qual})")
|
||||
|
||||
hex_color, rgb_color = atmo_indice.get_color()
|
||||
print(f"Couleur: {hex_color}")
|
||||
|
||||
# Polluants problématiques
|
||||
worst_pol, worst_code = atmo_indice.get_worst_pollutant()
|
||||
print(f"Polluant principal: {worst_pol} (niveau {worst_code})")
|
||||
|
||||
# Résumé des polluants
|
||||
pollutants_summary = format_pollutants_summary(atmo_indice)
|
||||
print(f"Polluants élevés: {pollutants_summary}")
|
||||
|
||||
# Coordonnées et données réglementaires
|
||||
if atmo_indice.has_coordinates():
|
||||
print(f"Coordonnées: {atmo_indice.coordinates}")
|
||||
|
||||
print(f"Type de zone: {atmo_indice.type_zone or 'Non spécifié'}")
|
||||
print(f"Source: {atmo_indice.get_source()}")
|
||||
print()
|
||||
|
||||
# === ANALYSE POLLEN ===
|
||||
display_section_header("INDICES POLLEN", "🌸")
|
||||
|
||||
print(f"Zone: {pollen_indice.lib_zone}")
|
||||
print(f"Alerte active: {'✅ OUI' if pollen_indice.is_alert_active() else '❌ Non'}")
|
||||
|
||||
# Pollen le plus élevé
|
||||
highest_pollen, highest_code = pollen_indice.get_highest_pollen()
|
||||
if highest_code > 0:
|
||||
highest_name = pollen_indice.get_pollens_summary()[highest_pollen]['espece']
|
||||
highest_emoji = pollen_indice.get_pollens_summary()[highest_pollen]['emoji']
|
||||
print(f"Pollen dominant: {highest_name} {highest_emoji} (niveau {highest_code})")
|
||||
else:
|
||||
print("Pollen dominant: Aucun pollen détecté")
|
||||
|
||||
# Taxons responsables selon l'API
|
||||
responsible_pollens = pollen_indice.get_responsible_pollens()
|
||||
if responsible_pollens:
|
||||
print(f"Taxons responsables: {', '.join(responsible_pollens)}")
|
||||
|
||||
# Résumé des pollens élevés
|
||||
pollens_summary = format_pollens_summary(pollen_indice)
|
||||
print(f"Pollens à surveiller: {pollens_summary}")
|
||||
|
||||
# Concentration la plus élevée
|
||||
highest_conc_taxon, highest_conc_value = pollen_indice.get_highest_concentration()
|
||||
if highest_conc_value > 0:
|
||||
conc_name = pollen_indice.get_pollens_summary()[highest_conc_taxon]['espece']
|
||||
print(f"Concentration max: {conc_name} ({highest_conc_value:.1f} grains/m³)")
|
||||
|
||||
print(f"Source: {pollen_indice.get_source()}")
|
||||
print()
|
||||
|
||||
# === ANALYSE COMBINÉE ===
|
||||
display_section_header("RISQUE COMBINÉ", "⚖️")
|
||||
|
||||
# Calcul du risque combiné
|
||||
combined_risk = get_risk_level_combined(
|
||||
atmo_indice.code_qual,
|
||||
highest_code,
|
||||
pollen_indice.is_alert_active()
|
||||
)
|
||||
|
||||
print(f"Niveau de risque: {combined_risk['level']} {combined_risk['emoji']}")
|
||||
print(f"Score global: {combined_risk['risk_score']}/4")
|
||||
print(f" • Contribution air: {combined_risk['atmo_contribution']}/4")
|
||||
print(f" • Contribution pollen: {combined_risk['pollen_contribution']}/4")
|
||||
print(f"Conseil général: {combined_risk['advice']}")
|
||||
print()
|
||||
|
||||
# === RECOMMANDATIONS ===
|
||||
display_section_header("RECOMMANDATIONS", "💡")
|
||||
|
||||
recommendations = get_detailed_recommendations(atmo_indice, pollen_indice, combined_risk)
|
||||
|
||||
if recommendations:
|
||||
for i, rec in enumerate(recommendations, 1):
|
||||
print(f"{rec}")
|
||||
else:
|
||||
print("✅ Aucune recommandation particulière")
|
||||
print(" Conditions normales pour toutes activités")
|
||||
|
||||
print()
|
||||
|
||||
# === RÉSUMÉ TECHNIQUE ===
|
||||
display_section_header("INFORMATIONS TECHNIQUES", "🔬")
|
||||
|
||||
print("Qualité de l'air:")
|
||||
print(f" • Date échéance: {atmo_indice.date_ech}")
|
||||
print(f" • Date diffusion: {atmo_indice.date_dif}")
|
||||
print(f" • AASQA: {atmo_indice.get_aasqa_name()}")
|
||||
|
||||
# Concentrations si disponibles
|
||||
concentrations = atmo_indice.get_concentrations()
|
||||
significant_conc = {k: v for k, v in concentrations.items() if v > 0}
|
||||
if significant_conc:
|
||||
print(" • Concentrations (μg/m³):")
|
||||
for polluant, conc in significant_conc.items():
|
||||
print(f" - {polluant}: {conc}")
|
||||
|
||||
print()
|
||||
print("Pollen:")
|
||||
all_concentrations = pollen_indice.get_concentrations()
|
||||
significant_pollen = {k: v for k, v in all_concentrations.items() if v > 0}
|
||||
if significant_pollen:
|
||||
print(" • Concentrations (grains/m³):")
|
||||
for taxon, conc in significant_pollen.items():
|
||||
taxon_name = pollen_indice.get_pollens_summary()[taxon]['espece']
|
||||
print(f" - {taxon_name}: {conc:.1f}")
|
||||
|
||||
print()
|
||||
|
||||
# === FOOTER ===
|
||||
print("=" * 70)
|
||||
print("🌱 Données fournies par Atmo France et les AASQA")
|
||||
print("📊 Synthèse générée par Atmo Data Wrapper")
|
||||
print("=" * 70)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de l'exécution: {e}")
|
||||
import traceback
|
||||
print("\nDétails de l'erreur:")
|
||||
print(traceback.format_exc())
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
166
examples/example_usage.py
Normal file
166
examples/example_usage.py
Normal file
|
@ -0,0 +1,166 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Exemples d'utilisation du wrapper AtmoDataClient
|
||||
"""
|
||||
|
||||
from atmo_data_wrapper import AtmoDataClient, AtmoDataException
|
||||
from atmo_data_wrapper import AASQA_CODES, POLLUANTS
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
def main():
|
||||
# Initialisation du client
|
||||
client = AtmoDataClient()
|
||||
|
||||
# Authentification automatique avec credentials.json
|
||||
try:
|
||||
success = client.auto_login()
|
||||
if not success:
|
||||
print("Échec de l'authentification")
|
||||
return
|
||||
print("Connexion réussie avec credentials.json !")
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur d'authentification: {e}")
|
||||
print("💡 Assurez-vous d'avoir créé le fichier credentials.json")
|
||||
print(" Utilisez credentials.json.example comme modèle")
|
||||
return
|
||||
|
||||
# Exemple 1: Récupération des indices ATMO d'aujourd'hui
|
||||
print("\n=== Indices ATMO d'aujourd'hui ===")
|
||||
try:
|
||||
today = datetime.now().strftime("%Y-%m-%d")
|
||||
indices = client.get_indices_atmo(
|
||||
date=today,
|
||||
aasqa="11", # Spécifier une région pour éviter erreur serveur
|
||||
format="geojson"
|
||||
)
|
||||
print(f"Nombre d'indices récupérés: {len(indices)}")
|
||||
print(f"Résumé: {indices.to_summary()}")
|
||||
|
||||
# Exemples avec objets typés
|
||||
if len(indices) > 0:
|
||||
first_indice = indices[0]
|
||||
print(f"Premier indice - Zone: {first_indice.lib_zone}")
|
||||
print(f"Qualité: {first_indice.get_qualificatif()}")
|
||||
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
# Exemple 2: Récupération des épisodes de pollution en cours
|
||||
print("\n=== Épisodes de pollution en cours ===")
|
||||
try:
|
||||
episodes = client.get_episodes_3jours(
|
||||
format="geojson",
|
||||
aasqa="11", # Île-de-France
|
||||
polluant=POLLUANTS[2] # PM10
|
||||
)
|
||||
print(f"Nombre d'épisodes: {len(episodes)}")
|
||||
|
||||
# Analyser les alertes
|
||||
alerts_actives = [ep for ep in episodes if ep.is_alert_active()]
|
||||
print(f"Alertes actives: {len(alerts_actives)}")
|
||||
|
||||
if alerts_actives:
|
||||
for alert in alerts_actives[:3]: # Max 3 exemples
|
||||
print(f" - {alert.lib_zone}: {alert.get_alert_level()}")
|
||||
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
# Exemple 3: Données d'émissions pour l'Île-de-France
|
||||
print(f"\n=== Émissions {AASQA_CODES['11']} ===")
|
||||
try:
|
||||
emissions = client.get_emissions(
|
||||
aasqa="11", # Île-de-France
|
||||
echelle="region",
|
||||
format="geojson"
|
||||
)
|
||||
print(f"Données d'émissions récupérées: {len(emissions)}")
|
||||
|
||||
# Analyser les émissions
|
||||
if len(emissions) > 0:
|
||||
em = emissions[0]
|
||||
print(f"Territoire: {em.name}")
|
||||
print(f"Population: {em.population:,.0f} habitants")
|
||||
total_em = em.get_total_emissions()
|
||||
print(f"Émissions NOx: {total_em['NOx']:,.1f} t/an")
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
# Exemple 4: Indices pollen avec alerte
|
||||
print("\n=== Indices pollen avec alerte ===")
|
||||
try:
|
||||
pollens = client.get_indices_pollens(
|
||||
format="geojson",
|
||||
aasqa="11", # Île-de-France
|
||||
alerte=True,
|
||||
with_geom=True
|
||||
)
|
||||
print(f"Nombre d'alertes pollen: {len(pollens)}")
|
||||
|
||||
# Analyser les pollens dangereux
|
||||
if len(pollens) > 0:
|
||||
dangerous_pollens = []
|
||||
for pollen in pollens[:5]: # Max 5 exemples
|
||||
dangerous = pollen.get_dangerous_pollens()
|
||||
if dangerous:
|
||||
dangerous_pollens.extend(dangerous)
|
||||
|
||||
if dangerous_pollens:
|
||||
print(f"Pollens à risque élevé: {', '.join(set(dangerous_pollens))}")
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
# Exemple 5: Recherche dans une zone géographique (bounding box)
|
||||
print("\n=== Recherche dans une zone géographique ===")
|
||||
try:
|
||||
# Bounding box approximative de Paris
|
||||
bbox = "2.2 48.8 2.4 48.9"
|
||||
indices_paris = client.get_indices_atmo(
|
||||
bounding_box=bbox,
|
||||
date=today,
|
||||
format="geojson"
|
||||
)
|
||||
print(f"Indices dans la zone Paris: {len(indices_paris)}")
|
||||
|
||||
# Analyser la qualité
|
||||
if len(indices_paris) > 0:
|
||||
stats = indices_paris.get_statistics()
|
||||
qs = stats['quality_stats']
|
||||
print(f"Qualité moyenne: {qs['moyenne']:.1f}/7")
|
||||
print(f"Bonne qualité: {qs['bon_pourcentage']:.1f}%")
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
# Exemple 6: Données historiques
|
||||
print("\n=== Données historiques ===")
|
||||
try:
|
||||
# Episodes d'il y a 30 jours
|
||||
date_historique = (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d")
|
||||
episodes_historiques = client.get_episodes_historique(
|
||||
date=today,
|
||||
date_historique=date_historique,
|
||||
aasqa="11", # Île-de-France
|
||||
format="geojson"
|
||||
)
|
||||
print(f"Épisodes sur 30 jours: {len(episodes_historiques)}")
|
||||
|
||||
# Analyser l'évolution
|
||||
if len(episodes_historiques) > 0:
|
||||
alerts_historiques = [ep for ep in episodes_historiques if ep.is_alert_active()]
|
||||
print(f"Alertes historiques: {len(alerts_historiques)}")
|
||||
|
||||
# Compter par polluant
|
||||
polluants_hist = {}
|
||||
for ep in episodes_historiques:
|
||||
pol = ep.lib_pol
|
||||
polluants_hist[pol] = polluants_hist.get(pol, 0) + 1
|
||||
|
||||
print("Répartition par polluant:")
|
||||
for pol, count in polluants_hist.items():
|
||||
print(f" {pol}: {count} épisodes")
|
||||
except AtmoDataException as e:
|
||||
print(f"Erreur: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
126
examples/setup_credentials.py
Normal file
126
examples/setup_credentials.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Script d'aide à la configuration des credentials
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from getpass import getpass
|
||||
|
||||
def setup_credentials():
|
||||
"""Guide l'utilisateur pour configurer ses credentials"""
|
||||
print("=== Configuration des credentials Atmo Data ===\n")
|
||||
|
||||
credentials_file = "credentials.json"
|
||||
example_file = "credentials.json.example"
|
||||
|
||||
# Vérifier si le fichier existe déjà
|
||||
if os.path.exists(credentials_file):
|
||||
response = input(f"Le fichier {credentials_file} existe déjà. Le remplacer ? (y/n): ")
|
||||
if response.lower() != 'y':
|
||||
print("Configuration annulée.")
|
||||
return
|
||||
|
||||
# Vérifier la présence du fichier exemple
|
||||
if not os.path.exists(example_file):
|
||||
print(f"❌ Fichier exemple {example_file} manquant.")
|
||||
print("Création du fichier exemple...")
|
||||
|
||||
example_content = {
|
||||
"username": "votre_nom_utilisateur",
|
||||
"password": "votre_mot_de_passe",
|
||||
"api_url": "https://api.atmo-data.org"
|
||||
}
|
||||
|
||||
with open(example_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(example_content, f, indent=2, ensure_ascii=False)
|
||||
print(f"✅ Fichier {example_file} créé.")
|
||||
|
||||
print("\nSaisie des credentials :")
|
||||
print("(Laissez vide pour utiliser la valeur par défaut)")
|
||||
|
||||
# Charger les valeurs par défaut depuis l'exemple
|
||||
try:
|
||||
with open(example_file, 'r', encoding='utf-8') as f:
|
||||
defaults = json.load(f)
|
||||
except:
|
||||
defaults = {}
|
||||
|
||||
# Saisie interactive
|
||||
username = input(f"Nom d'utilisateur [{defaults.get('username', '')}]: ").strip()
|
||||
if not username:
|
||||
username = defaults.get('username', '')
|
||||
|
||||
password = getpass(f"Mot de passe [{defaults.get('password', '')}]: ").strip()
|
||||
if not password:
|
||||
password = defaults.get('password', '')
|
||||
|
||||
api_url = input(f"URL de l'API [{defaults.get('api_url', 'https://api.atmo-data.org')}]: ").strip()
|
||||
if not api_url:
|
||||
api_url = defaults.get('api_url', 'https://api.atmo-data.org')
|
||||
|
||||
# Vérifier que les champs obligatoires sont remplis
|
||||
if not username or not password:
|
||||
print("❌ Le nom d'utilisateur et le mot de passe sont obligatoires.")
|
||||
return False
|
||||
|
||||
# Créer le fichier credentials
|
||||
credentials = {
|
||||
"username": username,
|
||||
"password": password,
|
||||
"api_url": api_url
|
||||
}
|
||||
|
||||
try:
|
||||
with open(credentials_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(credentials, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print(f"\n✅ Fichier {credentials_file} créé avec succès !")
|
||||
print("\nPour tester votre configuration :")
|
||||
print(" python test_real_connection.py")
|
||||
|
||||
# Vérifier que le fichier est dans .gitignore
|
||||
gitignore_file = ".gitignore"
|
||||
if os.path.exists(gitignore_file):
|
||||
with open(gitignore_file, 'r') as f:
|
||||
content = f.read()
|
||||
if credentials_file not in content:
|
||||
print(f"\n⚠️ Attention: {credentials_file} n'est pas dans .gitignore")
|
||||
add_to_gitignore = input("Ajouter à .gitignore ? (y/n): ")
|
||||
if add_to_gitignore.lower() == 'y':
|
||||
with open(gitignore_file, 'a') as f:
|
||||
f.write(f"\n# Fichiers de credentials\n{credentials_file}\n")
|
||||
print("✅ Ajouté à .gitignore")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors de la création du fichier: {e}")
|
||||
return False
|
||||
|
||||
def test_configuration():
|
||||
"""Test rapide de la configuration"""
|
||||
print("\n=== Test de la configuration ===")
|
||||
|
||||
try:
|
||||
from atmo_data_wrapper import AtmoDataClient
|
||||
|
||||
client = AtmoDataClient()
|
||||
credentials = client._load_credentials()
|
||||
|
||||
print("✅ Fichier credentials.json lu avec succès")
|
||||
print(f" Nom d'utilisateur: {credentials['username']}")
|
||||
print(f" URL API: {credentials.get('api_url', 'URL par défaut')}")
|
||||
|
||||
# Test de connexion (simulation)
|
||||
print("\nPour tester la connexion réelle à l'API, exécutez :")
|
||||
print(" python test_real_connection.py")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Erreur lors du test: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = setup_credentials()
|
||||
if success:
|
||||
test_configuration()
|
Loading…
Add table
Add a link
Reference in a new issue