figs: a5 dedup title->axis arrow + CSV, overlay onset dot->labeled vline

- a5: drop per-panel title (restated the axis); fold direction into the xlabel
  (DEPLOY hack rate (down=better) / solve (up=better)). Dump a5_generalisation.csv
  (per mode,arm deploy hack/solve mean+/-std) -- the reproducibility source it lacked.
- overlay (dyn_sub4_hack_overlay etc): replace the per-arm onset DOT with a single
  dashed labeled 'first hack' vertical line, matching the small-multiples/longrun.
- (dyn_sub4_hack_overlay shares dyn_sub4.csv -- same runs, different view, no new CSV.)

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
wassname
2026-06-05 04:13:37 +00:00
parent 8daf58d25e
commit 5242f66b7e
11 changed files with 889 additions and 917 deletions
+9 -4
View File
@@ -355,6 +355,7 @@ def _overlay_panel(ax, by_arm, arms, key, *, label, with_onset, label_arms, ylim
endpoint (de-collided in y). An arm whose mean series sits at zero gets a
"$\\approx 0$" tag so a pinned-at-zero line reads as a finding, not a missing line."""
ends = [] # (y_endpoint, x_endpoint, arm, color, is_zero) for direct labels
onset_steps = [] # mean-onset across arms -> ONE labeled vertical line (see below)
for arm in arms:
rs = [r for r in by_arm[arm] if key in r]
if not rs:
@@ -370,11 +371,15 @@ def _overlay_panel(ax, by_arm, arms, key, *, label, with_onset, label_arms, ylim
xm = rs[0]["steps"][:L]
ax.plot(xm, ym, color=color, lw=2.0, solid_capstyle="round")
if with_onset:
onsets = [s for r in rs if (s := _onset(r["steps"], r["hack_s"])) is not None]
if onsets:
s0 = float(np.mean(onsets))
ax.plot(s0, np.interp(s0, xm, ym), marker="o", ms=4, color=color, zorder=3)
onset_steps += [s for r in rs if (s := _onset(r["steps"], r["hack_s"])) is not None]
ends.append((float(ym[-1]), float(xm[-1]), arm, color, float(np.nanmax(ym)) < 0.02))
# First-hack as a labeled vertical line (matches the small-multiples), not a dot:
# a dashed rule reads as "emergence starts here" across both arms in one mark.
if with_onset and onset_steps:
s0 = float(np.mean(onset_steps))
ax.axvline(s0, color="0.55", lw=0.8, ls=(0, (4, 3)), zorder=0)
ax.annotate("first hack", (s0, ylim[1]), color="0.4", fontsize=7,
xytext=(2, -2), textcoords="offset points", va="top")
ax.set_ylim(*ylim)
ax.set_ylabel(label)
ax.spines[["top", "right"]].set_visible(False)