333 lines
No EOL
14 KiB
Python
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() |