Skip to content

Commit a645337

Browse files
feat(matplotlib): implement line-realtime (#3122)
## Implementation: `line-realtime` - matplotlib Implements the **matplotlib** version of `line-realtime`. **File:** `plots/line-realtime/implementations/matplotlib.py` **Parent Issue:** #3073 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620484861)* --------- 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 2835db8 commit a645337

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
""" pyplots.ai
2+
line-realtime: Real-Time Updating Line Chart
3+
Library: matplotlib 3.10.8 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-31
5+
"""
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
from matplotlib.patches import FancyArrowPatch
10+
11+
12+
# Data - Simulated CPU usage monitoring with sliding window
13+
np.random.seed(42)
14+
n_points = 100
15+
visible_points = 60
16+
17+
# Generate realistic CPU usage pattern (0-100%)
18+
base_usage = 45 + 15 * np.sin(np.linspace(0, 4 * np.pi, n_points))
19+
noise = np.random.normal(0, 5, n_points)
20+
spikes = np.zeros(n_points)
21+
spike_indices = [15, 35, 55, 78]
22+
for idx in spike_indices:
23+
spikes[idx : idx + 3] = np.array([20, 15, 8])[: min(3, n_points - idx)]
24+
25+
cpu_usage = np.clip(base_usage + noise + spikes, 0, 100)
26+
27+
# Time axis (seconds ago, with most recent on right)
28+
time_seconds = np.arange(n_points) * 0.1
29+
30+
# Visible window (last 60 points)
31+
visible_time = time_seconds[-visible_points:]
32+
visible_cpu = cpu_usage[-visible_points:]
33+
34+
# Current value for prominent display
35+
current_value = visible_cpu[-1]
36+
37+
# Create plot
38+
fig, ax = plt.subplots(figsize=(16, 9))
39+
40+
# Create gradient fill effect using multiple fills with decreasing alpha
41+
n_gradient = 10
42+
for i in range(n_gradient):
43+
alpha_fill = 0.05 + 0.15 * (i / n_gradient)
44+
y_offset = visible_cpu * (1 - 0.02 * (n_gradient - i))
45+
ax.fill_between(visible_time, 0, y_offset, alpha=alpha_fill, color="#306998", linewidth=0)
46+
47+
# Main line with gradient effect (darker at right/newer)
48+
colors = np.linspace(0.3, 1.0, visible_points)
49+
for i in range(len(visible_time) - 1):
50+
ax.plot(
51+
visible_time[i : i + 2],
52+
visible_cpu[i : i + 2],
53+
color="#306998",
54+
alpha=colors[i],
55+
linewidth=3,
56+
solid_capstyle="round",
57+
)
58+
59+
# Fade effect on left edge (older data)
60+
fade_width = 8
61+
for i in range(fade_width):
62+
fade_alpha = 1 - (fade_width - i) / fade_width
63+
ax.axvspan(visible_time[i], visible_time[i + 1], alpha=0.3 * (1 - fade_alpha), color="white", zorder=2)
64+
65+
# Arrow indicating scroll direction (data flowing left)
66+
arrow = FancyArrowPatch(
67+
(visible_time[5], 85),
68+
(visible_time[0], 85),
69+
arrowstyle="->",
70+
mutation_scale=25,
71+
color="#666666",
72+
linewidth=2,
73+
alpha=0.7,
74+
)
75+
ax.add_patch(arrow)
76+
ax.text(visible_time[2], 90, "← older data", fontsize=14, color="#666666", ha="center")
77+
78+
# Current value indicator
79+
ax.scatter([visible_time[-1]], [current_value], s=300, color="#FFD43B", zorder=5, edgecolor="#306998", linewidth=2)
80+
ax.annotate(
81+
f"{current_value:.1f}%",
82+
(visible_time[-1], current_value),
83+
xytext=(15, 10),
84+
textcoords="offset points",
85+
fontsize=18,
86+
fontweight="bold",
87+
color="#306998",
88+
bbox={"boxstyle": "round,pad=0.3", "facecolor": "#FFD43B", "edgecolor": "#306998", "alpha": 0.9},
89+
)
90+
91+
# Current time label
92+
ax.text(visible_time[-1], -8, "NOW", fontsize=14, fontweight="bold", color="#306998", ha="center")
93+
94+
# Styling
95+
ax.set_xlabel("Time (seconds)", fontsize=20)
96+
ax.set_ylabel("CPU Usage (%)", fontsize=20)
97+
ax.set_title("line-realtime · matplotlib · pyplots.ai", fontsize=24)
98+
ax.tick_params(axis="both", labelsize=16)
99+
100+
# Y-axis from 0 to 100 for CPU percentage
101+
ax.set_ylim(-12, 105)
102+
ax.set_xlim(visible_time[0] - 0.2, visible_time[-1] + 0.8)
103+
104+
# Grid
105+
ax.grid(True, alpha=0.3, linestyle="--")
106+
107+
# Add horizontal threshold line
108+
ax.axhline(y=80, color="#CC4444", linestyle="--", linewidth=2, alpha=0.6)
109+
ax.text(visible_time[-1] + 0.3, 80, "Warning", fontsize=12, color="#CC4444", va="center")
110+
111+
plt.tight_layout()
112+
plt.savefig("plot.png", dpi=300, bbox_inches="tight")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: matplotlib
2+
specification_id: line-realtime
3+
created: '2025-12-31T14:05:13Z'
4+
updated: '2025-12-31T14:15:39Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620484861
7+
issue: 3073
8+
python_version: 3.13.11
9+
library_version: 3.10.8
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-realtime/matplotlib/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-realtime/matplotlib/plot_thumb.png
12+
preview_html: null
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent implementation of sliding window concept with fade effect on older data
17+
- Creative gradient fill technique using layered fill_between calls
18+
- Prominent current value indicator with yellow badge is highly visible
19+
- Clear scroll direction arrow with text annotation
20+
- Warning threshold line adds practical monitoring context
21+
- Realistic CPU usage data pattern with sinusoidal base and random spikes
22+
- Perfect title format and axis labels with units
23+
weaknesses:
24+
- Missing legend entry for the warning threshold line (just has text label "Warning")
25+
- The gradient effect on the line itself (segment-by-segment plotting) could be
26+
smoother

0 commit comments

Comments
 (0)