Skip to content

Commit 6173c84

Browse files
feat(letsplot): implement line-realtime (#3135)
## Implementation: `line-realtime` - letsplot Implements the **letsplot** version of `line-realtime`. **File:** `plots/line-realtime/implementations/letsplot.py` **Parent Issue:** #3073 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20620617983)* --------- 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 70eeddd commit 6173c84

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
""" pyplots.ai
2+
line-realtime: Real-Time Updating Line Chart
3+
Library: letsplot 4.8.2 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-31
5+
"""
6+
7+
import numpy as np
8+
import pandas as pd
9+
from lets_plot import (
10+
LetsPlot,
11+
aes,
12+
element_blank,
13+
element_line,
14+
element_text,
15+
geom_area,
16+
geom_hline,
17+
geom_line,
18+
geom_point,
19+
geom_text,
20+
ggplot,
21+
ggsize,
22+
labs,
23+
scale_alpha_identity,
24+
scale_y_continuous,
25+
theme,
26+
theme_minimal,
27+
)
28+
from lets_plot.export import ggsave
29+
30+
31+
LetsPlot.setup_html()
32+
33+
# Data - Simulated CPU usage with real-time streaming effect
34+
np.random.seed(42)
35+
n_points = 100
36+
37+
# Generate realistic CPU usage with some noise and occasional spikes
38+
base_usage = 35 + 15 * np.sin(np.linspace(0, 4 * np.pi, n_points)) # Oscillating base
39+
noise = np.random.normal(0, 5, n_points)
40+
spikes = np.zeros(n_points)
41+
spike_indices = [25, 48, 72, 88]
42+
for idx in spike_indices:
43+
spikes[idx : idx + 3] = np.array([15, 25, 10])[: min(3, n_points - idx)]
44+
cpu_usage = np.clip(base_usage + noise + spikes, 0, 100)
45+
46+
# Create alpha gradient for fade effect (older points fade out)
47+
alpha_values = np.linspace(0.2, 1.0, n_points)
48+
49+
# Use numeric index for x-axis
50+
df = pd.DataFrame({"x_idx": range(n_points), "cpu_usage": cpu_usage, "alpha": alpha_values})
51+
52+
# Get latest value for annotation
53+
latest_value = cpu_usage[-1]
54+
55+
# Create annotation dataframes
56+
annotation_current = pd.DataFrame(
57+
{"x_idx": [n_points - 1], "cpu_usage": [latest_value + 8], "label": [f"Current: {latest_value:.1f}%"]}
58+
)
59+
annotation_fade = pd.DataFrame({"x_idx": [5], "cpu_usage": [10], "label": ["← older data fades"]})
60+
annotation_threshold = pd.DataFrame({"x_idx": [n_points - 1], "cpu_usage": [83], "label": ["Warning threshold"]})
61+
62+
# Create the plot with streaming visualization effect
63+
plot = (
64+
ggplot(df, aes(x="x_idx", y="cpu_usage"))
65+
# Main line
66+
+ geom_line(color="#306998", size=2.5, alpha=0.9)
67+
# Add area fill for visual depth
68+
+ geom_area(fill="#306998", alpha=0.15)
69+
# Add points with size/alpha gradient to show streaming direction
70+
+ geom_point(aes(alpha="alpha"), color="#306998", size=3, show_legend=False)
71+
# Highlight the latest point prominently
72+
+ geom_point(
73+
data=df.tail(1),
74+
mapping=aes(x="x_idx", y="cpu_usage"),
75+
color="#FFD43B",
76+
size=8,
77+
shape=21,
78+
fill="#FFD43B",
79+
stroke=2,
80+
)
81+
# Add horizontal reference lines for CPU thresholds
82+
+ geom_hline(yintercept=80, linetype="dashed", color="#DC2626", alpha=0.6, size=1)
83+
+ geom_hline(yintercept=50, linetype="dotted", color="#888888", alpha=0.4, size=0.8)
84+
# Add text annotations using geom_text
85+
+ geom_text(
86+
data=annotation_current,
87+
mapping=aes(x="x_idx", y="cpu_usage", label="label"),
88+
color="#FFD43B",
89+
size=16,
90+
fontface="bold",
91+
hjust=1,
92+
)
93+
+ geom_text(
94+
data=annotation_fade, mapping=aes(x="x_idx", y="cpu_usage", label="label"), color="#888888", size=12, hjust=0
95+
)
96+
+ geom_text(
97+
data=annotation_threshold,
98+
mapping=aes(x="x_idx", y="cpu_usage", label="label"),
99+
color="#DC2626",
100+
size=11,
101+
hjust=1,
102+
)
103+
# Labels and title
104+
+ labs(title="line-realtime · letsplot · pyplots.ai", x="Time (samples at 100ms interval)", y="CPU Usage (%)")
105+
# Scale configuration
106+
+ scale_y_continuous(limits=[0, 100], breaks=[0, 25, 50, 75, 100])
107+
+ scale_alpha_identity()
108+
# Theme for large canvas
109+
+ theme_minimal()
110+
+ theme(
111+
plot_title=element_text(size=28, face="bold"),
112+
axis_title=element_text(size=22),
113+
axis_text=element_text(size=16),
114+
panel_grid_major=element_line(color="#cccccc", size=0.5),
115+
panel_grid_minor=element_blank(),
116+
)
117+
# Set figure size (will be scaled 3x to 4800x2700)
118+
+ ggsize(1600, 900)
119+
)
120+
121+
# Save PNG (scale=3 gives 4800x2700)
122+
ggsave(plot, "plot.png", path=".", scale=3)
123+
124+
# Save HTML for interactivity
125+
ggsave(plot, "plot.html", path=".")
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
library: letsplot
2+
specification_id: line-realtime
3+
created: '2025-12-31T14:14:33Z'
4+
updated: '2025-12-31T14:49:35Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20620617983
7+
issue: 3073
8+
python_version: 3.13.11
9+
library_version: 4.8.2
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-realtime/letsplot/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-realtime/letsplot/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-realtime/letsplot/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent visual representation of real-time monitoring concept with clear current
17+
value annotation
18+
- Well-implemented fade effect indication with text annotation and threshold reference
19+
lines
20+
- Clean code structure following KISS principles with proper reproducibility
21+
- Good use of lets-plot ggplot2 grammar including multiple geom layers
22+
- Professional color scheme with accessible colors (blue line, yellow highlight,
23+
red threshold)
24+
- Proper figure sizing with scale=3 for high-resolution output
25+
weaknesses:
26+
- Title uses letsplot instead of lets-plot - should match the official library name
27+
format
28+
- The point alpha gradient (fade effect) is implemented but barely visible in the
29+
output; the text annotation helps but actual visual fade would be stronger
30+
- Grid alpha at 0.5 could be more subtle (0.2-0.3 recommended)

0 commit comments

Comments
 (0)