"""Speed-vs-accuracy Pareto scatter and per-method bar charts.""" from __future__ import annotations from pathlib import Path from typing import Any, Dict, List import matplotlib matplotlib.use("Agg") # headless import matplotlib.pyplot as plt # noqa: E402 def pareto_points(rows: List[Dict[str, Any]], x_key: str, y_key: str) -> List[Dict[str, Any]]: points = [] for row in rows: if row.get("status") != "ok": continue if row.get(x_key) is None or row.get(y_key) is None: continue points.append({ "method": row["method"], "x": row[x_key], "y": row[y_key], "t4_deployable": row.get("t4_deployable"), }) return points def _scatter(points, x_label, y_label, title, out_path: Path) -> None: fig, ax = plt.subplots(figsize=(7, 5)) for p in points: marker = "o" if p["t4_deployable"] else "x" ax.scatter(p["x"], p["y"], marker=marker, s=80) ax.annotate(p["method"], (p["x"], p["y"]), textcoords="offset points", xytext=(5, 5)) ax.set_xlabel(x_label) ax.set_ylabel(y_label) ax.set_title(title + " (o = T4-deployable, x = A100-only)") fig.tight_layout() fig.savefig(out_path, dpi=120) plt.close(fig) def _bar(rows, metric_key, y_label, out_path: Path) -> None: ok = [r for r in rows if r.get("status") == "ok" and r.get(metric_key) is not None] fig, ax = plt.subplots(figsize=(7, 5)) ax.bar([r["method"] for r in ok], [r[metric_key] for r in ok]) ax.set_ylabel(y_label) ax.set_title(metric_key) fig.tight_layout() fig.savefig(out_path, dpi=120) plt.close(fig) def render_all(rows: List[Dict[str, Any]], out_dir: Path) -> List[Path]: out_dir = Path(out_dir) out_dir.mkdir(parents=True, exist_ok=True) written: List[Path] = [] p1 = out_dir / "pareto_latency_cer.png" _scatter(pareto_points(rows, "mean_latency_s", "mean_cer"), "mean latency (s) [lower=faster]", "CER vs BF16 [lower=better]", "Speed vs recognition accuracy", p1) written.append(p1) p2 = out_dir / "pareto_latency_iou.png" _scatter(pareto_points(rows, "mean_latency_s", "mean_bbox_iou"), "mean latency (s) [lower=faster]", "bbox IoU vs BF16 [higher=better]", "Speed vs detection accuracy", p2) written.append(p2) for metric, label in [("mean_latency_s", "mean latency (s)"), ("mean_cer", "CER vs BF16"), ("mean_bbox_iou", "bbox IoU vs BF16")]: bp = out_dir / f"bar_{metric}.png" _bar(rows, metric, label, bp) written.append(bp) return written