Files
MiPi_TEST/rebuild_eye.py
David Rice 423766f7a3 Commit
2026-05-26 08:06:49 +02:00

92 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Rebuild the folded CLK+ eye diagram for the v2 report.
The original plot_eye() in make_flicker_report.py looks for an LP-11 → HS
transition (CLK+ > 0.5 V then falling). In session 20260515_135656 the
captures landed entirely in HS state (CLK+ stays in ~0.070.36 V), so the
edge detector returned None for every segment and the plot rendered with
zero overlays.
This script auto-detects the common mode per segment and folds around
every crossing of common mode — which is what the eye really wants.
"""
from __future__ import annotations
from pathlib import Path
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
ARRIVE_PURPLE = "#5f016f"
ARRIVE_PURPLE_DARK = "#3e0049"
SESSION = Path("data/flicker_bursts/20260515_135656")
BURST = 15
N_SEGS = 20
UI_NS = 2.315
OUT = Path("flicker_investigation_report_v2_plots/mipi_typical_eye.png")
def fold_segment(t_ns: np.ndarray, v_mv: np.ndarray, ui_ns: float,
ax: plt.Axes) -> int:
"""Overlay every common-mode crossing in this segment as a ±1 UI slice."""
cm = float(np.median(v_mv))
above = (v_mv > cm).astype(int)
edges = np.where(np.diff(above) != 0)[0]
n = 0
for e in edges:
t_cross = t_ns[e]
mask = (t_ns >= t_cross - ui_ns) & (t_ns <= t_ns[e] + ui_ns)
if mask.sum() < 3:
continue
ax.plot(t_ns[mask] - t_cross, v_mv[mask] - cm,
color=ARRIVE_PURPLE, linewidth=0.4, alpha=0.18)
n += 1
return n
def main() -> None:
clk_files = sorted(SESSION.glob(f"burst_{BURST:04d}_*_mipi_seg*_clk.csv"))
if not clk_files:
raise SystemExit(f"no CLK files for burst {BURST} in {SESSION}")
fig, ax = plt.subplots(figsize=(8.5, 3.0))
total_segs = 0
total_xings = 0
for f in clk_files[:N_SEGS]:
arr = np.genfromtxt(f, delimiter=",")
t_ns = arr[:, 0] * 1e9
v_mv = arr[:, 1] * 1000
n = fold_segment(t_ns, v_mv, UI_NS, ax)
if n:
total_segs += 1
total_xings += n
ax.axhline(0, color="grey", linewidth=0.4, alpha=0.5)
ax.axvline(-UI_NS / 2, color="grey", linestyle=":", linewidth=0.4, alpha=0.5)
ax.axvline(+UI_NS / 2, color="grey", linestyle=":", linewidth=0.4, alpha=0.5)
ax.set_xlabel(f"time (ns, folded on UI = {UI_NS} ns)")
ax.set_ylabel("CLK+ common-mode (mV)")
ax.set_xlim(-UI_NS, UI_NS)
ax.set_title(
f"CLK+ folded eye ({total_segs} segments × ~{total_xings // max(total_segs,1)} "
f"crossings overlaid on a 2-UI window, burst {BURST})",
color=ARRIVE_PURPLE, fontsize=11)
ax.grid(True, alpha=0.25)
ax.text(0.01, 0.95,
f"{total_segs} segments × ~{total_xings // max(total_segs,1)} cycles overlaid",
transform=ax.transAxes, fontsize=9, color=ARRIVE_PURPLE_DARK,
bbox=dict(facecolor="white", edgecolor="none", alpha=0.85), va="top")
OUT.parent.mkdir(parents=True, exist_ok=True)
fig.tight_layout()
fig.savefig(OUT, dpi=140)
print(f"wrote {OUT} ({total_segs} segments, {total_xings} crossings)")
if __name__ == "__main__":
main()