An eye diagram visualizes signal integrity by overlaying many periods of a digital signal onto a single time window spanning 1-2 unit intervals (UI). The overlapping traces form a characteristic eye-shaped opening whose height, width, and clarity reveal signal quality metrics such as jitter, noise, and inter-symbol interference (ISI). A wide-open eye indicates clean signal transmission, while a closed or blurred eye signals degradation.

""" anyplot.ai
eye-diagram-basic: Signal Integrity Eye Diagram
Library: seaborn 0.13.2 | Python 3.13.14
Quality: 88/100 | Updated: 2026-06-18
"""
import os
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.patches import Rectangle
from scipy.ndimage import gaussian_filter1d
# Theme tokens — Imprint palette chrome
THEME = os.getenv("ANYPLOT_THEME", "light")
PAGE_BG = "#FAF8F1" if THEME == "light" else "#1A1A17"
ELEVATED_BG = "#FFFDF6" if THEME == "light" else "#242420"
INK = "#1A1A17" if THEME == "light" else "#F0EFE8"
INK_SOFT = "#4A4A44" if THEME == "light" else "#B8B7B0"
ANYPLOT_AMBER = "#DDCC77"
# Seaborn theme — warm cream/near-black surfaces with Imprint chrome
sns.set_theme(
style="ticks",
rc={
"figure.facecolor": PAGE_BG,
"axes.facecolor": PAGE_BG,
"axes.edgecolor": INK_SOFT,
"axes.labelcolor": INK,
"text.color": INK,
"xtick.color": INK_SOFT,
"ytick.color": INK_SOFT,
"grid.color": INK,
"grid.alpha": 0.15,
"legend.facecolor": ELEVATED_BG,
"legend.edgecolor": INK_SOFT,
},
)
# Imprint sequential colormap — green → blue for trace density
imprint_seq = LinearSegmentedColormap.from_list("imprint_seq", ["#009E73", "#4467A3"])
# Data — NRZ signal with bandwidth-limited transitions, jitter, and noise
np.random.seed(42)
n_traces = 400
samples_per_ui = 200
ui_span = 2
n_display = samples_per_ui * ui_span
noise_sigma = 0.05
jitter_sigma = 0.03
bw_filter_sigma = 12
all_time = []
all_voltage = []
t_ui = np.linspace(0, ui_span, n_display, endpoint=False)
for _ in range(n_traces):
n_bits = 8
bits = np.random.randint(0, 2, size=n_bits)
samples_total = samples_per_ui * n_bits
signal_raw = np.repeat(bits.astype(float), samples_per_ui)
signal_smooth = gaussian_filter1d(signal_raw, sigma=bw_filter_sigma)
jitter_shift = int(np.random.normal(0, jitter_sigma * samples_per_ui))
signal_smooth = np.roll(signal_smooth, jitter_shift)
signal_smooth += np.random.normal(0, noise_sigma, samples_total)
start_bit = 3
start_idx = start_bit * samples_per_ui
end_idx = start_idx + n_display
segment = signal_smooth[start_idx:end_idx]
all_time.extend(t_ui.tolist())
all_voltage.extend(segment.tolist())
df = pd.DataFrame({"time": all_time, "voltage": all_voltage})
# Eye measurements — first eye center at t ≈ 0.5 UI (between transitions at t=0 and t=1)
eye_center_t = 0.5
center_mask = (df["time"] >= 0.35) & (df["time"] <= 0.65)
center_v = df.loc[center_mask, "voltage"]
logic0_center = center_v[center_v < 0.5]
logic1_center = center_v[center_v >= 0.5]
eye_floor = float(np.percentile(logic0_center, 99))
eye_ceiling = float(np.percentile(logic1_center, 1))
eye_height_v = max(eye_ceiling - eye_floor, 0.01)
# Eye width: find the transition-free horizontal zone at mid-voltage
n_tbins = 200
bins_time = np.linspace(0, 2, n_tbins + 1)
bin_centers = (bins_time[:-1] + bins_time[1:]) / 2
near_threshold = (df["voltage"] > 0.3) & (df["voltage"] < 0.7)
crossing_hist, _ = np.histogram(df.loc[near_threshold, "time"], bins=bins_time)
in_eye = crossing_hist < crossing_hist.max() * 0.08
center_bin = int(np.argmin(np.abs(bin_centers - eye_center_t)))
left = center_bin
right = center_bin
while left > 0 and in_eye[left - 1]:
left -= 1
while right < len(in_eye) - 1 and in_eye[right + 1]:
right += 1
eye_t_left = float(bin_centers[left])
eye_t_right = float(bin_centers[right])
eye_width_ui = max(eye_t_right - eye_t_left, 0.01)
eye_mid_t = (eye_t_left + eye_t_right) / 2
# Plot
fig, ax = plt.subplots(figsize=(8, 4.5), dpi=400)
# Seaborn 2D histogram — density heatmap; thresh=1 makes zero-count bins transparent
sns.histplot(
data=df,
x="time",
y="voltage",
bins=[300, 180],
stat="count",
thresh=1,
cbar=True,
cbar_kws={"label": "Trace Density", "shrink": 0.8},
cmap=imprint_seq,
ax=ax,
)
# NRZ reference levels — labeled for engineering context
ax.axhline(y=0.0, color=INK_SOFT, linewidth=0.8, linestyle="--", alpha=0.4)
ax.axhline(y=1.0, color=INK_SOFT, linewidth=0.8, linestyle="--", alpha=0.4)
ax.text(1.93, 0.04, "Logic 0", fontsize=7, color=INK_SOFT, va="bottom", ha="right")
ax.text(1.93, 0.96, "Logic 1", fontsize=7, color=INK_SOFT, va="top", ha="right")
# Eye opening outline — dashed rectangle highlights the clear region
eye_rect = Rectangle(
(eye_t_left, eye_floor),
eye_width_ui,
eye_height_v,
linewidth=0.9,
edgecolor=ANYPLOT_AMBER,
facecolor="none",
linestyle="--",
alpha=0.8,
)
ax.add_patch(eye_rect)
# Eye height annotation — vertical double arrow at eye center
ax.annotate(
"",
xy=(eye_mid_t, eye_floor),
xytext=(eye_mid_t, eye_ceiling),
arrowprops={"arrowstyle": "<->", "color": ANYPLOT_AMBER, "lw": 1.0},
)
ax.text(
eye_mid_t + 0.03,
(eye_floor + eye_ceiling) / 2,
f"H: {eye_height_v:.2f} V",
fontsize=6.5,
color=ANYPLOT_AMBER,
va="center",
ha="left",
)
# Eye width annotation — horizontal double arrow at mid-eye
v_arrow = eye_floor + eye_height_v * 0.28
ax.annotate(
"",
xy=(eye_t_left, v_arrow),
xytext=(eye_t_right, v_arrow),
arrowprops={"arrowstyle": "<->", "color": ANYPLOT_AMBER, "lw": 1.0},
)
ax.text(
eye_mid_t, v_arrow - 0.06, f"W: {eye_width_ui:.2f} UI", fontsize=6.5, color=ANYPLOT_AMBER, va="top", ha="center"
)
ax.set_xlim(0, 2)
ax.set_ylim(-0.3, 1.3)
ax.set_xticks([0, 0.5, 1.0, 1.5, 2.0])
# Style
title = "eye-diagram-basic · python · seaborn · anyplot.ai"
ax.set_title(title, fontsize=12, fontweight="medium", color=INK)
ax.set_xlabel("Time (UI)", fontsize=10, color=INK)
ax.set_ylabel("Voltage (V)", fontsize=10, color=INK)
ax.tick_params(axis="both", labelsize=8, colors=INK_SOFT)
sns.despine(ax=ax, top=True, right=True)
# Style colorbar text
if len(fig.axes) > 1:
cbar_ax = fig.axes[-1]
cbar_ax.tick_params(colors=INK_SOFT, labelsize=8)
cbar_ax.yaxis.label.set_color(INK)
for spine in cbar_ax.spines.values():
spine.set_color(INK_SOFT)
# Save
plt.savefig(f"plot-{THEME}.png", dpi=400, facecolor=PAGE_BG)
plt.close()
Part of Signal Integrity Eye Diagram on anyplot.ai.