Fig. 1: borderless cells in A; the Flaticon robot everywhere in B

Cells lose their borders (pastel fills float; not-tested/literature/open cells
go light gray, headers keep their frame); Fig. 1B's hand-drawn robots are
replaced by the same licensed Flaticon robot as the 1A headers, embedded
unsampled, with the capability dots kept. Both panels visually inspected
post-render (text visible, no overlaps) per the new standing rule in the
global CLAUDE.md: never ship a figure you have not seen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BkRLcc18rwT2Lysu6PbG7v
This commit is contained in:
Giorgio Gilestro 2026-09-07 13:48:25 +01:00
parent 60ef253c77
commit 70c8c54434
4 changed files with 20 additions and 25 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -158,25 +158,22 @@ def fig1a():
face = TIERS[j2][4] face = TIERS[j2][4]
if cell is None: if cell is None:
ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0, ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0,
boxstyle="round,pad=0.004", fc="white", ec="#bbbbbb", boxstyle="round,pad=0.004", fc="#f3f3f3", ec="none"))
lw=0.8, ls=(0, (3, 2))))
ax.text(x + cw / 2, yc, "adds no discriminating test\nat this tier", ha="center", ax.text(x + cw / 2, yc, "adds no discriminating test\nat this tier", ha="center",
va="center", fontsize=6.4, style="italic", color="#999", linespacing=1.35) va="center", fontsize=6.4, style="italic", color="#999", linespacing=1.35)
elif cell.startswith("LIT:"): elif cell.startswith("LIT:"):
ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0, ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0,
boxstyle="round,pad=0.004", fc="white", ec="#bbbbbb", boxstyle="round,pad=0.004", fc="#f3f3f3", ec="none"))
lw=0.8, ls=(0, (3, 2))))
ax.text(x + cw / 2, yc, cell[4:], ha="center", va="center", ax.text(x + cw / 2, yc, cell[4:], ha="center", va="center",
fontsize=6.4, style="italic", color="#777", linespacing=1.35) fontsize=6.4, style="italic", color="#777", linespacing=1.35)
elif cell == "OPEN": elif cell == "OPEN":
ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0, ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0,
boxstyle="round,pad=0.004", fc="white", ec=edge, boxstyle="round,pad=0.004", fc="#f3f3f3", ec="none"))
lw=0.8, ls=(0, (3, 2))))
ax.text(x + cw / 2, yc, "open \u2014 the stated gap", ha="center", va="center", ax.text(x + cw / 2, yc, "open \u2014 the stated gap", ha="center", va="center",
fontsize=6.6, style="italic", color=edge) fontsize=6.6, style="italic", color=edge)
else: else:
ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0, ax.add_patch(FancyBboxPatch((x + gap, y0), cw - 2 * gap, y1 - y0,
boxstyle="round,pad=0.004", fc=face, ec=edge, lw=0.9)) boxstyle="round,pad=0.004", fc=face, ec="none"))
ax.text(x + cw / 2, yc + 0.008, cell, ha="center", va="center", ax.text(x + cw / 2, yc + 0.008, cell, ha="center", va="center",
fontsize=6.4, linespacing=1.35) fontsize=6.4, linespacing=1.35)
if tags[j2]: # where the result lives (the ToC role) if tags[j2]: # where the result lives (the ToC role)
@ -188,23 +185,17 @@ def fig1a():
BLUE, GREEN, GOLD = "#4292c6", "#41ab5d", "#d4a017" BLUE, GREEN, GOLD = "#4292c6", "#41ab5d", "#d4a017"
def _robot(ax, x, y, fc="#e8eef5", dots=(), lost=(), w=0.52, h=0.52): def _robot(ax, x, y, img, dots=(), lost=(), size=0.62):
"""A friendly robot head with capability dots beneath (gold = the rare skill).""" """The robot icon (the same Flaticon asset as Fig. 1A) with capability dots beneath."""
from matplotlib.patches import Arc, Circle, FancyBboxPatch from matplotlib.patches import Circle
ax.add_patch(FancyBboxPatch((x - w / 2, y - h / 2), w, h, boxstyle="round,pad=0.03", ax.imshow(img, extent=(x - size / 2, x + size / 2, y - size / 2, y + size / 2),
fc=fc, ec="#445", lw=1.1)) interpolation="none", zorder=2)
for dx in (-w / 4.5, w / 4.5):
ax.add_patch(Circle((x + dx, y + h / 7), w / 9, fc="white", ec="#445", lw=0.7))
ax.add_patch(Circle((x + dx, y + h / 7), w / 24, fc="#334", ec="none"))
ax.add_patch(Arc((x, y - h / 7), w / 2.4, h / 3.2, theta1=195, theta2=345, ec="#445", lw=1.0))
ax.plot([x, x], [y + h / 2 + 0.03, y + h / 2 + 0.10], color="#445", lw=1.1)
ax.add_patch(Circle((x, y + h / 2 + 0.135), 0.04, fc="#445", ec="none"))
marks = [(c, False) for c in dots] + [(c, True) for c in lost] marks = [(c, False) for c in dots] + [(c, True) for c in lost]
n = len(marks) n = len(marks)
for i, (c, is_lost) in enumerate(marks): for i, (c, is_lost) in enumerate(marks):
cx = x + (i - (n - 1) / 2) * 0.19 cx = x + (i - (n - 1) / 2) * 0.19
cy = y - h / 2 - 0.17 cy = y - size / 2 - 0.13
if is_lost: if is_lost:
ax.add_patch(Circle((cx, cy), 0.07, fc="white", ec=c, lw=0.9, ls=(0, (2, 2)))) ax.add_patch(Circle((cx, cy), 0.07, fc="white", ec=c, lw=0.9, ls=(0, (2, 2))))
ax.text(cx, cy - 0.005, "\u00d7", ha="center", va="center", fontsize=6, color=c) ax.text(cx, cy - 0.005, "\u00d7", ha="center", va="center", fontsize=6, color=c)
@ -227,6 +218,8 @@ def fig1b():
ax.add_patch(FancyArrowPatch(p, q, arrowstyle=style, mutation_scale=10, color=color, ax.add_patch(FancyArrowPatch(p, q, arrowstyle=style, mutation_scale=10, color=color,
lw=lw, linestyle=ls, shrinkA=shrink, shrinkB=shrink)) lw=lw, linestyle=ls, shrinkA=shrink, shrinkB=shrink))
rob = _icon("robot.svg")
# ---------------- left: a society in space (contemporaries exchanging messages) # ---------------- left: a society in space (contemporaries exchanging messages)
cx, cy, r = 2.45, 2.95, 0.95 cx, cy, r = 2.45, 2.95, 0.95
dotsets = [(BLUE, GOLD), (GREEN,), (BLUE, GREEN), (GOLD, GREEN), (BLUE,)] dotsets = [(BLUE, GOLD), (GREEN,), (BLUE, GREEN), (GOLD, GREEN), (BLUE,)]
@ -235,7 +228,7 @@ def fig1b():
a = np.pi / 2 + i * 2 * np.pi / 5 a = np.pi / 2 + i * 2 * np.pi / 5
x, y = cx + r * np.cos(a) * 1.4, cy + r * np.sin(a) * 0.95 x, y = cx + r * np.cos(a) * 1.4, cy + r * np.sin(a) * 0.95
pos.append((x, y)) pos.append((x, y))
_robot(ax, x, y, dots=ds) _robot(ax, x, y, rob, dots=ds)
for i, j2 in [(0, 2), (1, 3), (2, 4), (0, 3), (1, 4)]: for i, j2 in [(0, 2), (1, 3), (2, 4), (0, 3), (1, 4)]:
arrow(pos[i], pos[j2], color="#99a", lw=0.9, style="<|-|>", shrink=26, ls=(0, (4, 2))) arrow(pos[i], pos[j2], color="#99a", lw=0.9, style="<|-|>", shrink=26, ls=(0, (4, 2)))
ax.text(pos[0][0] + 0.72, pos[0][1] + 0.38, "hi!", fontsize=8, ha="center", ax.text(pos[0][0] + 0.72, pos[0][1] + 0.38, "hi!", fontsize=8, ha="center",
@ -266,11 +259,11 @@ def fig1b():
p1, p2 = (8.0, 4.05), (9.5, 4.05) p1, p2 = (8.0, 4.05), (9.5, 4.05)
c1, c2 = (7.5, 2.80), (9.0, 2.80) c1, c2 = (7.5, 2.80), (9.0, 2.80)
g2 = (9.0, 1.60) g2 = (9.0, 1.60)
_robot(ax, *p1, dots=(BLUE, GOLD)) _robot(ax, *p1, rob, dots=(BLUE, GOLD))
_robot(ax, *p2, dots=(GREEN, BLUE)) _robot(ax, *p2, rob, dots=(GREEN, BLUE))
_robot(ax, *c1, dots=(BLUE,), lost=(GOLD,)) _robot(ax, *c1, rob, dots=(BLUE,), lost=(GOLD,))
_robot(ax, *c2, dots=(BLUE, GREEN, GOLD)) _robot(ax, *c2, rob, dots=(BLUE, GREEN, GOLD))
_robot(ax, *g2, dots=(BLUE, GREEN, GOLD)) _robot(ax, *g2, rob, dots=(BLUE, GREEN, GOLD))
arrow((7.87, 3.51), (7.56, 3.29), color="#666") arrow((7.87, 3.51), (7.56, 3.29), color="#666")
ax.text(7.42, 3.41, "inherit", ha="right", fontsize=7, style="italic", color="#555") ax.text(7.42, 3.41, "inherit", ha="right", fontsize=7, style="italic", color="#555")
arrow((8.15, 3.49), (8.85, 3.29), color="#666") arrow((8.15, 3.49), (8.85, 3.29), color="#666")
@ -296,6 +289,8 @@ def fig1b():
ha="center", fontsize=7.2, style="italic", color="#555") ha="center", fontsize=7.2, style="italic", color="#555")
ax.text(8.9, 0.24, "from parent model to child model \u2014 where population genetics applies", ax.text(8.9, 0.24, "from parent model to child model \u2014 where population genetics applies",
ha="center", fontsize=7.2, style="italic", color="#555") ha="center", fontsize=7.2, style="italic", color="#555")
ax.set_xlim(0, W)
ax.set_ylim(0, H)
save(fig, "fig1b") save(fig, "fig1b")
# ---------------------------------------------------------------- fig 2: grounding + MNIST # ---------------------------------------------------------------- fig 2: grounding + MNIST