fix overlay label collisions: common right-gutter anchor + leaders

End-labels sat on the line termini (2-arm figs) and piled up bottom-left on
ragged-length multi-arm overlays (substrate, where arms end at different steps).
Now all labels anchor at one gutter x with a leader fanning back to each line's
actual end, y-de-collided. Added right margin so the gutter is clear.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
wassname
2026-06-05 03:31:26 +00:00
parent 504922a3d6
commit a9523c9cb8
31 changed files with 4333 additions and 4380 deletions
+11 -5
View File
@@ -382,16 +382,22 @@ def _overlay_panel(ax, by_arm, arms, key, *, label, with_onset, label_arms, ylim
if not label_arms: # other panel shares colours -- redundant ink
return
ends.sort(key=lambda e: e[0]) # bottom-to-top by endpoint
gap = 0.052 * (ylim[1] - ylim[0]) # min y-separation, scaled to the range
gap = 0.06 * (ylim[1] - ylim[0]) # min y-separation, scaled to the range
xmax = max(e[1] for e in ends)
dx = 0.035 * (xmax - ax.get_xlim()[0]) # horizontal clearance off the line end
x_lab = xmax + dx # ALL labels share one gutter x, leaders fan back
ax.set_xlim(right=xmax + dx * 3.4) # right margin so labels sit clear in the gutter
placed = []
for y, x, arm, color, is_zero in ends:
y_lab = y if not placed else max(y, placed[-1] + gap)
placed.append(y_lab)
text = arm_label(arm) + (r" $\equiv 0$" if is_zero else "")
arrow = dict(arrowstyle="-", color=color, lw=0.5, shrinkA=0, shrinkB=0)
ax.annotate(text, xy=(x, y), xytext=(x + 1.0, y_lab), textcoords="data",
color=color, fontsize=8, va="center",
arrowprops=arrow if abs(y_lab - y) > 1e-3 else None)
# Common gutter x + leader back to each line's actual end: ragged run lengths
# otherwise scatter labels mid-plot onto other arms' lines (collision test).
arrow = dict(arrowstyle="-", color=color, lw=0.5, shrinkA=0, shrinkB=2)
ax.annotate(text, xy=(x, y), xytext=(x_lab, y_lab), textcoords="data",
color=color, fontsize=8, va="center", annotation_clip=False,
arrowprops=arrow)
def plot_hack_overlay(runs: list[dict], out: Path) -> None: