Réorganise les visuels de l'étape 15 sous figures/step15
This commit is contained in:
parent
d494c1a695
commit
7a193136e5
@ -183,4 +183,5 @@ Le script lit `data/intermediate/colors_by_set.csv` et produit deux agrégats :
|
||||
1. `source .venv/bin/activate`
|
||||
2. `python -m scripts.plot_colors_timeline`
|
||||
|
||||
Le script lit les deux agrégats de l'étape précédente et produit `figures/step14/colors_translucent_share.png` (part des pièces translucides par année et nombre de couleurs distinctes), `figures/step14/colors_heatmap_linear.png` (heatmap année × couleur en quantités brutes) et `figures/step14/colors_heatmap_log.png` (heatmap avec échelle log1p).
|
||||
Le script lit les agrégats de l'étape 14 et produit `figures/step15/colors_translucent_share.png` (part des pièces translucides par année et nombre de couleurs distinctes), `figures/step15/colors_heatmap_linear.png` (heatmap année × couleur en quantités brutes) et `figures/step15/colors_heatmap_log.png` (heatmap avec échelle log1p).
|
||||
Une troisième variante normalise les quantités par année : `figures/step15/colors_heatmap_share.png`. Dans cette vue, chaque colonne (année) est ramenée à une part relative (0–1) du total de pièces de l'année. Cela met en évidence la structure de palette indépendamment du volume : deux années restent comparables même si leur nombre total de pièces diffère fortement, mais l'information de volume absolu n'apparaît plus (à privilégier pour les comparaisons de proportions, pas pour mesurer la rareté volumique).
|
||||
|
||||
@ -79,11 +79,21 @@ def build_heatmap_data(rows: Iterable[dict]) -> Tuple[List[int], List[str], np.n
|
||||
return years, labels, matrix, swatches
|
||||
|
||||
|
||||
def plot_colors_heatmap(matrix_path: Path, destination_path: Path, use_log_scale: bool = False) -> None:
|
||||
"""Génère une heatmap année × couleur basée sur les quantités totales avec pastilles."""
|
||||
def plot_colors_heatmap(
|
||||
matrix_path: Path,
|
||||
destination_path: Path,
|
||||
use_log_scale: bool = False,
|
||||
normalize_by_year: bool = False,
|
||||
) -> None:
|
||||
"""Génère une heatmap année × couleur avec pastilles (linéaire, log1p ou normalisée)."""
|
||||
rows = load_rows(matrix_path)
|
||||
years, labels, matrix, swatches = build_heatmap_data(rows)
|
||||
values = np.log1p(matrix) if use_log_scale else matrix
|
||||
values = matrix
|
||||
if normalize_by_year:
|
||||
column_totals = matrix.sum(axis=0, keepdims=True)
|
||||
values = matrix / column_totals
|
||||
if use_log_scale:
|
||||
values = np.log1p(values)
|
||||
|
||||
fig, ax = plt.subplots(figsize=(14, max(6, len(labels) * 0.26)))
|
||||
y_positions = np.arange(len(labels))
|
||||
@ -108,10 +118,18 @@ def plot_colors_heatmap(matrix_path: Path, destination_path: Path, use_log_scale
|
||||
)
|
||||
ax.set_xlim(-1.1, len(years) - 0.5)
|
||||
ax.set_xlabel("Année")
|
||||
title_scale = "log1p des quantités" if use_log_scale else "quantités totales"
|
||||
if normalize_by_year:
|
||||
title_scale = "parts de couleur (par année)"
|
||||
else:
|
||||
title_scale = "log1p des quantités" if use_log_scale else "quantités totales"
|
||||
ax.set_title(f"Intensité des couleurs par année ({title_scale})")
|
||||
cbar = fig.colorbar(heatmap, ax=ax, shrink=0.82, pad=0.018)
|
||||
cbar_label = "log1p(quantité totale)" if use_log_scale else "quantité totale"
|
||||
if normalize_by_year:
|
||||
cbar_label = "Part de la couleur (0-1)"
|
||||
elif use_log_scale:
|
||||
cbar_label = "log1p(quantité totale)"
|
||||
else:
|
||||
cbar_label = "quantité totale"
|
||||
cbar.set_label(cbar_label)
|
||||
ensure_parent_dir(destination_path)
|
||||
fig.subplots_adjust(left=0.26, right=0.97, bottom=0.08, top=0.94)
|
||||
|
||||
@ -7,9 +7,10 @@ from lib.plots.colors_timeline import plot_colors_heatmap, plot_translucent_shar
|
||||
|
||||
TIMELINE_PATH = Path("data/intermediate/colors_timeline.csv")
|
||||
MATRIX_PATH = Path("data/intermediate/colors_year_color_matrix.csv")
|
||||
TRANSLUCENT_DESTINATION = Path("figures/step14/colors_translucent_share.png")
|
||||
HEATMAP_LINEAR_DESTINATION = Path("figures/step14/colors_heatmap_linear.png")
|
||||
HEATMAP_LOG_DESTINATION = Path("figures/step14/colors_heatmap_log.png")
|
||||
TRANSLUCENT_DESTINATION = Path("figures/step15/colors_translucent_share.png")
|
||||
HEATMAP_LINEAR_DESTINATION = Path("figures/step15/colors_heatmap_linear.png")
|
||||
HEATMAP_LOG_DESTINATION = Path("figures/step15/colors_heatmap_log.png")
|
||||
HEATMAP_SHARE_DESTINATION = Path("figures/step15/colors_heatmap_share.png")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@ -17,6 +18,7 @@ def main() -> None:
|
||||
plot_translucent_share(TIMELINE_PATH, TRANSLUCENT_DESTINATION)
|
||||
plot_colors_heatmap(MATRIX_PATH, HEATMAP_LINEAR_DESTINATION, use_log_scale=False)
|
||||
plot_colors_heatmap(MATRIX_PATH, HEATMAP_LOG_DESTINATION, use_log_scale=True)
|
||||
plot_colors_heatmap(MATRIX_PATH, HEATMAP_SHARE_DESTINATION, normalize_by_year=True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@ -28,8 +28,9 @@ def test_plot_translucent_share(tmp_path: Path) -> None:
|
||||
def test_plot_colors_heatmap(tmp_path: Path) -> None:
|
||||
"""Génère une heatmap année × couleur."""
|
||||
matrix_path = tmp_path / "colors_year_color_matrix.csv"
|
||||
destination_linear = tmp_path / "figures" / "step14" / "colors_heatmap_linear.png"
|
||||
destination_log = tmp_path / "figures" / "step14" / "colors_heatmap_log.png"
|
||||
destination_linear = tmp_path / "figures" / "step15" / "colors_heatmap_linear.png"
|
||||
destination_log = tmp_path / "figures" / "step15" / "colors_heatmap_log.png"
|
||||
destination_share = tmp_path / "figures" / "step15" / "colors_heatmap_share.png"
|
||||
matrix_path.write_text(
|
||||
"year,color_rgb,is_translucent,color_name,quantity_total\n"
|
||||
"2020,AAAAAA,false,Gray,5\n"
|
||||
@ -40,8 +41,11 @@ def test_plot_colors_heatmap(tmp_path: Path) -> None:
|
||||
|
||||
plot_colors_heatmap(matrix_path, destination_linear, use_log_scale=False)
|
||||
plot_colors_heatmap(matrix_path, destination_log, use_log_scale=True)
|
||||
plot_colors_heatmap(matrix_path, destination_share, normalize_by_year=True)
|
||||
|
||||
assert destination_linear.exists()
|
||||
assert destination_linear.stat().st_size > 0
|
||||
assert destination_log.exists()
|
||||
assert destination_log.stat().st_size > 0
|
||||
assert destination_share.exists()
|
||||
assert destination_share.stat().st_size > 0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user