py_atmo_data_wrapper/demos/demo_pollen_functions.py
2025-07-14 17:56:57 +02:00

333 lines
No EOL
14 KiB
Python

#!/usr/bin/env python3
"""
Script de démonstration de toutes les fonctions du datamodel IndicePollen
Utilise les données réelles de l'API pour Tomblaine (aujourd'hui)
Idéal pour documentation et exemples
"""
from atmo_data_wrapper import AtmoDataClient, AtmoDataException
from atmo_data_wrapper import CODE_TAXON
from datetime import datetime
import sys
def demo_pollen_functions():
"""Démonstration complète des fonctions IndicePollen avec données réelles"""
# Configuration
CODE_INSEE_TOMBLAINE = "54526"
AASQA_GRAND_EST = "44"
today = datetime.now().strftime('%Y-%m-%d')
print("🌸 DÉMONSTRATION DES FONCTIONS INDICEPOLLEN")
print("=" * 55)
print(f"📍 Ville: Tomblaine (INSEE: {CODE_INSEE_TOMBLAINE})")
print(f"🗓️ Date: {today}")
print(f"🏛️ AASQA: {AASQA_GRAND_EST} (Grand Est)")
print()
try:
# Connexion et récupération des données
print("🔐 Connexion à l'API...")
client = AtmoDataClient()
success = client.auto_login()
if not success:
print("❌ Échec de la connexion à l'API")
return False
print("✅ Connecté avec succès !")
# Récupération des données pollen
print(f"🌸 Récupération des indices pollen pour {today}...")
pollens = client.get_indices_pollens(
format="geojson",
date=today,
aasqa=AASQA_GRAND_EST,
code_zone=CODE_INSEE_TOMBLAINE,
with_geom=False
)
if not pollens or len(pollens) == 0:
print("❌ Aucune donnée pollen trouvée")
return False
print(f"{len(pollens)} station(s) trouvée(s)")
# Utiliser la première station pour la démo
pollen = pollens[0]
print(f"📍 Station sélectionnée: {pollen.lib_zone}")
print()
# === DÉMONSTRATION DES PROPRIÉTÉS DE BASE ===
print("📊 === PROPRIÉTÉS DE BASE (héritées d'AtmoDataBase) ===")
print()
print("🏛️ INFORMATIONS GÉNÉRALES:")
print(f" • AASQA: {pollen.aasqa}")
print(f" • Zone: {pollen.lib_zone}")
print(f" • Source: {pollen.source}")
print(f" • Alerte active: {pollen.alerte}")
print()
print("🗺️ COORDONNÉES:")
if pollen.has_coordinates():
coords = pollen.get_coordinates()
print(f" • Latitude: {coords.latitude:.6f}")
print(f" • Longitude: {coords.longitude:.6f}")
else:
print(" • Pas de coordonnées disponibles")
print()
print("🎨 FONCTIONS CENTRALISÉES:")
for level in [0, 1, 2, 3, 4]:
emoji_round = pollen.get_emoji_by_level(level, "round")
emoji_square = pollen.get_emoji_by_level(level, "square")
color_hex, color_rgb = pollen.get_color_by_level(level)
print(f" • Niveau {level}: {emoji_round}{emoji_square} {color_hex} {color_rgb}")
print()
# === DÉMONSTRATION DES PROPRIÉTÉS SPÉCIFIQUES POLLEN ===
print("🌿 === PROPRIÉTÉS SPÉCIFIQUES POLLEN ===")
print()
print("📈 CODES PAR TAXON:")
print(f" • Ambroisie (ambr): {pollen.code_ambr}")
print(f" • Armoise (arm): {pollen.code_arm}")
print(f" • Aulne (aul): {pollen.code_aul}")
print(f" • Bouleau (boul): {pollen.code_boul}")
print(f" • Graminées (gram): {pollen.code_gram}")
print(f" • Olivier (oliv): {pollen.code_oliv}")
print()
print("🔬 CONCENTRATIONS (grains/m³):")
print(f" • Ambroisie: {pollen.conc_ambr:.1f}")
print(f" • Armoise: {pollen.conc_arm:.1f}")
print(f" • Aulne: {pollen.conc_aul:.1f}")
print(f" • Bouleau: {pollen.conc_boul:.1f}")
print(f" • Graminées: {pollen.conc_gram:.1f}")
print(f" • Olivier: {pollen.conc_oliv:.1f}")
print()
print("🎯 TAXONS RESPONSABLES DE L'INDICE:")
print(f" • pollen_resp (raw): '{pollen.pollen_resp}'")
print()
# === DÉMONSTRATION DES MÉTHODES HELPER ===
print("🛠️ === MÉTHODES HELPER ===")
print()
# 1. is_alert_active()
print("🚨 1. DÉTECTION D'ALERTE:")
alert_active = pollen.is_alert_active()
print(f" • is_alert_active(): {alert_active}")
if alert_active:
print(" → Alerte pollen active !")
else:
print(" → Pas d'alerte pollen")
print()
# 2. get_highest_pollen()
print("🏆 2. POLLEN LE PLUS ÉLEVÉ:")
highest_taxon, highest_code = pollen.get_highest_pollen()
highest_name = CODE_TAXON.get(highest_taxon, highest_taxon.title())
print(f" • get_highest_pollen(): ('{highest_taxon}', {highest_code})")
print(f" → Espèce: {highest_name}")
print(f" → Niveau: {highest_code}")
print()
# 3. get_highest_concentration()
print("🔬 3. CONCENTRATION LA PLUS ÉLEVÉE:")
highest_conc_taxon, highest_conc_value = pollen.get_highest_concentration()
highest_conc_name = CODE_TAXON.get(highest_conc_taxon, highest_conc_taxon.title())
print(f" • get_highest_concentration(): ('{highest_conc_taxon}', {highest_conc_value})")
print(f" → Espèce: {highest_conc_name}")
print(f" → Concentration: {highest_conc_value:.1f} grains/m³")
print()
# 4. get_dangerous_pollens()
print("⚠️ 4. POLLENS DANGEREUX (niveau ≥ 4):")
dangerous = pollen.get_dangerous_pollens()
print(f" • get_dangerous_pollens(): {dangerous}")
if dangerous:
dangerous_names = [CODE_TAXON.get(p, p.title()) for p in dangerous]
print(f" → Espèces à risque: {', '.join(dangerous_names)}")
else:
print(" → Aucun pollen à risque élevé")
print()
# 5. get_responsible_pollens() - NOUVELLE MÉTHODE
print("🎯 5. TAXONS RESPONSABLES DE L'INDICE (API):")
responsible = pollen.get_responsible_pollens()
print(f" • get_responsible_pollens(): {responsible}")
if responsible:
print(f" → Espèces responsables selon l'API: {', '.join(responsible)}")
else:
print(" → Aucun taxon responsable spécifié par l'API")
print()
# 6. get_concentrations()
print("📊 6. TOUTES LES CONCENTRATIONS:")
concentrations = pollen.get_concentrations()
print(f" • get_concentrations(): {concentrations}")
print(" → Détail:")
for taxon, conc in concentrations.items():
taxon_name = CODE_TAXON.get(taxon, taxon.title())
print(f" - {taxon_name}: {conc:.1f} grains/m³")
print()
# 7. get_pollens_summary()
print("📋 7. RÉSUMÉ COMPLET:")
summary = pollen.get_pollens_summary()
print(f" • get_pollens_summary():")
print(" → Structure complète par taxon:")
for code_taxon, info in summary.items():
if info['code'] > 0: # Afficher seulement les pollens détectés
print(f" - {code_taxon}:")
print(f" * Code: {info['code']}")
print(f" * Espèce: {info['espece']}")
print(f" * Qualificatif: {info['qualificatif']}")
print(f" * Concentration: {info['concentration']:.1f} gr/m³")
print(f" * Couleur: {info['couleur']}")
print(f" * Émoji rond: {info['emoji_round']}")
print(f" * Émoji carré: {info['emoji_square']}")
print()
# 8. Test des styles d'émojis
print("🎨 8. TEST DES STYLES D'ÉMOJIS:")
summary_round = pollen.get_pollens_summary("round")
summary_square = pollen.get_pollens_summary("square")
print(" • Comparaison des styles par défaut:")
for code_taxon in ['arm', 'gram']: # Tester avec les pollens détectés
if summary_round[code_taxon]['code'] > 0:
round_emoji = summary_round[code_taxon]['emoji']
square_emoji = summary_square[code_taxon]['emoji']
espece = summary_round[code_taxon]['espece']
print(f" - {espece}: Rond={round_emoji} | Carré={square_emoji}")
print()
# === DÉMONSTRATION DES MÉTHODES STRING ===
print("📝 === REPRÉSENTATION STRING ===")
print()
print("🔤 MÉTHODE __str__():")
print(f" • str(pollen): '{str(pollen)}'")
print()
# === EXEMPLES D'UTILISATION PRATIQUE ===
print("💡 === EXEMPLES D'UTILISATION PRATIQUE ===")
print()
print("🎯 ANALYSE RAPIDE:")
print(f" • Niveau global le plus élevé: {highest_name} (niveau {highest_code})")
print(f" • Concentration maximale: {highest_conc_name} ({highest_conc_value:.1f} gr/m³)")
if alert_active:
print(" • ⚠️ ALERTE ACTIVE - Précautions recommandées")
if dangerous:
print(f" • 🚨 POLLENS À RISQUE: {', '.join([CODE_TAXON.get(p, p) for p in dangerous])}")
else:
print(" • ✅ Aucun pollen à risque élevé")
print()
print("📈 DÉTECTION DE TENDANCES:")
detected_pollens = [taxon for taxon, info in summary.items() if info['code'] > 0]
significant_pollens = [taxon for taxon, info in summary.items() if info['code'] >= 2]
print(f" • Pollens détectés: {len(detected_pollens)} espèces")
print(f" • Pollens significatifs (≥2): {len(significant_pollens)} espèces")
if significant_pollens:
sig_names = [CODE_TAXON.get(p, p) for p in significant_pollens]
print(f"{', '.join(sig_names)}")
print()
print("🔍 FILTRAGE AVANCÉ:")
# Exemple de filtrage par concentration
high_conc = {t: c for t, c in concentrations.items() if c > 5.0}
if high_conc:
print(" • Concentrations élevées (>5 gr/m³):")
for taxon, conc in high_conc.items():
taxon_name = CODE_TAXON.get(taxon, taxon.title())
print(f"{taxon_name}: {conc:.1f} gr/m³")
else:
print(" • Aucune concentration élevée (>5 gr/m³)")
print()
# === INFORMATIONS TECHNIQUES ===
print("🔧 === INFORMATIONS TECHNIQUES ===")
print()
print("📦 STRUCTURE DE DONNÉES:")
print(f" • Type d'objet: {type(pollen).__name__}")
print(f" • Classe parente: {type(pollen).__bases__[0].__name__}")
print(f" • Propriétés disponibles: {len(pollen.properties)} champs")
print(f" • Géométrie: {'Oui' if pollen.has_coordinates() else 'Non'}")
print()
print("🎨 MÉTHODES HÉRITÉES:")
inherited_methods = [
'get_emoji_by_level()', 'get_color_by_level()', 'has_coordinates()',
'get_coordinates()', 'get_source()'
]
print(f" • Méthodes de AtmoDataBase: {', '.join(inherited_methods)}")
print()
specific_methods = [
'is_alert_active()', 'get_highest_pollen()', 'get_highest_concentration()',
'get_dangerous_pollens()', 'get_responsible_pollens()', 'get_concentrations()', 'get_pollens_summary()'
]
print(f" • Méthodes spécifiques IndicePollen: {', '.join(specific_methods)}")
print()
print("🎨 NOUVEAUTÉS ÉMOJIS:")
print(" • get_emoji_by_level(level, style) - style='round'|'square'")
print(" • get_emoji(style) - pour IndiceAtmo avec choix de style")
print(" • get_pollens_summary(emoji_style) - résumé avec style d'émoji")
print(" • Chaque résumé inclut emoji_round ET emoji_square")
print()
print("📋 CONFORMITÉ NOTICE OFFICIELLE (1er avril 2025):")
print(" • Tous les champs de la notice officielle sont supportés")
print(" • Classes IndiceAtmo et IndicePollen conformes aux spécifications")
print(" • Nouvelles propriétés pour IndiceAtmo : type_zone, coordonnées réglementaires")
print(" • Concentrations facultatives ajoutées selon la notice")
print(" • Méthodes basées sur les règles officielles de calcul")
print(" • Codes couleur et qualificatifs conformes au tableau page 6")
print()
print("✅ === DÉMONSTRATION TERMINÉE ===")
print()
print("📚 Ce script illustre toutes les fonctionnalités de la classe IndicePollen")
print("🔧 Utilisez ces exemples pour votre documentation et vos développements")
print()
return True
except AtmoDataException as e:
print(f"❌ Erreur API: {e}")
return False
except Exception as e:
print(f"❌ Erreur inattendue: {e}")
import traceback
traceback.print_exc()
return False
def main():
"""Point d'entrée principal"""
print("🌸 Démonstration des fonctions IndicePollen")
print("=" * 55)
print()
success = demo_pollen_functions()
if not success:
print("\n❌ La démonstration s'est terminée avec des erreurs")
sys.exit(1)
else:
print("🎉 Démonstration terminée avec succès !")
sys.exit(0)
if __name__ == "__main__":
main()