Skip to content

Commit a833d38

Browse files
feat(highcharts): implement bar-error (#2407)
## Implementation: `bar-error` - highcharts Implements the **highcharts** version of `bar-error`. **File:** `plots/bar-error/implementations/highcharts.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20543283403)* --------- 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 4260854 commit a833d38

2 files changed

Lines changed: 239 additions & 0 deletions

File tree

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
""" pyplots.ai
2+
bar-error: Bar Chart with Error Bars
3+
Library: highcharts unknown | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-27
5+
"""
6+
7+
import tempfile
8+
import time
9+
import urllib.request
10+
from pathlib import Path
11+
12+
from highcharts_core.chart import Chart
13+
from highcharts_core.options import HighchartsOptions
14+
from highcharts_core.options.series.bar import ColumnSeries
15+
from selenium import webdriver
16+
from selenium.webdriver.chrome.options import Options
17+
18+
19+
# Data - Treatment comparison with ±1 SD error bars
20+
categories = ["Control", "Treatment A", "Treatment B", "Treatment C", "Treatment D"]
21+
values = [42.3, 58.7, 51.2, 67.8, 45.9]
22+
errors = [5.2, 7.1, 4.8, 8.3, 6.0] # Standard deviation
23+
24+
# Download Highcharts JS (required for headless Chrome)
25+
highcharts_url = "https://code.highcharts.com/highcharts.js"
26+
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
27+
highcharts_js = response.read().decode("utf-8")
28+
29+
# Download highcharts-more.js for error bars
30+
highcharts_more_url = "https://code.highcharts.com/highcharts-more.js"
31+
with urllib.request.urlopen(highcharts_more_url, timeout=30) as response:
32+
highcharts_more_js = response.read().decode("utf-8")
33+
34+
# Create chart with container
35+
chart = Chart(container="container")
36+
chart.options = HighchartsOptions()
37+
38+
# Chart configuration
39+
chart.options.chart = {
40+
"type": "column",
41+
"width": 4800,
42+
"height": 2700,
43+
"backgroundColor": "#ffffff",
44+
"marginBottom": 180,
45+
"style": {"fontFamily": "Arial, sans-serif"},
46+
}
47+
48+
# Title
49+
chart.options.title = {
50+
"text": "bar-error \u00b7 highcharts \u00b7 pyplots.ai",
51+
"style": {"fontSize": "48px", "fontWeight": "bold"},
52+
}
53+
54+
# Subtitle explaining error bars
55+
chart.options.subtitle = {
56+
"text": "Error bars represent \u00b11 Standard Deviation",
57+
"style": {"fontSize": "28px", "color": "#666666"},
58+
}
59+
60+
# X-axis
61+
chart.options.x_axis = {
62+
"categories": categories,
63+
"title": {"text": "Treatment Group", "style": {"fontSize": "32px"}},
64+
"labels": {"style": {"fontSize": "26px"}},
65+
}
66+
67+
# Y-axis
68+
chart.options.y_axis = {
69+
"title": {"text": "Response Value (units)", "style": {"fontSize": "32px"}},
70+
"labels": {"style": {"fontSize": "24px"}},
71+
"min": 0,
72+
"gridLineWidth": 1,
73+
"gridLineColor": "#e0e0e0",
74+
}
75+
76+
# Legend
77+
chart.options.legend = {"enabled": True, "itemStyle": {"fontSize": "24px"}, "symbolHeight": 20, "symbolWidth": 30}
78+
79+
# Plot options
80+
chart.options.plot_options = {
81+
"column": {"pointPadding": 0.2, "borderWidth": 1, "borderColor": "#1a4d73"},
82+
"errorbar": {"whiskerLength": "60%", "whiskerWidth": 4, "stemWidth": 4, "color": "#333333"},
83+
}
84+
85+
# Create column series
86+
column_series = ColumnSeries()
87+
column_series.name = "Mean Value"
88+
column_series.data = values
89+
column_series.color = "#306998"
90+
91+
# Add series to chart
92+
chart.add_series(column_series)
93+
94+
# Generate HTML with inline Highcharts and error bar configuration
95+
html_str = chart.to_js_literal()
96+
97+
# Build error bar data for Highcharts errorbar series
98+
error_bar_data = [[v - e, v + e] for v, e in zip(values, errors, strict=True)]
99+
100+
# Create custom HTML with error bar series added
101+
html_content = f"""<!DOCTYPE html>
102+
<html>
103+
<head>
104+
<meta charset="utf-8">
105+
<script>{highcharts_js}</script>
106+
<script>{highcharts_more_js}</script>
107+
</head>
108+
<body style="margin:0;">
109+
<div id="container" style="width: 4800px; height: 2700px;"></div>
110+
<script>
111+
Highcharts.chart('container', {{
112+
chart: {{
113+
type: 'column',
114+
width: 4800,
115+
height: 2700,
116+
backgroundColor: '#ffffff',
117+
marginBottom: 300,
118+
marginLeft: 180,
119+
style: {{ fontFamily: 'Arial, sans-serif' }}
120+
}},
121+
title: {{
122+
text: 'bar-error \u00b7 highcharts \u00b7 pyplots.ai',
123+
style: {{ fontSize: '56px', fontWeight: 'bold' }}
124+
}},
125+
subtitle: {{
126+
text: 'Error bars represent \u00b11 Standard Deviation',
127+
style: {{ fontSize: '32px', color: '#666666' }}
128+
}},
129+
xAxis: {{
130+
categories: {categories},
131+
title: {{
132+
text: 'Treatment Group',
133+
style: {{ fontSize: '36px' }},
134+
margin: 20
135+
}},
136+
labels: {{ style: {{ fontSize: '28px' }} }}
137+
}},
138+
yAxis: {{
139+
title: {{
140+
text: 'Response Value (units)',
141+
style: {{ fontSize: '36px' }},
142+
margin: 20
143+
}},
144+
labels: {{ style: {{ fontSize: '26px' }} }},
145+
min: 0,
146+
gridLineWidth: 1,
147+
gridLineColor: '#e0e0e0',
148+
gridLineDashStyle: 'Dash'
149+
}},
150+
legend: {{
151+
enabled: true,
152+
itemStyle: {{ fontSize: '28px' }},
153+
symbolHeight: 24,
154+
symbolWidth: 36,
155+
align: 'right',
156+
verticalAlign: 'top',
157+
y: 80,
158+
x: -40
159+
}},
160+
plotOptions: {{
161+
column: {{
162+
pointPadding: 0.2,
163+
borderWidth: 2,
164+
borderColor: '#1a4d73'
165+
}},
166+
errorbar: {{
167+
whiskerLength: '50%',
168+
whiskerWidth: 5,
169+
stemWidth: 5,
170+
color: '#333333'
171+
}}
172+
}},
173+
series: [{{
174+
name: 'Mean Value',
175+
type: 'column',
176+
data: {values},
177+
color: '#306998'
178+
}}, {{
179+
name: 'Error (\u00b11 SD)',
180+
type: 'errorbar',
181+
data: {error_bar_data},
182+
stemColor: '#333333',
183+
whiskerColor: '#333333'
184+
}}]
185+
}});
186+
</script>
187+
</body>
188+
</html>"""
189+
190+
# Write temp HTML and take screenshot
191+
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
192+
f.write(html_content)
193+
temp_path = f.name
194+
195+
# Also save the HTML file
196+
Path("plot.html").write_text(html_content, encoding="utf-8")
197+
198+
# Setup Chrome options for headless rendering
199+
chrome_options = Options()
200+
chrome_options.add_argument("--headless")
201+
chrome_options.add_argument("--no-sandbox")
202+
chrome_options.add_argument("--disable-dev-shm-usage")
203+
chrome_options.add_argument("--disable-gpu")
204+
chrome_options.add_argument("--window-size=4800,2800")
205+
206+
driver = webdriver.Chrome(options=chrome_options)
207+
driver.get(f"file://{temp_path}")
208+
time.sleep(5) # Wait for chart to render
209+
driver.save_screenshot("plot.png")
210+
driver.quit()
211+
212+
Path(temp_path).unlink() # Clean up temp file
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
library: highcharts
2+
specification_id: bar-error
3+
created: '2025-12-27T19:22:37Z'
4+
updated: '2025-12-27T19:30:00Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20543283403
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: unknown
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/bar-error/highcharts/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/bar-error/highcharts/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/bar-error/highcharts/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent use of Highcharts errorbar series with proper whisker styling (caps
17+
visible)
18+
- Clear subtitle explaining what error bars represent (±1 SD) as required by spec
19+
- Professional appearance with colorblind-safe color palette
20+
- Properly downloads and inlines Highcharts JS for headless rendering
21+
- Clean separation between bar series and errorbar series
22+
- Good canvas utilization with appropriate margins
23+
weaknesses:
24+
- Legend appears to only show Mean Value entry; the Error series legend entry is
25+
not visible in the rendered image
26+
- Could demonstrate asymmetric error bars to fully showcase the capability mentioned
27+
in spec

0 commit comments

Comments
 (0)