Archived
d3495476f4
El SDK Release / build-and-release (push) Failing after 13m0s
The generated C, amalgams, vendored runtime pins, and compiled binaries from the Claude Code era are removed from the worktree. The El sources survive; this tree is now source-only for the first-principles rebuild. Per Principal direction 2026-08-19.
43 lines
1.7 KiB
Python
43 lines
1.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Plot instrument. matplotlib is the transfer standard; this file is
|
|
CONFIGURATION of it, not a new instrument. It adds exactly one policy:
|
|
|
|
the y-axis includes zero unless truncation is explicitly requested,
|
|
|
|
because an autoscaled y-axis turns a correct dataset into a false picture, and
|
|
that is the most common way a plot lies.
|
|
"""
|
|
import sys, csv, matplotlib
|
|
matplotlib.use("Agg")
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib.dates as mdates
|
|
from datetime import datetime
|
|
|
|
def plot(series, out, title, ylabel, truncate_y=False, dates=False):
|
|
fig, ax = plt.subplots(figsize=(11, 5.2), dpi=160)
|
|
for name, xs, ys, color in series:
|
|
ax.plot(xs, ys, marker="o", ms=2.6, lw=1.4, color=color, label=name, zorder=3)
|
|
if not truncate_y:
|
|
ax.set_ylim(bottom=0) # the policy
|
|
if dates:
|
|
ax.xaxis.set_major_locator(mdates.AutoDateLocator())
|
|
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %d"))
|
|
ax.set_ylabel(ylabel); ax.set_title(title, loc="left")
|
|
ax.grid(True, lw=0.5, alpha=0.35, zorder=0)
|
|
ax.legend(frameon=False, loc="upper left")
|
|
for s in ("top","right"): ax.spines[s].set_visible(False)
|
|
fig.tight_layout(); fig.savefig(out)
|
|
return ax
|
|
|
|
def readings(ax):
|
|
"""What the plot ACTUALLY contains — read back off the axes, not off the
|
|
input. This is what makes the plot checkable."""
|
|
out = []
|
|
for ln in ax.get_lines():
|
|
d = ln.get_xydata()
|
|
out.append({"label": ln.get_label(), "n": len(d),
|
|
"xmin": float(d[:,0].min()), "xmax": float(d[:,0].max()),
|
|
"ymin": float(d[:,1].min()), "ymax": float(d[:,1].max()),
|
|
"last": (float(d[-1,0]), float(d[-1,1]))})
|
|
return out, ax.get_ylim()
|