1
etude_lego_jurassic_world/lib/plots/minifig_character_spans.py

64 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Diagramme de longévité des personnages (bornes d'apparition)."""
from pathlib import Path
from typing import List
import matplotlib.pyplot as plt
from lib.filesystem import ensure_parent_dir
from lib.rebrickable.stats import read_rows
def load_spans(path: Path) -> List[dict]:
"""Charge le CSV des bornes min/max par personnage."""
return read_rows(path)
def plot_character_spans(spans_path: Path, destination_path: Path) -> None:
"""Trace un diagramme en barres représentant la longévité des personnages."""
rows = load_spans(spans_path)
if not rows:
return
characters = [row["known_character"] for row in rows]
starts = [int(row["start_year"]) for row in rows]
ends = [int(row["end_year"]) for row in rows]
counts = [int(row["total_minifigs"]) for row in rows]
positions = list(range(len(rows)))
widths = [end - start + 1 for start, end in zip(starts, ends)]
min_year = min(starts)
max_year = max(ends)
height = max(5, len(rows) * 0.3)
fig, ax = plt.subplots(figsize=(12, height))
bars = ax.barh(
positions,
widths,
left=starts,
color="#1f77b4",
edgecolor="#0d0d0d",
linewidth=0.6,
)
ax.set_yticks(positions)
ax.set_yticklabels(characters)
ax.set_xlabel("Années d'apparition")
ax.set_ylabel("Personnage")
ax.set_title("Longévité des personnages (première à dernière apparition)")
ax.set_xlim(min_year - 1, max_year + 1)
ax.grid(True, axis="x", linestyle="--", alpha=0.25)
for bar, start, end, count in zip(bars, starts, ends, counts):
label = f"{start}{end} ({count})" if start != end else f"{start} ({count})"
ax.text(
start + (end - start) / 2,
bar.get_y() + bar.get_height() / 2,
label,
ha="center",
va="center",
fontsize=8,
color="#0d0d0d",
)
ensure_parent_dir(destination_path)
fig.tight_layout()
fig.savefig(destination_path, dpi=160)
plt.close(fig)