Spaces:
Running
Running
File size: 3,151 Bytes
48c3baa | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | """Render side-by-side comparison plots for JS vs Python benchmark runs.
Two columns × three rows: each row is a channel (left antenna, right
antenna, head Y); left column is the JS run, right column is the Python
run. Same y range per row so the comparison is honest.
"""
import csv
import sys
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
def load(path):
rows = []
with open(path) as f:
for r in csv.DictReader(f):
rows.append({k: float(v) if v else None for k, v in r.items()})
return rows
def col(rows, key):
return [r[key] for r in rows]
def plot_pair(ax, time, cmd, act, title, ylabel, ylim=None):
ax.plot(time, cmd, color="C0", linestyle="--", linewidth=1.2, label="commanded")
ax.plot(time, act, color="C3", linewidth=1.2, label="measured")
ax.set_title(title, fontsize=10)
ax.set_xlabel("t (s)", fontsize=9)
ax.set_ylabel(ylabel, fontsize=9)
ax.grid(True, alpha=0.3)
if ylim is not None:
ax.set_ylim(*ylim)
ax.legend(fontsize=8, loc="upper right")
ax.tick_params(labelsize=8)
def main(js_csv, py_csv, out_png):
js = load(js_csv)
py = load(py_csv)
js_t = col(js, "t_s")
py_t = col(py, "t_s")
# Shared y ranges (per row), computed across BOTH runs.
def span(*lists, pad=3):
vals = [v for lst in lists for v in lst if v is not None]
return min(vals) - pad, max(vals) + pad
yl_l = span(col(js, "left_commanded_deg"), col(js, "left_actual_deg"),
col(py, "left_commanded_deg"), col(py, "left_actual_deg"))
yl_r = span(col(js, "right_commanded_deg"), col(js, "right_actual_deg"),
col(py, "right_commanded_deg"), col(py, "right_actual_deg"))
yl_h = span(col(js, "head_y_commanded_cm"), col(js, "head_y_actual_cm"),
col(py, "head_y_commanded_cm"), col(py, "head_y_actual_cm"), pad=0.5)
fig, axes = plt.subplots(3, 2, figsize=(13, 9))
plot_pair(axes[0, 0], js_t, col(js, "left_commanded_deg"), col(js, "left_actual_deg"),
"Left antenna — JS", "deg", yl_l)
plot_pair(axes[0, 1], py_t, col(py, "left_commanded_deg"), col(py, "left_actual_deg"),
"Left antenna — Python", "deg", yl_l)
plot_pair(axes[1, 0], js_t, col(js, "right_commanded_deg"), col(js, "right_actual_deg"),
"Right antenna — JS", "deg", yl_r)
plot_pair(axes[1, 1], py_t, col(py, "right_commanded_deg"), col(py, "right_actual_deg"),
"Right antenna — Python", "deg", yl_r)
plot_pair(axes[2, 0], js_t, col(js, "head_y_commanded_cm"), col(js, "head_y_actual_cm"),
"Head Y — JS", "cm", yl_h)
plot_pair(axes[2, 1], py_t, col(py, "head_y_commanded_cm"), col(py, "head_y_actual_cm"),
"Head Y — Python", "cm", yl_h)
fig.suptitle("Streaming benchmark: JS (browser) vs Python (script)",
fontsize=12, fontweight="bold")
fig.tight_layout(rect=(0, 0, 1, 0.97))
fig.savefig(out_png, dpi=140)
print(f"Wrote {out_png}")
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2], sys.argv[3])
|