Skip to content

Commit bc5273c

Browse files
update(pie-basic): highcharts — comprehensive quality review (#4222)
## Summary Updated **highcharts** implementation for **pie-basic**. **Changes:** Comprehensive review improving code quality, data choice, visual design, spec compliance, and library feature usage. ## Test Plan - [x] Preview images uploaded to GCS staging - [x] Implementation file passes ruff format/check - [x] Metadata YAML updated with current versions - [ ] Automated review triggered --- Generated with [Claude Code](https://claude.com/claude-code) `/update` command --------- 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 a3b2231 commit bc5273c

2 files changed

Lines changed: 234 additions & 166 deletions

File tree

Lines changed: 95 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" pyplots.ai
22
pie-basic: Basic Pie Chart
3-
Library: highcharts unknown | Python 3.13.11
4-
Quality: 92/100 | Created: 2025-12-23
3+
Library: highcharts 1.10.3 | Python 3.14.0
4+
Quality: 90/100 | Created: 2025-12-23
55
"""
66

77
import tempfile
@@ -12,89 +12,130 @@
1212
from highcharts_core.chart import Chart
1313
from highcharts_core.options import HighchartsOptions
1414
from highcharts_core.options.series.pie import PieSeries
15-
from PIL import Image
1615
from selenium import webdriver
1716
from selenium.webdriver.chrome.options import Options
1817

1918

20-
# Data - Market share distribution (5 categories, realistic business context)
21-
categories = ["Product A", "Product B", "Product C", "Product D", "Product E"]
22-
values = [35, 25, 20, 12, 8]
19+
# Data — Cloud infrastructure market share (5 categories, realistic business context)
20+
categories = ["AWS", "Azure", "Google Cloud", "Alibaba", "Others"]
21+
values = [31, 25, 11, 4, 29]
2322

24-
# Colorblind-safe colors (Python Blue first, then complementary)
25-
colors = ["#306998", "#FFD43B", "#9467BD", "#17BECF", "#8C564B"]
23+
# Colorblind-safe palette (Python Blue first, then complementary)
24+
# Replaced cyan (#17BECF) with softer teal (#2CA089) for better palette harmony
25+
colors = ["#306998", "#FFD43B", "#E07B54", "#2CA089", "#9467BD"]
2626

27-
# Create chart with container specified
27+
# Compute top-3 share for subtitle storytelling
28+
top3_share = sum(values[:3])
29+
30+
# Chart
2831
chart = Chart(container="container")
2932
chart.options = HighchartsOptions()
3033

31-
# Chart configuration for 3600x3600 square (ideal for pie charts)
3234
chart.options.chart = {
3335
"type": "pie",
34-
"width": 3600,
35-
"height": 3600,
36+
"width": 4800,
37+
"height": 2700,
3638
"backgroundColor": "#ffffff",
37-
"spacingTop": 80,
38-
"spacingBottom": 80,
39-
"spacingLeft": 80,
40-
"spacingRight": 80,
39+
"spacingTop": 30,
40+
"spacingBottom": 25,
41+
"spacingLeft": 60,
42+
"spacingRight": 60,
43+
"style": {"fontFamily": "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif"},
4144
}
4245

4346
# Title
4447
chart.options.title = {
45-
"text": "pie-basic · highcharts · pyplots.ai",
46-
"style": {"fontSize": "48px", "fontWeight": "bold"},
47-
"margin": 40,
48+
"text": "Cloud Infrastructure Market Share · pie-basic · highcharts · pyplots.ai",
49+
"style": {"fontSize": "50px", "fontWeight": "bold", "color": "#1a1a2e"},
50+
"margin": 10,
51+
}
52+
53+
# Subtitle with storytelling context and insight callout
54+
chart.options.subtitle = {
55+
"text": (
56+
f"Global cloud spending by provider, 2024 \u2014 Top 3 providers control {top3_share}% of the market"
57+
'<br><span style="font-style: italic; color: #1a1a2e; font-weight: 600;">'
58+
"AWS leads with nearly \u2153 of global cloud revenue</span>"
59+
),
60+
"useHTML": True,
61+
"style": {"fontSize": "34px", "color": "#555555", "fontWeight": "normal", "textAlign": "center"},
4862
}
4963

5064
# Colors
5165
chart.options.colors = colors
5266

53-
# Plot options for pie with percentage labels and legend
67+
# Credits
68+
chart.options.credits = {"enabled": False}
69+
70+
# Plot options with enhanced visual refinement
5471
chart.options.plot_options = {
5572
"pie": {
5673
"allowPointSelect": True,
5774
"cursor": "pointer",
75+
"borderWidth": 2,
76+
"borderColor": "#ffffff",
77+
"shadow": {"color": "rgba(0,0,0,0.12)", "offsetX": 3, "offsetY": 3, "width": 8},
5878
"dataLabels": {
5979
"enabled": True,
60-
"format": "<b>{point.name}</b>: {point.percentage:.1f}%",
61-
"style": {"fontSize": "32px", "textOutline": "none"},
62-
"distance": 40,
80+
"format": "<b>{point.name}</b><br>{point.percentage:.1f}%",
81+
"style": {"fontSize": "38px", "textOutline": "none", "fontWeight": "normal", "color": "#333333"},
82+
"distance": 55,
6383
"connectorWidth": 2,
84+
"connectorColor": "#999999",
85+
"softConnector": True,
86+
"connectorShape": "crookedLine",
6487
},
6588
"showInLegend": True,
66-
"slicedOffset": 25,
67-
"size": "70%",
68-
"center": ["40%", "50%"],
89+
"slicedOffset": 40,
90+
"size": "75%",
91+
"center": ["50%", "55%"],
92+
"startAngle": -45,
93+
"innerSize": "0%",
94+
"states": {"hover": {"halo": {"size": 15, "opacity": 0.25}}, "inactive": {"opacity": 0.5}},
6995
}
7096
}
7197

72-
# Legend on the right side
98+
# Legend — bottom horizontal
7399
chart.options.legend = {
74100
"enabled": True,
75-
"align": "right",
76-
"verticalAlign": "middle",
77-
"layout": "vertical",
78-
"itemStyle": {"fontSize": "36px", "fontWeight": "normal"},
79-
"itemMarginTop": 20,
80-
"itemMarginBottom": 20,
81-
"symbolRadius": 10,
101+
"align": "center",
102+
"verticalAlign": "bottom",
103+
"layout": "horizontal",
104+
"itemStyle": {"fontSize": "36px", "fontWeight": "normal", "color": "#444444"},
105+
"itemHoverStyle": {"color": "#1a1a2e"},
106+
"symbolRadius": 8,
82107
"symbolHeight": 20,
83108
"symbolWidth": 20,
84-
"x": -80,
109+
"margin": 8,
110+
"padding": 8,
111+
}
112+
113+
# Tooltip
114+
chart.options.tooltip = {
115+
"pointFormat": "<b>{point.percentage:.1f}%</b> market share",
116+
"style": {"fontSize": "28px"},
117+
"backgroundColor": "rgba(255,255,255,0.95)",
118+
"borderColor": "#cccccc",
119+
"borderRadius": 8,
120+
"shadow": {"color": "rgba(0,0,0,0.08)", "offsetX": 1, "offsetY": 1, "width": 3},
85121
}
86122

87-
# Create pie series with data - first slice (largest) is exploded for emphasis
123+
# Series — largest slice (AWS) exploded for emphasis
88124
series = PieSeries()
89125
series.name = "Market Share"
90-
series.data = [
91-
{"name": cat, "y": val, "sliced": i == 0, "selected": i == 0}
92-
for i, (cat, val) in enumerate(zip(categories, values, strict=True))
93-
]
94126

127+
series_data = []
128+
for i, (cat, val) in enumerate(zip(categories, values, strict=True)):
129+
point = {"name": cat, "y": val, "sliced": i == 0, "selected": i == 0}
130+
if i == 0:
131+
point["borderWidth"] = 3
132+
point["borderColor"] = "#1e4060"
133+
series_data.append(point)
134+
135+
series.data = series_data
95136
chart.add_series(series)
96137

97-
# Download Highcharts JS for inline embedding (required for headless Chrome)
138+
# Download Highcharts JS for inline embedding
98139
highcharts_url = "https://code.highcharts.com/highcharts.js"
99140
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
100141
highcharts_js = response.read().decode("utf-8")
@@ -108,38 +149,37 @@
108149
<script>{highcharts_js}</script>
109150
</head>
110151
<body style="margin:0;">
111-
<div id="container" style="width: 3600px; height: 3600px;"></div>
152+
<div id="container" style="width: 4800px; height: 2700px;"></div>
112153
<script>{html_str}</script>
113154
</body>
114155
</html>"""
115156

116-
# Write temp HTML and take screenshot
157+
# Write temp HTML and save interactive version
117158
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
118159
f.write(html_content)
119160
temp_path = f.name
120161

121-
# Also save the HTML for interactive version
122162
with open("plot.html", "w", encoding="utf-8") as f:
123163
f.write(html_content)
124164

125-
# Setup Chrome for screenshot
165+
# Screenshot via headless Chrome
126166
chrome_options = Options()
127167
chrome_options.add_argument("--headless")
128168
chrome_options.add_argument("--no-sandbox")
129169
chrome_options.add_argument("--disable-dev-shm-usage")
130170
chrome_options.add_argument("--disable-gpu")
131-
chrome_options.add_argument("--window-size=3600,3800")
171+
chrome_options.add_argument("--window-size=4800,2700")
132172

133173
driver = webdriver.Chrome(options=chrome_options)
174+
175+
# Adjust window to get exact 4800x2700 viewport (compensate for browser chrome)
176+
inner_h = driver.execute_script("return window.innerHeight")
177+
outer_h = driver.get_window_size()["height"]
178+
driver.set_window_size(4800, 2700 + (outer_h - inner_h))
179+
134180
driver.get(f"file://{temp_path}")
135-
time.sleep(5) # Wait for chart to render
136-
driver.save_screenshot("plot_raw.png")
181+
time.sleep(5)
182+
driver.save_screenshot("plot.png")
137183
driver.quit()
138184

139-
# Crop to exact 3600x3600 dimensions
140-
img = Image.open("plot_raw.png")
141-
img_cropped = img.crop((0, 0, 3600, 3600))
142-
img_cropped.save("plot.png")
143-
Path("plot_raw.png").unlink()
144-
145-
Path(temp_path).unlink() # Clean up temp file
185+
Path(temp_path).unlink()

0 commit comments

Comments
 (0)