49) -> tuple[Path, Path]:
51 json_path = cwd / _JSON_NAME
52 png_path = cwd / _PNG_NAME
56 "saved_at": datetime.now(timezone.utc).isoformat(),
60 json_path.write_text(json.dumps(payload, indent=2, default=str), encoding=
"utf-8")
62 return json_path, png_path
69 import matplotlib.pyplot
as plt
71 if result.get(
"error"):
72 fig, ax = plt.subplots(figsize=(6, 2), facecolor=
"#0f1117")
74 ax.text(0.5, 0.5, f
"Error: {result['error']}", ha=
"center", va=
"center", wrap=
True, color=
"#e5e7eb")
75 fig.savefig(png_path, dpi=140, bbox_inches=
"tight", facecolor=
"#0f1117")
79 model = str(result.get(
"model_id")
or "")
80 mode = str(result.get(
"mode")
or "")
81 n_probes = int(result.get(
"n_probes")
or 0)
82 profile = [p
for p
in (result.get(
"layer_profile")
or [])
if p.get(
"sae_available",
True)]
83 heatmap = result.get(
"heatmap")
or {}
85 title = f
"SAE stats — {model} · {mode} · {n_probes} probes"
86 fig = plt.figure(figsize=(12, 7.5), facecolor=
"#0f1117")
87 gs = fig.add_gridspec(2, 2, height_ratios=[1, 1.35], hspace=0.38, wspace=0.28)
88 ax_profile = fig.add_subplot(gs[0, 0])
89 ax_sparse = fig.add_subplot(gs[0, 1])
90 ax_heat = fig.add_subplot(gs[1, :])
92 fig.suptitle(title, color=
"#e5e7eb", fontsize=11, y=0.98)
94 _plot_layer_profile(ax_profile, profile, metric=
"mean_l0", title=
"Mean L0 per layer", color=
"#6366f1")
95 _plot_layer_profile(ax_sparse, profile, metric=
"sparsity", title=
"Sparsity per layer", color=
"#34d399", pct=
True)
98 for ax
in (ax_profile, ax_sparse, ax_heat):
99 ax.set_facecolor(
"#0f1117")
100 for spine
in ax.spines.values():
101 spine.set_color(
"#374151")
103 fig.savefig(png_path, dpi=140, bbox_inches=
"tight", facecolor=
"#0f1117")
109 profile: list[dict[str, Any]],
116 ax.set_title(title, color=
"#e5e7eb", fontsize=10)
120 ax.text(0.5, 0.5,
"No layer profile", ha=
"center", va=
"center", color=
"#9ca3af")
123 layers = [int(p.get(
"layer", i))
for i, p
in enumerate(profile)]
124 vals = [float(p.get(metric)
or 0)
for p
in profile]
125 ax.bar(layers, vals, color=color, width=0.75, alpha=0.9)
126 ax.set_xlabel(
"Layer", color=
"#9ca3af", fontsize=8)
127 ylab =
"Sparsity" if pct
else "Mean L0"
128 ax.set_ylabel(ylab, color=
"#9ca3af", fontsize=8)
129 ax.tick_params(colors=
"#6b7280", labelsize=8)
130 ax.grid(axis=
"y", alpha=0.2, color=
"#4b5563")
132 ax.set_ylim(0, min(1.05, max(vals) * 1.15 + 0.05))
135def _plot_heatmap(ax: Any, heatmap: dict[str, Any], probes: list[dict[str, Any]]) ->
None:
136 rows = heatmap.get(
"rows")
or []
137 cols = heatmap.get(
"cols")
or []
138 values = heatmap.get(
"values")
or []
139 metric = str(heatmap.get(
"metric")
or "mean_l0")
141 ax.set_title(f
"Probe × layer heatmap ({metric})", color=
"#e5e7eb", fontsize=10, pad=10)
143 if not rows
or not cols
or not values:
145 ax.text(0.5, 0.5,
"No heatmap data", ha=
"center", va=
"center", color=
"#9ca3af")
150 data = np.array(values, dtype=float)
153 ax.text(0.5, 0.5,
"Invalid heatmap shape", ha=
"center", va=
"center", color=
"#9ca3af")
156 im = ax.imshow(data, aspect=
"auto", cmap=
"viridis", origin=
"upper")
157 ax.set_xticks(range(len(cols)))
158 ax.set_xticklabels(cols, fontsize=7, color=
"#d1d5db", rotation=45, ha=
"right")
159 ax.set_yticks(range(len(rows)))
160 ylabels = [
_probe_label(row_id, probes)
for row_id
in rows]
161 ax.set_yticklabels(ylabels, fontsize=7, color=
"#d1d5db")
162 ax.tick_params(axis=
"x", colors=
"#6b7280")
163 ax.tick_params(axis=
"y", colors=
"#6b7280")
164 cbar = ax.figure.colorbar(im, ax=ax, fraction=0.025, pad=0.02)
165 cbar.ax.tick_params(colors=
"#9ca3af", labelsize=7)
166 cbar.set_label(metric, color=
"#9ca3af", fontsize=8)
169def _probe_label(row_id: str, probes: list[dict[str, Any]]) -> str:
171 if str(p.get(
"id")) == str(row_id):
172 stressor = p.get(
"stressor")
None _plot_layer_profile(Any ax, list[dict[str, Any]] profile, *, str metric, str title, str color, bool pct=False)