Skip to content

Commit 314a914

Browse files
feat(plotly): implement line-realtime (#3123)
## Implementation: `line-realtime` - plotly Implements the **plotly** version of `line-realtime`. **File:** `plots/line-realtime/implementations/plotly.py` **Parent Issue:** #3073 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620491102)* --------- 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 6f1d1c7 commit 314a914

2 files changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
""" pyplots.ai
2+
line-realtime: Real-Time Updating Line Chart
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 92/100 | Created: 2025-12-31
5+
"""
6+
7+
import numpy as np
8+
import plotly.graph_objects as go
9+
10+
11+
# Data - Simulated CPU usage with sliding window effect
12+
np.random.seed(42)
13+
n_points = 120
14+
time_seconds = np.arange(n_points)
15+
16+
# Generate realistic CPU usage pattern with some spikes
17+
base_cpu = 35 + 10 * np.sin(time_seconds * 0.1) # Slow oscillation
18+
noise = np.random.normal(0, 5, n_points)
19+
spikes = np.zeros(n_points)
20+
spike_positions = [25, 45, 70, 95]
21+
for pos in spike_positions:
22+
spikes[pos : pos + 5] = np.array([15, 25, 20, 10, 5])
23+
cpu_usage = np.clip(base_cpu + noise + spikes, 0, 100)
24+
25+
# Create figure with gradient fill to show live data effect
26+
fig = go.Figure()
27+
28+
# Main line trace
29+
fig.add_trace(
30+
go.Scatter(
31+
x=time_seconds,
32+
y=cpu_usage,
33+
mode="lines",
34+
name="CPU Usage",
35+
line={"color": "#306998", "width": 3},
36+
fill="tozeroy",
37+
fillcolor="rgba(48, 105, 152, 0.2)",
38+
)
39+
)
40+
41+
# Add marker for the latest value (to emphasize real-time aspect)
42+
latest_idx = n_points - 1
43+
fig.add_trace(
44+
go.Scatter(
45+
x=[time_seconds[latest_idx]],
46+
y=[cpu_usage[latest_idx]],
47+
mode="markers+text",
48+
name=f"Current: {cpu_usage[latest_idx]:.1f}%",
49+
marker={"color": "#FFD43B", "size": 18, "line": {"color": "#306998", "width": 2}},
50+
text=[f"{cpu_usage[latest_idx]:.1f}%"],
51+
textposition="top center",
52+
textfont={"size": 20, "color": "#306998"},
53+
)
54+
)
55+
56+
# Add fade effect on the left side using shapes to indicate scrolling direction
57+
# Create gradient overlay shapes for the trailing edge
58+
for i in range(10):
59+
alpha = 0.08 * (10 - i)
60+
fig.add_vrect(x0=i * 2, x1=(i + 1) * 2, fillcolor=f"rgba(255, 255, 255, {alpha})", layer="above", line_width=0)
61+
62+
# Add arrow annotation to show scrolling direction
63+
fig.add_annotation(
64+
x=5,
65+
y=90,
66+
ax=25,
67+
ay=90,
68+
xref="x",
69+
yref="y",
70+
axref="x",
71+
ayref="y",
72+
showarrow=True,
73+
arrowhead=2,
74+
arrowsize=1.5,
75+
arrowwidth=3,
76+
arrowcolor="#306998",
77+
)
78+
fig.add_annotation(
79+
x=15, y=92, text="← Data scrolls", showarrow=False, font={"size": 18, "color": "#306998"}, xref="x", yref="y"
80+
)
81+
82+
# Layout for 4800x2700
83+
fig.update_layout(
84+
title={
85+
"text": "CPU Usage Monitor · line-realtime · plotly · pyplots.ai",
86+
"font": {"size": 32, "color": "#333333"},
87+
"x": 0.5,
88+
"xanchor": "center",
89+
},
90+
xaxis={
91+
"title": {"text": "Time (seconds)", "font": {"size": 24}},
92+
"tickfont": {"size": 18},
93+
"showgrid": True,
94+
"gridwidth": 1,
95+
"gridcolor": "rgba(0, 0, 0, 0.1)",
96+
"range": [0, n_points + 5],
97+
},
98+
yaxis={
99+
"title": {"text": "CPU Usage (%)", "font": {"size": 24}},
100+
"tickfont": {"size": 18},
101+
"showgrid": True,
102+
"gridwidth": 1,
103+
"gridcolor": "rgba(0, 0, 0, 0.1)",
104+
"range": [0, 105],
105+
},
106+
template="plotly_white",
107+
showlegend=True,
108+
legend={
109+
"font": {"size": 18},
110+
"x": 0.98,
111+
"y": 0.98,
112+
"xanchor": "right",
113+
"yanchor": "top",
114+
"bgcolor": "rgba(255, 255, 255, 0.8)",
115+
"bordercolor": "#306998",
116+
"borderwidth": 1,
117+
},
118+
margin={"l": 100, "r": 80, "t": 120, "b": 100},
119+
)
120+
121+
# Add live indicator annotation
122+
fig.add_annotation(
123+
x=0.95,
124+
y=0.05,
125+
xref="paper",
126+
yref="paper",
127+
text="● LIVE",
128+
showarrow=False,
129+
font={"size": 22, "color": "#e74c3c", "family": "Arial Black"},
130+
bgcolor="rgba(255, 255, 255, 0.9)",
131+
borderpad=8,
132+
)
133+
134+
# Save as PNG (4800x2700)
135+
fig.write_image("plot.png", width=1600, height=900, scale=3)
136+
137+
# Save as interactive HTML
138+
fig.write_html("plot.html", include_plotlyjs=True, full_html=True)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: plotly
2+
specification_id: line-realtime
3+
created: '2025-12-31T14:05:59Z'
4+
updated: '2025-12-31T14:15:56Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620491102
7+
issue: 3073
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-realtime/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-realtime/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-realtime/plotly/plot.html
13+
quality_score: 92
14+
review:
15+
strengths:
16+
- Excellent implementation of real-time visualization indicators (LIVE badge, current
17+
value marker, scrolling direction arrow)
18+
- Creative use of vrect shapes to create fade effect indicating data scroll direction
19+
- Well-structured code with realistic CPU usage data including oscillation pattern
20+
and spikes
21+
- Good use of Plotly annotation system for the arrow and text labels
22+
- Outputs both static PNG and interactive HTML versions
23+
weaknesses:
24+
- Title format includes extra descriptor before spec-id instead of exact format
25+
- Fade effect using vrect covers some data points reducing left portion readability
26+
- Grid alpha at 0.1 is too subtle, could be 0.2-0.3 for better visibility

0 commit comments

Comments
 (0)