Skip to content

Commit cb6e745

Browse files
feat(highcharts): implement histogram-cumulative (#2576)
## Implementation: `histogram-cumulative` - highcharts Implements the **highcharts** version of `histogram-cumulative`. **File:** `plots/histogram-cumulative/implementations/highcharts.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20593352018)* --------- 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 fa08331 commit cb6e745

2 files changed

Lines changed: 179 additions & 0 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
""" pyplots.ai
2+
histogram-cumulative: Cumulative Histogram
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 AreaSeries
16+
from selenium import webdriver
17+
from selenium.webdriver.chrome.options import Options
18+
19+
20+
# Data - Student test scores (realistic educational context)
21+
np.random.seed(42)
22+
scores = np.concatenate(
23+
[
24+
np.random.normal(65, 10, 150), # Average performers
25+
np.random.normal(85, 5, 80), # High performers
26+
np.random.normal(45, 8, 50), # Struggling students
27+
]
28+
)
29+
scores = np.clip(scores, 0, 100) # Clip to valid score range
30+
31+
# Calculate cumulative histogram data
32+
n_bins = 20
33+
counts, bin_edges = np.histogram(scores, bins=n_bins, range=(0, 100))
34+
cumulative_counts = np.cumsum(counts)
35+
cumulative_proportion = cumulative_counts / len(scores) * 100 # Percentage
36+
37+
# Prepare data for Highcharts area/step chart
38+
# Using bin centers for x values
39+
bin_centers = (bin_edges[:-1] + bin_edges[1:]) / 2
40+
data_points = [[float(x), float(y)] for x, y in zip(bin_centers, cumulative_proportion, strict=True)]
41+
42+
# Create chart
43+
chart = Chart(container="container")
44+
chart.options = HighchartsOptions()
45+
46+
# Chart configuration
47+
chart.options.chart = {
48+
"type": "area",
49+
"width": 4800,
50+
"height": 2700,
51+
"backgroundColor": "#ffffff",
52+
"marginBottom": 250,
53+
"marginLeft": 200,
54+
"marginRight": 100,
55+
"marginTop": 180,
56+
}
57+
58+
# Title
59+
chart.options.title = {
60+
"text": "histogram-cumulative · highcharts · pyplots.ai",
61+
"style": {"fontSize": "48px", "fontWeight": "bold"},
62+
}
63+
64+
# Subtitle
65+
chart.options.subtitle = {"text": "Student Test Score Distribution (n=280)", "style": {"fontSize": "32px"}}
66+
67+
# X-axis
68+
chart.options.x_axis = {
69+
"title": {"text": "Test Score", "style": {"fontSize": "36px"}, "margin": 20},
70+
"labels": {"style": {"fontSize": "28px"}},
71+
"min": 0,
72+
"max": 100,
73+
"tickInterval": 10,
74+
"gridLineWidth": 1,
75+
"gridLineColor": "#e0e0e0",
76+
}
77+
78+
# Y-axis
79+
chart.options.y_axis = {
80+
"title": {"text": "Cumulative Percentage (%)", "style": {"fontSize": "36px"}},
81+
"labels": {"style": {"fontSize": "28px"}, "format": "{value}%"},
82+
"min": 0,
83+
"max": 100,
84+
"tickInterval": 10,
85+
"gridLineWidth": 1,
86+
"gridLineColor": "#e0e0e0",
87+
}
88+
89+
# Legend
90+
chart.options.legend = {"enabled": True, "itemStyle": {"fontSize": "28px"}}
91+
92+
# Plot options for step-like appearance
93+
chart.options.plot_options = {
94+
"area": {
95+
"step": "center",
96+
"marker": {"enabled": True, "radius": 10, "fillColor": "#306998", "lineColor": "#306998", "lineWidth": 2},
97+
"lineWidth": 4,
98+
"color": "#306998",
99+
"fillColor": {
100+
"linearGradient": {"x1": 0, "y1": 0, "x2": 0, "y2": 1},
101+
"stops": [[0, "rgba(48, 105, 152, 0.5)"], [1, "rgba(48, 105, 152, 0.1)"]],
102+
},
103+
}
104+
}
105+
106+
# Credits
107+
chart.options.credits = {"enabled": False}
108+
109+
# Add series
110+
series = AreaSeries()
111+
series.data = data_points
112+
series.name = "Cumulative Distribution"
113+
chart.add_series(series)
114+
115+
# Export to PNG via Selenium
116+
highcharts_url = "https://code.highcharts.com/highcharts.js"
117+
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
118+
highcharts_js = response.read().decode("utf-8")
119+
120+
html_str = chart.to_js_literal()
121+
html_content = f"""<!DOCTYPE html>
122+
<html>
123+
<head>
124+
<meta charset="utf-8">
125+
<script>{highcharts_js}</script>
126+
</head>
127+
<body style="margin:0;">
128+
<div id="container" style="width: 4800px; height: 2700px;"></div>
129+
<script>{html_str}</script>
130+
</body>
131+
</html>"""
132+
133+
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
134+
f.write(html_content)
135+
temp_path = f.name
136+
137+
chrome_options = Options()
138+
chrome_options.add_argument("--headless")
139+
chrome_options.add_argument("--no-sandbox")
140+
chrome_options.add_argument("--disable-dev-shm-usage")
141+
chrome_options.add_argument("--disable-gpu")
142+
chrome_options.add_argument("--window-size=4800,2700")
143+
144+
driver = webdriver.Chrome(options=chrome_options)
145+
driver.get(f"file://{temp_path}")
146+
time.sleep(5)
147+
driver.save_screenshot("plot.png")
148+
driver.quit()
149+
150+
Path(temp_path).unlink()
151+
152+
# Also save HTML for interactive version
153+
with open("plot.html", "w", encoding="utf-8") as f:
154+
f.write(html_content)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
library: highcharts
2+
specification_id: histogram-cumulative
3+
created: '2025-12-30T09:31:54Z'
4+
updated: '2025-12-30T09:38:31Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20593352018
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: unknown
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/highcharts/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/highcharts/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/histogram-cumulative/highcharts/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent step-area visualization that clearly shows cumulative distribution behavior
17+
- Proper use of gradient fill creates visually appealing depth effect
18+
- Clear title format following pyplots.ai convention with informative subtitle
19+
- Well-chosen realistic educational context with appropriate sample size
20+
- Good colorblind-safe color choice (#306998)
21+
- Proper use of Selenium for PNG export with inline Highcharts JS
22+
weaknesses:
23+
- Legend could be positioned more optimally (e.g., inside the plot area in lower-right
24+
corner)
25+
- Output image height slightly differs from specified 2700px

0 commit comments

Comments
 (0)