From 6c1465bd6b0d3b21dfe1a2ccaa9269f14312c1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Peccini?= Date: Thu, 31 Jul 2025 10:29:29 +0200 Subject: [PATCH] =?UTF-8?q?fix(ISG=20en=20dur)=20:=20l'isg=20=C3=A9tait=20?= =?UTF-8?q?d=C3=A9fini=20en=20dur=20et=20non=20=C3=A0=20partir=20du=20fich?= =?UTF-8?q?ier=20config.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/graph_utils.py | 98 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/utils/graph_utils.py b/utils/graph_utils.py index eb726aa..0e36e46 100644 --- a/utils/graph_utils.py +++ b/utils/graph_utils.py @@ -3,6 +3,8 @@ import pandas as pd import logging import streamlit as st import json +import yaml +import pathlib from networkx.drawing.nx_agraph import read_dot # Configuration Gitea @@ -129,35 +131,102 @@ def recuperer_donnees_2(graph, noeuds_2): return donnees -def couleur_noeud(n, niveaux, G): +def load_seuils_config(path: str = "assets/config.yaml") -> dict: + """ + Charge les seuils depuis le fichier de configuration YAML. + + Args: + path (str): Chemin vers le fichier de configuration. + + Returns: + dict: Dictionnaire contenant les seuils pour chaque indice. + """ + try: + data = yaml.safe_load(pathlib.Path(path).read_text(encoding="utf-8")) + return data.get("seuils", {}) + except Exception as e: + logging.warning(f"Erreur lors du chargement des seuils depuis {path}: {e}") + # Valeurs par défaut en cas d'erreur + return { + "ISG": {"vert": {"max": 40}, "orange": {"min": 40, "max": 70}, "rouge": {"min": 70}}, + "IHH": {"vert": {"max": 15}, "orange": {"min": 15, "max": 25}, "rouge": {"min": 25}}, + "IVC": {"vert": {"max": 15}, "orange": {"min": 15, "max": 60}, "rouge": {"min": 60}} + } + + +def determiner_couleur_par_seuil(valeur: int, seuils_indice: dict) -> str: + """ + Détermine la couleur en fonction de la valeur et des seuils configurés. + Logique alignée avec determine_threshold_color du projet. + + Args: + valeur (int): Valeur de l'indice à évaluer. + seuils_indice (dict): Seuils pour cet indice depuis la configuration. + + Returns: + str: Couleur correspondante ("darkgreen", "orange", "darkred", "gray"). + """ + if valeur < 0: + return "gray" + + # Vérifier d'abord le seuil rouge (priorité la plus haute) + if "rouge" in seuils_indice and "min" in seuils_indice["rouge"]: + if valeur >= seuils_indice["rouge"]["min"]: + return "darkred" + + # Ensuite le seuil orange + if "orange" in seuils_indice and "min" in seuils_indice["orange"] and "max" in seuils_indice["orange"]: + if valeur >= seuils_indice["orange"]["min"] and valeur < seuils_indice["orange"]["max"]: + return "orange" + + # Seuil vert (valeurs inférieures au seuil orange) + if "vert" in seuils_indice and "max" in seuils_indice["vert"]: + if valeur < seuils_indice["vert"]["max"]: + return "darkgreen" + + # Par défaut orange si on ne trouve pas de correspondance exacte + return "orange" + + +def couleur_noeud(n: str, niveaux: dict, G: nx.DiGraph) -> str: + """ + Détermine la couleur d'un nœud en fonction de son niveau et de ses attributs. + Utilise les seuils définis dans le fichier de configuration. + + Args: + n (str): Nom du nœud. + niveaux (dict): Dictionnaire associant chaque nœud à son niveau. + G (nx.DiGraph): Graphe NetworkX contenant les données. + + Returns: + str: Couleur du nœud. + """ niveau = niveaux.get(n, 99) attrs = G.nodes[n] + seuils = load_seuils_config() # Niveau 99 : pays géographique avec isg if niveau == 99: isg = int(attrs.get("isg", -1)) - return ( - "darkred" if isg >= 60 else - "orange" if isg >= 31 else - "darkgreen" if isg >= 0 else - "gray" - ) + if isg >= 0 and "ISG" in seuils: + return determiner_couleur_par_seuil(isg, seuils["ISG"]) + return "gray" # Niveau 11 ou 12 connecté à un pays géographique if niveau in (11, 12, 1011, 1012): for succ in G.successors(n): if niveaux.get(succ) == 99: isg = int(G.nodes[succ].get("isg", -1)) - return ( - "darkred" if isg >= 60 else - "orange" if isg >= 31 else - "darkgreen" if isg >= 0 else - "gray" - ) + if isg >= 0 and "ISG" in seuils: + return determiner_couleur_par_seuil(isg, seuils["ISG"]) + return "gray" # Logique existante pour IHH / IVC if niveau in (10, 1010) and attrs.get("ihh_pays"): ihh = int(attrs["ihh_pays"]) + if "IHH" in seuils: + return determiner_couleur_par_seuil(ihh, seuils["IHH"]) + # Fallback vers les anciennes valeurs return ( "darkgreen" if ihh <= 15 else "orange" if ihh <= 25 else @@ -165,6 +234,9 @@ def couleur_noeud(n, niveaux, G): ) elif niveau == 2 and attrs.get("ivc"): ivc = int(attrs["ivc"]) + if "IVC" in seuils: + return determiner_couleur_par_seuil(ivc, seuils["IVC"]) + # Fallback vers les anciennes valeurs return ( "darkgreen" if ivc <= 15 else "orange" if ivc <= 30 else