SPB Git

spb/wpai0002_uqo

Public

Figures: order-stable system colours and markers

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Nov 9, 2026) parent d8b346c Browse files

10 changed files +42 −2

modified paper/figures/FIGURE_PROVENANCE.md +1 −0
@@ -2,3 +2,4 @@
2 2
3 3 - Smoke: generated from `artifacts/metrics/vs_smoke/report.json` (created 2026-11-09T17:33:43Z, git 43899c8924172a93eb7fdb44567c22c0c6bb1e47) and runs ['artifacts/runs/vs_smoke-m1-nano']
4 4 - PilotVal: generated from `artifacts/metrics/pilot_val_exploratory/report.json` (created 2026-11-09T19:23:50Z, git c310982a0a448cfba546579ee1883679f6565058) and runs ['artifacts/runs/pilot_m1_tiny', 'artifacts/runs/pilot_m2_tiny', 'artifacts/runs/pilot_m1_tiny_denoiseinit']
5 +- PilotVal: generated from `artifacts/metrics/pilot_val_exploratory/report.json` (created 2026-11-09T19:23:50Z, git c310982a0a448cfba546579ee1883679f6565058) and runs ['artifacts/runs/pilot_m1_tiny', 'artifacts/runs/pilot_m2_tiny', 'artifacts/runs/pilot_m1_tiny_denoiseinit']
modified paper/figures/fig_by_discipline_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_by_era_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_by_role_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_by_variant_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_overall_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_stylometry_pilotval.pdf +0 −0

Binary file not shown.

modified paper/figures/fig_training_pilotval.pdf +0 −0

Binary file not shown.

modified scripts/build_figures.py +6 −1
@@ -86,7 +86,9 @@ def fig_stylometry(report: dict, out: Path) -> None:
86 86 m = means["rewrite"] if r == "rewrite" else sty[r]["feature_means"]
87 87 # standardised mean shift (in SDs of the originals; floor avoids blow-ups on near-constant features)
88 88 vals = [(m[f] - orig[f]) / max(sds.get(f, 1.0), 0.05 * (abs(orig[f]) + 1e-9), 1e-6) for f in FEATURES]
89 − ax.plot(range(len(FEATURES)), vals, marker="o", color=("#52514e" if r == "rewrite" else system_color(r)), label=("LLM rewrite" if r == "rewrite" else pretty(r)), linewidth=1.2)
89 + from htr.evaluation.plotstyle import system_marker
90 +
91 + ax.plot(range(len(FEATURES)), vals, marker=("x" if r == "rewrite" else system_marker(r, systems)), color=("#52514e" if r == "rewrite" else system_color(r)), label=("LLM rewrite" if r == "rewrite" else pretty(r)), linewidth=1.2)
90 92 ax.axhline(0, color="#c3c2b7", linewidth=0.8)
91 93 ax.set_xticks(range(len(FEATURES)))
92 94 ax.set_xticklabels([f.replace("_", " ") for f in FEATURES], rotation=60, ha="right", fontsize=7)
@@ -162,6 +164,9 @@ def main() -> None:
162 164 a = ap.parse_args()
163 165 apply()
164 166 rep = json.loads(Path(a.report).read_text())
167 + from htr.evaluation.plotstyle import assign_system_colors
168 +
169 + assign_system_colors(list(rep["systems"]))
165 170 figs, tabs = ROOT / "paper/figures", ROOT / "paper/tables"
166 171 figs.mkdir(exist_ok=True)
167 172 tabs.mkdir(exist_ok=True)
modified src/htr/evaluation/plotstyle.py +35 −1
@@ -16,13 +16,47 @@ SYSTEM_SLOT = {"B0_identity": 0, "B1_generic_paraphrase": 1, "B2": 3, "M1": 2, "
16 16 SEQUENTIAL_BLUE = ["#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#1c5cab", "#104281"]
17 17
18 18
19 +_ASSIGNED: dict[str, str] = {}
20 +MARKERS = ["o", "s", "D", "^", "v", "P"]
21 +
22 +
23 +def assign_system_colors(systems: list[str]) -> dict[str, str]:
24 + """Fixed, order-stable assignment: baselines keep their slots (B0 blue, B1 orange, B2 yellow); other systems take
25 + the remaining slots in the order given. Hues are never generated; beyond 6 systems the extra ones reuse a slot and
26 + must be distinguished by marker (see MARKERS) and direct labels."""
27 + fixed = {"B0_identity": 0, "B1_generic_paraphrase": 1}
28 + used = set()
29 + out: dict[str, str] = {}
30 + for s in systems:
31 + if s in fixed:
32 + out[s] = CATEGORICAL[fixed[s]]
33 + used.add(fixed[s])
34 + elif s.startswith("B2"):
35 + out[s] = CATEGORICAL[3]
36 + used.add(3)
37 + free = [i for i in range(len(CATEGORICAL)) if i not in used]
38 + k = 0
39 + for s in systems:
40 + if s not in out:
41 + out[s] = CATEGORICAL[free[k % len(free)]] if free else INK2
42 + k += 1
43 + _ASSIGNED.update(out)
44 + return out
45 +
46 +
19 47 def system_color(name: str) -> str:
48 + if name in _ASSIGNED:
49 + return _ASSIGNED[name]
20 50 for key, slot in SYSTEM_SLOT.items():
21 − if name == key or name.lower().startswith(key.lower()) or (key in ("M1", "M2", "M3") and f"-{key.lower()}" in name.lower()):
51 + if name == key or name.lower().startswith(key.lower()):
22 52 return CATEGORICAL[slot]
23 53 return INK2
24 54
25 55
56 +def system_marker(name: str, systems: list[str]) -> str:
57 + return MARKERS[systems.index(name) % len(MARKERS)] if name in systems else "o"
58 +
59 +
26 60 def apply() -> None:
27 61 mpl.rcParams.update({
28 62 "figure.facecolor": SURFACE, "axes.facecolor": SURFACE, "savefig.facecolor": SURFACE,
29 63
Menu

Theme