microduck-arena-lab / tools /plot_progress.py
Kyry10's picture
Microduck Arena Lab: selected policies, reproducible guides and real simulation films
dc9a7f8 verified
Raw History Blame Contribute Delete
2.83 kB
"""Export a publication-ready figure of the measured selected milestones."""
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
ROOT = Path(__file__).resolve().parents[1]
plt.rcParams.update({"font.family": "DejaVu Sans", "font.size": 12,
"figure.facecolor": "#0a1523", "axes.facecolor": "#0a1523",
"text.color": "#f2f6fa", "axes.labelcolor": "#a9bacc",
"xtick.color": "#a9bacc", "ytick.color": "#f2f6fa"})
groups = [
("2 m sprint", "Licensed actor → race adaptation", "#69e2ce",
["Hannes baseline", "2B / 750", "B3 / 800", "D1 / 900"], [1.192, 1.096, 1.092, 1.084]),
("1.5 m hill / 8°", "Reference benchmark → selected policy", "#ffb36b",
["Pollen benchmark", "H1b / 500"], [5.880, 1.360]),
("2 m passive rollers", "Transfer adaptation → PPO polish", "#9bbcff",
["Pollen benchmark", "R1 / 300", "R1 / 400", "R1 / 900", "R2 / 1100"],
[3.136, 1.864, 1.648, 1.576, 1.516]),
]
fig, axes = plt.subplots(1, 3, figsize=(17, 7), gridspec_kw={"wspace": .46})
fig.suptitle("Selected checkpoints. Exact Arena score.", x=.07, y=.94, ha="left", fontsize=23, fontweight="bold")
fig.text(.07, .875, "Timed finish mean over five seeds · every shown policy finished 5/5 · lower is better",
color="#a9bacc", fontsize=12)
for ax, (title, subtitle, color, labels, scores) in zip(axes, groups):
ax.barh(range(len(scores)), scores, color=color, height=.58, alpha=.82)
ax.invert_yaxis()
ax.set_yticks(range(len(labels)), labels, fontsize=11)
ax.set_xlim(0, max(scores) * 1.29)
ax.set_xlabel("Timed finish / seconds", fontsize=10, labelpad=12)
ax.set_title(title + "\n" + subtitle, loc="left", fontsize=12, pad=22, color=color)
ax.xaxis.grid(True, color="#263d4f", linewidth=.7)
ax.set_axisbelow(True)
for index, score in enumerate(scores):
ax.text(score + max(scores) * .025, index, f"{score:.3f} s", va="center",
fontsize=11, fontweight="bold" if index == len(scores) - 1 else "normal")
for spine in ax.spines.values():
spine.set_visible(False)
ax.tick_params(axis="y", length=0)
fig.subplots_adjust(left=.13, right=.97, top=.72, bottom=.20)
fig.text(.07, .08, "References were benchmarks, not reused weight parents. All trained policies descend from the licensed Hannes actor.",
color="#a9bacc", fontsize=10)
fig.text(.07, .035, "Snapshot: October 2026. Local best policies and published Arena entries can differ; see models/manifest.json.",
color="#a9bacc", fontsize=9)
fig.savefig(ROOT / "media/experiment-progress.png", dpi=140, facecolor=fig.get_facecolor())
fig.savefig(ROOT / "media/experiment-progress.svg", facecolor=fig.get_facecolor())
print("Exported PNG and SVG progress figures.")