Skip to content

Commit 7d0b7e8

Browse files
feat(highcharts): implement scatter-annotated (#2834)
## Implementation: `scatter-annotated` - highcharts Implements the **highcharts** version of `scatter-annotated`. **File:** `plots/scatter-annotated/implementations/highcharts.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20602455906)* --------- 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 841524b commit 7d0b7e8

2 files changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
""" pyplots.ai
2+
scatter-annotated: Annotated Scatter Plot with Text Labels
3+
Library: highcharts unknown | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-30
5+
"""
6+
7+
import json
8+
import tempfile
9+
import time
10+
import urllib.request
11+
from pathlib import Path
12+
13+
import numpy as np
14+
from selenium import webdriver
15+
from selenium.webdriver.chrome.options import Options
16+
17+
18+
# Data - Tech companies with market metrics
19+
np.random.seed(42)
20+
companies = [
21+
"TechCorp",
22+
"DataFlow",
23+
"CloudNet",
24+
"ByteWorks",
25+
"NeuralSys",
26+
"QuantumIO",
27+
"CyberEdge",
28+
"AlphaCore",
29+
"OmniSoft",
30+
"GridLogic",
31+
"NovaCode",
32+
"SyncLabs",
33+
"PrimeData",
34+
"VectorAI",
35+
"CoreStack",
36+
]
37+
revenue = np.random.uniform(50, 500, 15) # Revenue in millions
38+
growth = revenue * 0.12 + np.random.normal(0, 15, 15) # Growth rate %
39+
40+
# Create data points with names (labels)
41+
data_points = [
42+
{"x": round(float(revenue[i]), 1), "y": round(float(growth[i]), 1), "name": companies[i]}
43+
for i in range(len(companies))
44+
]
45+
46+
# Build Highcharts configuration
47+
chart_config = {
48+
"chart": {
49+
"type": "scatter",
50+
"width": 4800,
51+
"height": 2700,
52+
"backgroundColor": "#ffffff",
53+
"marginBottom": 280,
54+
"marginTop": 120,
55+
"marginLeft": 220,
56+
"marginRight": 200,
57+
},
58+
"title": {
59+
"text": "scatter-annotated · highcharts · pyplots.ai",
60+
"style": {"fontSize": "48px", "fontWeight": "bold"},
61+
},
62+
"xAxis": {
63+
"title": {
64+
"text": "Annual Revenue ($ millions)",
65+
"style": {"fontSize": "36px", "color": "#333333"},
66+
"margin": 30,
67+
},
68+
"labels": {"style": {"fontSize": "28px"}, "y": 40},
69+
"gridLineWidth": 1,
70+
"gridLineColor": "rgba(0, 0, 0, 0.15)",
71+
"min": 0,
72+
"max": 550,
73+
"tickInterval": 100,
74+
},
75+
"yAxis": {
76+
"title": {"text": "Year-over-Year Growth (%)", "style": {"fontSize": "36px", "color": "#333333"}, "margin": 20},
77+
"labels": {"style": {"fontSize": "28px"}},
78+
"gridLineWidth": 1,
79+
"gridLineColor": "rgba(0, 0, 0, 0.15)",
80+
},
81+
"legend": {"enabled": False},
82+
"credits": {"enabled": False},
83+
"plotOptions": {
84+
"scatter": {
85+
"marker": {"radius": 20, "fillColor": "rgba(48, 105, 152, 0.7)"},
86+
"dataLabels": {
87+
"enabled": True,
88+
"format": "{point.name}",
89+
"style": {"fontSize": "26px", "fontWeight": "500", "textOutline": "3px white", "color": "#333333"},
90+
"y": -30,
91+
"allowOverlap": False,
92+
},
93+
}
94+
},
95+
"series": [{"type": "scatter", "name": "Companies", "color": "#306998", "data": data_points}],
96+
}
97+
98+
# Download Highcharts JS for inline embedding
99+
highcharts_url = "https://code.highcharts.com/highcharts.js"
100+
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
101+
highcharts_js = response.read().decode("utf-8")
102+
103+
# Generate HTML with inline scripts
104+
chart_json = json.dumps(chart_config)
105+
html_content = f"""<!DOCTYPE html>
106+
<html>
107+
<head>
108+
<meta charset="utf-8">
109+
<script>{highcharts_js}</script>
110+
</head>
111+
<body style="margin:0;">
112+
<div id="container" style="width: 4800px; height: 2700px;"></div>
113+
<script>
114+
document.addEventListener('DOMContentLoaded', function() {{
115+
Highcharts.chart('container', {chart_json});
116+
}});
117+
</script>
118+
</body>
119+
</html>"""
120+
121+
# Write temp HTML file
122+
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
123+
f.write(html_content)
124+
temp_path = f.name
125+
126+
# Save interactive HTML
127+
with open("plot.html", "w", encoding="utf-8") as f:
128+
f.write(html_content)
129+
130+
# Setup headless Chrome
131+
chrome_options = Options()
132+
chrome_options.add_argument("--headless")
133+
chrome_options.add_argument("--no-sandbox")
134+
chrome_options.add_argument("--disable-dev-shm-usage")
135+
chrome_options.add_argument("--disable-gpu")
136+
chrome_options.add_argument("--window-size=4800,2700")
137+
138+
# Take screenshot
139+
driver = webdriver.Chrome(options=chrome_options)
140+
driver.get(f"file://{temp_path}")
141+
time.sleep(5)
142+
driver.save_screenshot("plot.png")
143+
driver.quit()
144+
145+
# Cleanup
146+
Path(temp_path).unlink()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
library: highcharts
2+
specification_id: scatter-annotated
3+
created: '2025-12-30T17:58:18Z'
4+
updated: '2025-12-30T18:06:31Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20602455906
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: unknown
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/highcharts/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/highcharts/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/scatter-annotated/highcharts/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- 'Excellent use of Highcharts dataLabels with allowOverlap: false to prevent label
17+
collisions'
18+
- Clean, professional appearance with appropriate color choice and transparency
19+
- 'Good text outline (textOutline: 3px white) ensures label readability over grid
20+
lines'
21+
- Realistic tech company business context that demonstrates the annotation use case
22+
well
23+
- Proper title format following spec requirements
24+
weaknesses:
25+
- Uses raw JSON dict configuration instead of highcharts-core Python classes as
26+
shown in library rules
27+
- Grid lines could be slightly more visible (alpha 0.15 is quite faint)
28+
- Some labels could benefit from smart positioning (e.g., labels near axis edges
29+
like DataFlow appear slightly cramped)

0 commit comments

Comments
 (0)