This repository has been archived on 2026-08-20. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
el-retired/docs/experiments/instruments/instrument/plot/plot.py
T
will d3495476f4
El SDK Release / build-and-release (push) Failing after 13m0s
kill: purge old-paradigm dist/platform binaries from tree
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.
2026-08-19 19:46:15 -05:00

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()