"""Jeux de paires et scénarios standardisés pour explorer les corrélations.""" from __future__ import annotations from dataclasses import dataclass from typing import Callable, Sequence import numpy as np HexbinReducer = Callable[[np.ndarray], float] HEXBIN_REDUCE_FUNCTIONS: dict[str, HexbinReducer] = { "mean": np.mean, "median": np.median, "max": np.max, } HEXBIN_REDUCE_LABELS: dict[str, str] = { "mean": "moyenne", "median": "médiane", "max": "maximum", } @dataclass(frozen=True) class CorrelationBand: """Intervalle de corrélation, avec couleur et étiquette pour l'affichage.""" min_value: float max_value: float label: str color: str # Repères par défaut pour lire rapidement l'intensité (en |r|) DEFAULT_ABS_CORRELATION_BANDS: Sequence[CorrelationBand] = ( CorrelationBand(0.0, 0.1, "Quasi nulle", "#f6f6f6"), CorrelationBand(0.1, 0.3, "Faible", "#dce8f7"), CorrelationBand(0.3, 0.5, "Modérée", "#c8e6c9"), CorrelationBand(0.5, 1.0, "Forte", "#ffe0b2"), ) # Bandes pour corrélations signées (symétriques autour de 0) DEFAULT_SIGNED_CORRELATION_BANDS: Sequence[CorrelationBand] = ( CorrelationBand(-1.0, -0.5, "Forte négative", "#c6dbef"), CorrelationBand(-0.5, -0.3, "Modérée négative", "#deebf7"), CorrelationBand(-0.3, -0.1, "Faible négative", "#edf8fb"), CorrelationBand(-0.1, 0.1, "Quasi nulle", "#f5f5f5"), CorrelationBand(0.1, 0.3, "Faible positive", "#fff7ec"), CorrelationBand(0.3, 0.5, "Modérée positive", "#fee8c8"), CorrelationBand(0.5, 1.0, "Forte positive", "#fdbb84"), ) @dataclass(frozen=True) class HexbinScenario: """Décrit un cas d'usage pour un nuage hexbin coloré par une 3ᵉ variable.""" key_x: str key_y: str key_color: str filename: str description: str reduce: str = "mean" gridsize: int = 60 mincnt: int = 5 def get_reduce_func(self) -> HexbinReducer: """Retourne la fonction de réduction associée (moyenne, médiane, ...).""" return HEXBIN_REDUCE_FUNCTIONS.get(self.reduce, np.mean) def get_reduce_label(self) -> str: """Libellé français de la fonction de réduction utilisée.""" return HEXBIN_REDUCE_LABELS.get(self.reduce, self.reduce) DEFAULT_LAGGED_PAIRS: Sequence[tuple[str, str]] = ( ("temperature", "humidity"), ("temperature", "rain_rate"), ("pressure", "rain_rate"), ("pressure", "wind_speed"), ("pressure", "illuminance"), ("illuminance", "temperature"), ("humidity", "rain_rate"), ) DEFAULT_ROLLING_PAIRS: Sequence[tuple[str, str]] = ( ("temperature", "humidity"), ("pressure", "rain_rate"), ("pressure", "wind_speed"), ("illuminance", "temperature"), ("humidity", "rain_rate"), ) DEFAULT_HEXBIN_SCENARIOS: Sequence[HexbinScenario] = ( HexbinScenario( key_x="temperature", key_y="humidity", key_color="rain_rate", filename="hexbin_temp_humidity_color_rain.png", description=( "Mettre en évidence comment l'humidité relative plafonne lorsque la température chute " "et comment les épisodes de pluie se situent dans une bande restreinte." ), reduce="max", gridsize=50, mincnt=8, ), HexbinScenario( key_x="sun_elevation", key_y="temperature", key_color="humidity", filename="hexbin_sunelev_temp_color_humidity.png", description=( "Suivre le cycle diurne : la température grimpe avec l'élévation solaire " "et l'humidité médiane chute nettement une fois le soleil levé." ), reduce="median", gridsize=60, mincnt=8, ), HexbinScenario( key_x="pressure", key_y="rain_rate", key_color="wind_speed", filename="hexbin_pressure_rain_color_wind.png", description=( "Vérifier si des rafales accompagnent vraiment les chutes de pression. " "On s'attend à voir beaucoup de cases vides : la corrélation est loin d'être systématique." ), reduce="median", gridsize=45, mincnt=5, ), HexbinScenario( key_x="illuminance", key_y="humidity", key_color="temperature", filename="hexbin_lux_humidity_color_temp.png", description=( "Explorer le cycle jour/nuit : l'humidité monte quand l'illuminance chute, " "mais cela n'implique pas toujours une baisse rapide de température." ), reduce="mean", gridsize=55, mincnt=6, ), HexbinScenario( key_x="sun_elevation", key_y="illuminance", key_color="rain_rate", filename="hexbin_sunelev_lux_color_rain.png", description=( "Comparer l'ensoleillement théorique (élévation solaire) et la luminance mesurée, " "et repérer les épisodes où la pluie ou un ciel très couvert écrasent la lumière " "malgré un soleil haut." ), reduce="max", gridsize=48, mincnt=3, ), ) __all__ = [ "HexbinScenario", "DEFAULT_LAGGED_PAIRS", "DEFAULT_ROLLING_PAIRS", "DEFAULT_HEXBIN_SCENARIOS", "CorrelationBand", "DEFAULT_ABS_CORRELATION_BANDS", "DEFAULT_SIGNED_CORRELATION_BANDS", ]