|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | 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: /100 | Updated: 2026-02-14 |
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import tempfile |
|
17 | 17 | from selenium.webdriver.chrome.options import Options |
18 | 18 |
|
19 | 19 |
|
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] |
| 20 | +# Data — Cloud infrastructure market share (5 categories, realistic business context) |
| 21 | +# No random data — fully deterministic |
| 22 | +categories = ["AWS", "Azure", "Google Cloud", "Alibaba", "Others"] |
| 23 | +values = [31, 25, 11, 4, 29] |
23 | 24 |
|
24 | | -# Colorblind-safe colors (Python Blue first, then complementary) |
25 | | -colors = ["#306998", "#FFD43B", "#9467BD", "#17BECF", "#8C564B"] |
| 25 | +# Colorblind-safe palette (Python Blue first, then complementary) |
| 26 | +colors = ["#306998", "#FFD43B", "#E07B54", "#17BECF", "#9467BD"] |
26 | 27 |
|
27 | | -# Create chart with container specified |
| 28 | +# Chart |
28 | 29 | chart = Chart(container="container") |
29 | 30 | chart.options = HighchartsOptions() |
30 | 31 |
|
31 | | -# Chart configuration for 3600x3600 square (ideal for pie charts) |
32 | 32 | chart.options.chart = { |
33 | 33 | "type": "pie", |
34 | 34 | "width": 3600, |
35 | 35 | "height": 3600, |
36 | 36 | "backgroundColor": "#ffffff", |
37 | | - "spacingTop": 80, |
38 | | - "spacingBottom": 80, |
39 | | - "spacingLeft": 80, |
40 | | - "spacingRight": 80, |
| 37 | + "spacingTop": 60, |
| 38 | + "spacingBottom": 40, |
| 39 | + "spacingLeft": 100, |
| 40 | + "spacingRight": 100, |
41 | 41 | } |
42 | 42 |
|
43 | 43 | # Title |
44 | 44 | chart.options.title = { |
45 | | - "text": "pie-basic · highcharts · pyplots.ai", |
46 | | - "style": {"fontSize": "48px", "fontWeight": "bold"}, |
47 | | - "margin": 40, |
| 45 | + "text": "Cloud Infrastructure Market Share · pie-basic · highcharts · pyplots.ai", |
| 46 | + "style": {"fontSize": "52px", "fontWeight": "bold"}, |
| 47 | + "margin": 20, |
| 48 | +} |
| 49 | + |
| 50 | +# Subtitle |
| 51 | +chart.options.subtitle = { |
| 52 | + "text": "Global cloud spending by provider, 2024", |
| 53 | + "style": {"fontSize": "36px", "color": "#666666"}, |
48 | 54 | } |
49 | 55 |
|
50 | 56 | # Colors |
51 | 57 | chart.options.colors = colors |
52 | 58 |
|
53 | | -# Plot options for pie with percentage labels and legend |
| 59 | +# Credits |
| 60 | +chart.options.credits = {"enabled": False} |
| 61 | + |
| 62 | +# Plot options |
54 | 63 | chart.options.plot_options = { |
55 | 64 | "pie": { |
56 | 65 | "allowPointSelect": True, |
57 | 66 | "cursor": "pointer", |
58 | 67 | "dataLabels": { |
59 | 68 | "enabled": True, |
60 | 69 | "format": "<b>{point.name}</b>: {point.percentage:.1f}%", |
61 | | - "style": {"fontSize": "32px", "textOutline": "none"}, |
62 | | - "distance": 40, |
63 | | - "connectorWidth": 2, |
| 70 | + "style": {"fontSize": "38px", "textOutline": "none", "fontWeight": "normal"}, |
| 71 | + "distance": 50, |
| 72 | + "connectorWidth": 3, |
| 73 | + "connectorColor": "#aaaaaa", |
| 74 | + "softConnector": True, |
64 | 75 | }, |
65 | 76 | "showInLegend": True, |
66 | | - "slicedOffset": 25, |
| 77 | + "slicedOffset": 35, |
67 | 78 | "size": "70%", |
68 | | - "center": ["40%", "50%"], |
| 79 | + "center": ["50%", "50%"], |
| 80 | + "startAngle": -20, |
69 | 81 | } |
70 | 82 | } |
71 | 83 |
|
72 | | -# Legend on the right side |
| 84 | +# Legend — bottom horizontal |
73 | 85 | chart.options.legend = { |
74 | 86 | "enabled": True, |
75 | | - "align": "right", |
76 | | - "verticalAlign": "middle", |
77 | | - "layout": "vertical", |
78 | | - "itemStyle": {"fontSize": "36px", "fontWeight": "normal"}, |
79 | | - "itemMarginTop": 20, |
80 | | - "itemMarginBottom": 20, |
| 87 | + "align": "center", |
| 88 | + "verticalAlign": "bottom", |
| 89 | + "layout": "horizontal", |
| 90 | + "itemStyle": {"fontSize": "38px", "fontWeight": "normal"}, |
81 | 91 | "symbolRadius": 10, |
82 | | - "symbolHeight": 20, |
83 | | - "symbolWidth": 20, |
84 | | - "x": -80, |
| 92 | + "symbolHeight": 22, |
| 93 | + "symbolWidth": 22, |
| 94 | + "margin": 20, |
85 | 95 | } |
86 | 96 |
|
87 | | -# Create pie series with data - first slice (largest) is exploded for emphasis |
| 97 | +# Tooltip |
| 98 | +chart.options.tooltip = {"pointFormat": "<b>{point.percentage:.1f}%</b> market share", "style": {"fontSize": "28px"}} |
| 99 | + |
| 100 | +# Series — largest slice (AWS) exploded for emphasis |
88 | 101 | series = PieSeries() |
89 | 102 | series.name = "Market Share" |
90 | 103 | series.data = [ |
|
113 | 126 | </body> |
114 | 127 | </html>""" |
115 | 128 |
|
116 | | -# Write temp HTML and take screenshot |
| 129 | +# Write temp HTML and save interactive version |
117 | 130 | with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f: |
118 | 131 | f.write(html_content) |
119 | 132 | temp_path = f.name |
120 | 133 |
|
121 | | -# Also save the HTML for interactive version |
122 | 134 | with open("plot.html", "w", encoding="utf-8") as f: |
123 | 135 | f.write(html_content) |
124 | 136 |
|
125 | | -# Setup Chrome for screenshot |
| 137 | +# Screenshot via headless Chrome |
126 | 138 | chrome_options = Options() |
127 | 139 | chrome_options.add_argument("--headless") |
128 | 140 | chrome_options.add_argument("--no-sandbox") |
|
132 | 144 |
|
133 | 145 | driver = webdriver.Chrome(options=chrome_options) |
134 | 146 | driver.get(f"file://{temp_path}") |
135 | | -time.sleep(5) # Wait for chart to render |
| 147 | +time.sleep(5) |
136 | 148 | driver.save_screenshot("plot_raw.png") |
137 | 149 | driver.quit() |
138 | 150 |
|
139 | | -# Crop to exact 3600x3600 dimensions |
| 151 | +# Crop to exact 3600x3600 |
140 | 152 | img = Image.open("plot_raw.png") |
141 | 153 | img_cropped = img.crop((0, 0, 3600, 3600)) |
142 | 154 | img_cropped.save("plot.png") |
143 | 155 | Path("plot_raw.png").unlink() |
144 | 156 |
|
145 | | -Path(temp_path).unlink() # Clean up temp file |
| 157 | +Path(temp_path).unlink() |
0 commit comments