"""Fonctions utilitaires pour générer des hexbins à partir de scénarios.""" from __future__ import annotations from dataclasses import dataclass from pathlib import Path from typing import Sequence import pandas as pd from meteo.correlation_presets import HexbinScenario from meteo.variables import VARIABLES_BY_KEY, Variable from .relationships import plot_hexbin_with_third_variable __all__ = [ "HexbinPlotResult", "prepare_hexbin_dataframe", "generate_hexbin_for_scenario", "generate_hexbin_scenarios", ] @dataclass(frozen=True) class HexbinPlotResult: """Résultat d'un hexbin généré à partir d'un scénario prédéfini.""" scenario: HexbinScenario var_x: Variable var_y: Variable var_color: Variable output_path: Path point_count: int def _get_variables_for_scenario(scenario: HexbinScenario) -> tuple[Variable, Variable, Variable]: try: return ( VARIABLES_BY_KEY[scenario.key_x], VARIABLES_BY_KEY[scenario.key_y], VARIABLES_BY_KEY[scenario.key_color], ) except KeyError as exc: raise KeyError(f"Variable inconnue dans le scénario hexbin : {exc}") from exc def prepare_hexbin_dataframe( df: pd.DataFrame, var_x: Variable, var_y: Variable, var_color: Variable, ) -> pd.DataFrame: """Sélectionne et nettoie les colonnes utiles à un hexbin.""" columns = [var_x.column, var_y.column, var_color.column] missing = [col for col in columns if col not in df.columns] if missing: raise KeyError(f"Colonnes absentes dans le DataFrame : {missing}") return df[columns].dropna() def generate_hexbin_for_scenario( df: pd.DataFrame, scenario: HexbinScenario, *, base_output_dir: str | Path, cmap: str = "viridis", ) -> HexbinPlotResult: """Construit un hexbin complet à partir d'un scénario et retourne ses métadonnées.""" var_x, var_y, var_color = _get_variables_for_scenario(scenario) cleaned_df = prepare_hexbin_dataframe(df, var_x, var_y, var_color) output_dir = Path(base_output_dir) output_dir.mkdir(parents=True, exist_ok=True) output_path = output_dir / scenario.filename reduce_func = scenario.get_reduce_func() reduce_label = scenario.get_reduce_label() plot_hexbin_with_third_variable( df=cleaned_df, var_x=var_x, var_y=var_y, var_color=var_color, output_path=output_path, gridsize=scenario.gridsize, mincnt=scenario.mincnt, reduce_func=reduce_func, reduce_func_label=reduce_label, cmap=cmap, ) return HexbinPlotResult( scenario=scenario, var_x=var_x, var_y=var_y, var_color=var_color, output_path=output_path.resolve(), point_count=len(cleaned_df), ) def generate_hexbin_scenarios( df: pd.DataFrame, scenarios: Sequence[HexbinScenario], *, base_output_dir: str | Path, cmap: str = "viridis", ) -> list[HexbinPlotResult]: """Génère en série plusieurs hexbins prédéfinis et retourne les résultats.""" if not scenarios: raise ValueError("Aucun scénario hexbin fourni.") results: list[HexbinPlotResult] = [] for scenario in scenarios: result = generate_hexbin_for_scenario( df=df, scenario=scenario, base_output_dir=base_output_dir, cmap=cmap, ) results.append(result) return results