Skip to content

Commit 975a8aa

Browse files
feat(highcharts): implement line-stepwise (#2642)
## Implementation: `line-stepwise` - highcharts Implements the **highcharts** version of `line-stepwise`. **File:** `plots/line-stepwise/implementations/highcharts.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20594565437)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 9413de8 commit 975a8aa

2 files changed

Lines changed: 190 additions & 0 deletions

File tree

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
""" pyplots.ai
2+
line-stepwise: Step Line Plot
3+
Library: highcharts unknown | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import tempfile
8+
import time
9+
import urllib.request
10+
from pathlib import Path
11+
12+
import numpy as np
13+
from highcharts_core.chart import Chart
14+
from highcharts_core.options import HighchartsOptions
15+
from highcharts_core.options.series.area import LineSeries
16+
from selenium import webdriver
17+
from selenium.webdriver.chrome.options import Options
18+
19+
20+
# Data - Server response time over monitoring period (discrete changes)
21+
np.random.seed(42)
22+
hours = np.arange(0, 24)
23+
# Simulate server response times that change discretely throughout the day
24+
base_response = 45
25+
response_times = np.zeros(24)
26+
response_times[0:6] = base_response + np.random.randint(0, 10, 6) # Night: low load
27+
response_times[6:9] = base_response + 25 + np.random.randint(0, 15, 3) # Morning spike
28+
response_times[9:12] = base_response + 15 + np.random.randint(0, 10, 3) # Mid-morning
29+
response_times[12:14] = base_response + 30 + np.random.randint(0, 20, 2) # Lunch peak
30+
response_times[14:17] = base_response + 20 + np.random.randint(0, 15, 3) # Afternoon
31+
response_times[17:20] = base_response + 35 + np.random.randint(0, 20, 3) # Evening peak
32+
response_times[20:24] = base_response + 5 + np.random.randint(0, 10, 4) # Night decline
33+
34+
# Create chart
35+
chart = Chart(container="container")
36+
chart.options = HighchartsOptions()
37+
38+
# Chart configuration for 4800x2700 px
39+
chart.options.chart = {
40+
"type": "line",
41+
"width": 4800,
42+
"height": 2700,
43+
"backgroundColor": "#ffffff",
44+
"marginBottom": 250,
45+
"marginLeft": 180,
46+
"marginTop": 150,
47+
}
48+
49+
# Title
50+
chart.options.title = {
51+
"text": "line-stepwise · highcharts · pyplots.ai",
52+
"style": {"fontSize": "48px", "fontWeight": "bold"},
53+
}
54+
55+
chart.options.subtitle = {"text": "Server Response Time (24-Hour Monitoring)", "style": {"fontSize": "32px"}}
56+
57+
# X-axis configuration
58+
chart.options.x_axis = {
59+
"title": {"text": "Hour of Day", "style": {"fontSize": "40px"}, "margin": 20},
60+
"labels": {"style": {"fontSize": "28px"}, "y": 35},
61+
"categories": [f"{h:02d}:00" for h in hours],
62+
"tickInterval": 2,
63+
"lineWidth": 2,
64+
"tickWidth": 2,
65+
}
66+
67+
# Y-axis configuration
68+
chart.options.y_axis = {
69+
"title": {"text": "Response Time (ms)", "style": {"fontSize": "40px"}, "margin": 20},
70+
"labels": {"style": {"fontSize": "28px"}, "x": -10},
71+
"min": 40,
72+
"max": 100,
73+
"gridLineColor": "#e0e0e0",
74+
"gridLineWidth": 1,
75+
"lineWidth": 2,
76+
}
77+
78+
# Plot options - enable step line
79+
chart.options.plot_options = {
80+
"line": {
81+
"step": "left", # Step before the point (horizontal-then-vertical)
82+
"lineWidth": 6,
83+
"marker": {"enabled": True, "radius": 12, "symbol": "circle"},
84+
}
85+
}
86+
87+
# Legend configuration
88+
chart.options.legend = {
89+
"enabled": True,
90+
"itemStyle": {"fontSize": "28px"},
91+
"align": "right",
92+
"verticalAlign": "top",
93+
"x": -50,
94+
"y": 100,
95+
}
96+
97+
# Create series
98+
series = LineSeries()
99+
series.name = "Response Time"
100+
series.data = [float(v) for v in response_times]
101+
series.color = "#306998" # Python Blue
102+
series.marker = {"fillColor": "#306998", "lineWidth": 2, "lineColor": "#ffffff"}
103+
104+
chart.add_series(series)
105+
106+
# Download Highcharts JS for headless Chrome
107+
highcharts_url = "https://code.highcharts.com/highcharts.js"
108+
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
109+
highcharts_js = response.read().decode("utf-8")
110+
111+
# Generate HTML with inline scripts
112+
html_str = chart.to_js_literal()
113+
html_content = f"""<!DOCTYPE html>
114+
<html>
115+
<head>
116+
<meta charset="utf-8">
117+
<script>{highcharts_js}</script>
118+
</head>
119+
<body style="margin:0;">
120+
<div id="container" style="width: 4800px; height: 2700px;"></div>
121+
<script>{html_str}</script>
122+
</body>
123+
</html>"""
124+
125+
# Write temp HTML and take screenshot
126+
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
127+
f.write(html_content)
128+
temp_path = f.name
129+
130+
# Also save the HTML file for interactive viewing
131+
with open("plot.html", "w", encoding="utf-8") as f:
132+
# For the saved HTML, use CDN for broader compatibility
133+
html_cdn = (
134+
"""<!DOCTYPE html>
135+
<html>
136+
<head>
137+
<meta charset="utf-8">
138+
<script src="https://code.highcharts.com/highcharts.js"></script>
139+
</head>
140+
<body style="margin:0;">
141+
<div id="container" style="width: 100%; height: 100vh;"></div>
142+
<script>"""
143+
+ html_str
144+
+ """</script>
145+
</body>
146+
</html>"""
147+
)
148+
f.write(html_cdn)
149+
150+
# Take screenshot with headless Chrome
151+
chrome_options = Options()
152+
chrome_options.add_argument("--headless")
153+
chrome_options.add_argument("--no-sandbox")
154+
chrome_options.add_argument("--disable-dev-shm-usage")
155+
chrome_options.add_argument("--disable-gpu")
156+
chrome_options.add_argument("--window-size=4800,2700")
157+
158+
driver = webdriver.Chrome(options=chrome_options)
159+
driver.get(f"file://{temp_path}")
160+
time.sleep(5) # Wait for chart to render
161+
driver.save_screenshot("plot.png")
162+
driver.quit()
163+
164+
Path(temp_path).unlink() # Clean up temp file
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: highcharts
2+
specification_id: line-stepwise
3+
created: '2025-12-30T10:45:53Z'
4+
updated: '2025-12-30T10:52:11Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20594565437
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: unknown
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/line-stepwise/highcharts/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/line-stepwise/highcharts/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/line-stepwise/highcharts/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- 'Excellent implementation of step line using Highcharts native step: left option'
17+
- Realistic and relevant data scenario (server response time monitoring)
18+
- Clear step pattern showing discrete value changes throughout the day
19+
- Proper title format following spec requirements
20+
- Good use of subtitle for additional context
21+
- Clean KISS code structure with reproducible seed
22+
- Saves both PNG and interactive HTML output
23+
weaknesses:
24+
- Image dimensions slightly off (2561 vs 2700 height)
25+
- Legend could be slightly larger for better visibility at high resolution
26+
- Could utilize more Highcharts-specific interactive features like custom tooltips

0 commit comments

Comments
 (0)