Skip to content

Commit 20daa57

Browse files
feat(seaborn): implement line-realtime (#3125)
## Implementation: `line-realtime` - seaborn Implements the **seaborn** version of `line-realtime`. **File:** `plots/line-realtime/implementations/seaborn.py` **Parent Issue:** #3073 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620498178)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 84db9dd commit 20daa57

2 files changed

Lines changed: 171 additions & 0 deletions

File tree

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
""" pyplots.ai
2+
line-realtime: Real-Time Updating Line Chart
3+
Library: seaborn 0.13.2 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
import pandas as pd
10+
import seaborn as sns
11+
from matplotlib.dates import DateFormatter
12+
13+
14+
# Data - Simulated CPU usage with realistic patterns
15+
np.random.seed(42)
16+
n_points = 100
17+
visible_points = 60 # Sliding window shows last 60 points
18+
19+
# Create timestamps (100ms intervals)
20+
base_time = pd.Timestamp("2025-12-31 14:30:00")
21+
timestamps = pd.date_range(start=base_time, periods=n_points, freq="100ms")
22+
23+
# Generate realistic CPU usage (with spikes and trends)
24+
base_usage = 45 + np.cumsum(np.random.randn(n_points) * 0.5)
25+
spikes = np.random.choice([0, 15, 25], size=n_points, p=[0.85, 0.10, 0.05])
26+
cpu_usage = np.clip(base_usage + spikes + np.random.randn(n_points) * 2, 5, 95)
27+
28+
# Create DataFrame
29+
df = pd.DataFrame({"timestamp": timestamps, "cpu_usage": cpu_usage})
30+
31+
# Select visible window (sliding window effect)
32+
df_visible = df.iloc[-visible_points:].copy()
33+
34+
# Create alpha gradient for fade effect (older points more transparent)
35+
alpha_values = np.linspace(0.3, 1.0, visible_points)
36+
37+
# Create plot
38+
fig, ax = plt.subplots(figsize=(16, 9))
39+
40+
# Plot the main line with gradient effect (segment by segment for fade)
41+
for i in range(len(df_visible) - 1):
42+
sns.lineplot(
43+
data=df_visible.iloc[i : i + 2],
44+
x="timestamp",
45+
y="cpu_usage",
46+
ax=ax,
47+
color="#306998",
48+
linewidth=3,
49+
alpha=alpha_values[i],
50+
legend=False,
51+
)
52+
53+
# Add scatter points at key locations (latest points more visible)
54+
scatter_indices = [0, len(df_visible) // 4, len(df_visible) // 2, -10, -5, -1]
55+
for idx in scatter_indices:
56+
point = df_visible.iloc[idx]
57+
alpha = alpha_values[idx] if idx >= 0 else 1.0
58+
size = 150 if idx == -1 else 80
59+
ax.scatter(
60+
point["timestamp"],
61+
point["cpu_usage"],
62+
s=size,
63+
color="#306998",
64+
alpha=alpha,
65+
zorder=5,
66+
edgecolors="white",
67+
linewidth=1.5,
68+
)
69+
70+
# Highlight the latest value with annotation
71+
latest_value = df_visible.iloc[-1]["cpu_usage"]
72+
latest_time = df_visible.iloc[-1]["timestamp"]
73+
ax.annotate(
74+
f"Latest: {latest_value:.1f}%",
75+
xy=(latest_time, latest_value),
76+
xytext=(15, 25),
77+
textcoords="offset points",
78+
fontsize=18,
79+
fontweight="bold",
80+
color="#306998",
81+
bbox={"boxstyle": "round,pad=0.4", "facecolor": "#FFD43B", "edgecolor": "#306998", "linewidth": 2},
82+
arrowprops={"arrowstyle": "->", "color": "#306998", "linewidth": 2},
83+
)
84+
85+
# Add arrow indicating scroll direction (old data scrolls off left)
86+
ax.annotate(
87+
"",
88+
xy=(df_visible.iloc[0]["timestamp"], 92),
89+
xytext=(df_visible.iloc[8]["timestamp"], 92),
90+
arrowprops={"arrowstyle": "<-", "color": "#666666", "linewidth": 2.5, "mutation_scale": 15},
91+
)
92+
ax.text(
93+
df_visible.iloc[4]["timestamp"],
94+
96,
95+
"← Old data scrolls off",
96+
fontsize=13,
97+
color="#666666",
98+
ha="center",
99+
style="italic",
100+
)
101+
102+
# Styling
103+
ax.set_xlabel("Time (HH:MM:SS)", fontsize=20)
104+
ax.set_ylabel("CPU Usage (%)", fontsize=20)
105+
ax.set_title("line-realtime · seaborn · pyplots.ai", fontsize=24, fontweight="bold")
106+
ax.tick_params(axis="both", labelsize=16)
107+
108+
# Format x-axis time labels (cleaner format)
109+
ax.xaxis.set_major_formatter(DateFormatter("%H:%M:%S"))
110+
plt.xticks(rotation=25, ha="right")
111+
112+
# Set y-axis limits with padding
113+
ax.set_ylim(0, 100)
114+
115+
# Grid styling
116+
ax.grid(True, alpha=0.3, linestyle="--")
117+
ax.set_facecolor("#fafafa")
118+
119+
# Add live indicator with pulsing effect simulation
120+
ax.text(
121+
0.02,
122+
0.96,
123+
"● LIVE",
124+
transform=ax.transAxes,
125+
fontsize=18,
126+
fontweight="bold",
127+
color="#e74c3c",
128+
verticalalignment="top",
129+
)
130+
131+
# Add window info
132+
ax.text(
133+
0.98,
134+
0.02,
135+
f"Sliding window: {visible_points} samples (6 sec)",
136+
transform=ax.transAxes,
137+
fontsize=13,
138+
color="#666666",
139+
ha="right",
140+
va="bottom",
141+
)
142+
143+
plt.tight_layout()
144+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: seaborn
2+
specification_id: line-realtime
3+
created: '2025-12-31T14:06:35Z'
4+
updated: '2025-12-31T14:18:42Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620498178
7+
issue: 3073
8+
python_version: 3.13.11
9+
library_version: 0.13.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-realtime/seaborn/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-realtime/seaborn/plot_thumb.png
12+
preview_html: null
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent visual communication of real-time concept with LIVE indicator and scroll
17+
direction arrow
18+
- Latest value annotation with contrasting yellow background draws attention effectively
19+
- Alpha gradient fade effect successfully conveys older data visually
20+
- Proper sliding window implementation showing 60 of 100 generated points
21+
- Clean title format and axis labels with units
22+
- Realistic CPU monitoring scenario with appropriate value ranges
23+
weaknesses:
24+
- Calling sns.lineplot 59 times in a loop is inefficient; consider using matplotlib
25+
LineCollection for gradient or a single seaborn call with post-processing
26+
- Data lacks dramatic variation - mostly hovers around 35-50% with only one visible
27+
spike

0 commit comments

Comments
 (0)