Skip to content

Commit bc9f3ac

Browse files
update(density-basic): highcharts — comprehensive quality review
Comprehensive quality review: bimodal heights data, y-only grid, rug markers, clean static export.
1 parent 2dd92c8 commit bc9f3ac

2 files changed

Lines changed: 75 additions & 58 deletions

File tree

plots/density-basic/implementations/highcharts.py

Lines changed: 64 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
""" pyplots.ai
22
density-basic: Basic Density Plot
3-
Library: highcharts unknown | Python 3.13.11
4-
Quality: 91/100 | Created: 2025-12-23
3+
Library: highcharts 1.10.3 | Python 3.14
4+
Quality: /100 | Updated: 2026-02-23
55
"""
66

77
import tempfile
@@ -18,21 +18,20 @@
1818
from selenium.webdriver.chrome.options import Options
1919

2020

21-
# Data - simulating heights (cm) with realistic distribution
21+
# Data - simulating heights (cm) with bimodal distribution
2222
np.random.seed(42)
23-
# Mix of two normal distributions to show bimodal feature (male/female heights)
2423
n_samples = 500
25-
values_a = np.random.normal(165, 7, n_samples // 2) # Female heights
26-
values_b = np.random.normal(178, 8, n_samples // 2) # Male heights
24+
values_a = np.random.normal(162, 6, n_samples // 2) # Female heights
25+
values_b = np.random.normal(178, 6, n_samples // 2) # Male heights
2726
values = np.concatenate([values_a, values_b])
2827

29-
# Kernel Density Estimation (Gaussian kernel) - inline calculation
30-
x_min, x_max = values.min() - 10, values.max() + 10
31-
x_grid = np.linspace(x_min, x_max, 200)
28+
# Kernel Density Estimation (Gaussian kernel)
29+
x_min, x_max = values.min() - 12, values.max() + 12
30+
x_grid = np.linspace(x_min, x_max, 300)
3231

3332
# Silverman's rule of thumb for bandwidth
3433
n = len(values)
35-
bandwidth = 1.06 * np.std(values) * n ** (-1 / 5)
34+
bandwidth = 0.9 * min(np.std(values), np.subtract(*np.percentile(values, [75, 25])) / 1.34) * n ** (-1 / 5)
3635

3736
# Compute Gaussian KDE
3837
density = np.zeros_like(x_grid)
@@ -50,79 +49,99 @@
5049
"width": 4800,
5150
"height": 2700,
5251
"backgroundColor": "#ffffff",
53-
"marginBottom": 200,
54-
"marginLeft": 200,
52+
"marginBottom": 180,
53+
"marginLeft": 180,
54+
"marginRight": 60,
55+
"marginTop": 140,
56+
"style": {"fontFamily": "Arial, Helvetica, sans-serif"},
5557
}
5658

5759
# Title
5860
chart.options.title = {
59-
"text": "density-basic · highcharts · pyplots.ai",
60-
"style": {"fontSize": "72px", "fontWeight": "bold"},
61+
"text": "density-basic \u00b7 highcharts \u00b7 pyplots.ai",
62+
"style": {"fontSize": "64px", "fontWeight": "600", "color": "#2c3e50"},
63+
"margin": 40,
6164
}
6265

63-
# X-axis
66+
# Disable credits
67+
chart.options.credits = {"enabled": False}
68+
69+
# X-axis - clean L-shaped frame
6470
chart.options.x_axis = {
65-
"title": {"text": "Height (cm)", "style": {"fontSize": "48px"}},
66-
"labels": {"style": {"fontSize": "36px"}},
67-
"gridLineWidth": 1,
68-
"gridLineColor": "rgba(0, 0, 0, 0.25)",
71+
"title": {"text": "Height (cm)", "style": {"fontSize": "48px", "color": "#444444"}, "margin": 24},
72+
"labels": {"style": {"fontSize": "36px", "color": "#666666"}},
73+
"lineColor": "#cccccc",
74+
"lineWidth": 2,
75+
"tickWidth": 0,
76+
"tickInterval": 5,
77+
"gridLineWidth": 0,
6978
}
7079

71-
# Y-axis - start at 0 for proper density representation
80+
# Y-axis - subtle horizontal grid only
7281
chart.options.y_axis = {
73-
"title": {"text": "Density", "style": {"fontSize": "48px"}},
74-
"labels": {"style": {"fontSize": "36px"}},
82+
"title": {"text": "Density", "style": {"fontSize": "48px", "color": "#444444"}, "margin": 24},
83+
"labels": {"style": {"fontSize": "36px", "color": "#666666"}},
7584
"gridLineWidth": 1,
76-
"gridLineColor": "rgba(0, 0, 0, 0.25)",
85+
"gridLineColor": "rgba(0, 0, 0, 0.10)",
86+
"lineColor": "#cccccc",
87+
"lineWidth": 2,
88+
"tickAmount": 7,
7789
"min": 0,
7890
}
7991

80-
# Plot options with semi-transparent fill
92+
# Plot options
8193
chart.options.plot_options = {
8294
"area": {
8395
"fillColor": {
8496
"linearGradient": {"x1": 0, "y1": 0, "x2": 0, "y2": 1},
85-
"stops": [[0, "rgba(48, 105, 152, 0.6)"], [1, "rgba(48, 105, 152, 0.1)"]],
97+
"stops": [[0, "rgba(48, 105, 152, 0.45)"], [1, "rgba(48, 105, 152, 0.03)"]],
8698
},
8799
"lineWidth": 5,
88100
"marker": {"enabled": False},
89101
"color": "#306998",
102+
"states": {"hover": {"lineWidth": 5}},
90103
},
91104
"scatter": {
92-
"marker": {"radius": 8, "fillColor": "#FFD43B", "symbol": "diamond", "lineWidth": 2, "lineColor": "#D4AA00"}
105+
"marker": {"radius": 5, "fillColor": "rgba(48, 105, 152, 0.6)", "symbol": "diamond", "lineWidth": 0},
106+
"states": {"hover": {"enabled": False}},
93107
},
108+
"series": {"animation": False},
94109
}
95110

96-
# Legend - enabled with clear styling
111+
# Disable tooltip for static export
112+
chart.options.tooltip = {"enabled": False}
113+
114+
# Legend
97115
chart.options.legend = {
98116
"enabled": True,
99117
"layout": "horizontal",
100118
"align": "right",
101119
"verticalAlign": "top",
102120
"floating": True,
103-
"x": -50,
104-
"y": 80,
105-
"itemStyle": {"fontSize": "36px"},
106-
"symbolHeight": 24,
107-
"symbolWidth": 40,
121+
"x": -40,
122+
"y": 60,
123+
"itemStyle": {"fontSize": "34px", "fontWeight": "normal", "color": "#555555"},
124+
"symbolHeight": 20,
125+
"symbolWidth": 32,
126+
"itemDistance": 40,
127+
"borderWidth": 0,
108128
}
109129

110130
# Add density curve as area series
111131
area_series = AreaSeries()
112-
area_series.data = [[float(x), float(y)] for x, y in zip(x_grid, density, strict=True)]
113-
area_series.name = "Density Curve"
132+
area_series.data = [[round(float(x), 2), round(float(y), 6)] for x, y in zip(x_grid, density, strict=True)]
133+
area_series.name = "Density"
114134
chart.add_series(area_series)
115135

116-
# Add rug plot as small vertical tick marks at y=0
117-
# Sample every 5th point to show distribution without overcrowding
118-
rug_sample = values[::5]
119-
rug_y = 0.0005 # Small positive value just above x-axis
120-
rug_data = [[float(v), rug_y] for v in sorted(rug_sample)]
136+
# Add rug plot - vertical tick marks along x-axis
137+
rug_sample = values[::3] # Show every 3rd observation for good coverage
138+
rug_y = max(density) * 0.008 # Small positive value near axis
139+
rug_data = [[round(float(v), 2), round(float(rug_y), 6)] for v in sorted(rug_sample)]
121140

122141
rug_series = ScatterSeries()
123142
rug_series.data = rug_data
124-
rug_series.name = "Observations (Rug)"
125-
rug_series.marker = {"symbol": "diamond", "fillColor": "#FFD43B", "lineColor": "#D4AA00", "lineWidth": 2, "radius": 10}
143+
rug_series.name = "Observations"
144+
rug_series.marker = {"symbol": "diamond", "fillColor": "rgba(48, 105, 152, 0.55)", "lineWidth": 0, "radius": 10}
126145
chart.add_series(rug_series)
127146

128147
# Download Highcharts JS for inline embedding
@@ -149,9 +168,8 @@
149168
f.write(html_content)
150169
temp_path = f.name
151170

152-
# Also save HTML for interactive version
171+
# Save standalone HTML for interactive version
153172
with open("plot.html", "w", encoding="utf-8") as f:
154-
# For standalone HTML, use CDN link
155173
standalone_html = f"""<!DOCTYPE html>
156174
<html>
157175
<head>
@@ -170,15 +188,14 @@
170188
chrome_options.add_argument("--no-sandbox")
171189
chrome_options.add_argument("--disable-dev-shm-usage")
172190
chrome_options.add_argument("--disable-gpu")
173-
chrome_options.add_argument("--window-size=5000,3000")
191+
chrome_options.add_argument("--window-size=4900,2800")
174192

175193
driver = webdriver.Chrome(options=chrome_options)
176194
driver.get(f"file://{temp_path}")
177-
time.sleep(5) # Wait for chart to render
195+
time.sleep(5)
178196

179-
# Screenshot the chart element specifically for exact 4800x2700
180197
container = driver.find_element("id", "container")
181198
container.screenshot("plot.png")
182199
driver.quit()
183200

184-
Path(temp_path).unlink() # Clean up temp file
201+
Path(temp_path).unlink()

plots/density-basic/metadata/highcharts.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
library: highcharts
22
specification_id: density-basic
33
created: '2025-12-23T10:02:51Z'
4-
updated: '2025-12-23T10:10:15Z'
5-
generated_by: claude-opus-4-5-20251101
4+
updated: '2026-02-23T22:38:00+00:00'
5+
generated_by: claude-opus-4-6
66
workflow_run: 20457537154
77
issue: 0
8-
python_version: 3.13.11
9-
library_version: unknown
8+
python_version: 3.14.3
9+
library_version: 1.10.3
1010
preview_url: https://storage.googleapis.com/pyplots-images/plots/density-basic/highcharts/plot.png
1111
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/density-basic/highcharts/plot_thumb.png
1212
preview_html: https://storage.googleapis.com/pyplots-images/plots/density-basic/highcharts/plot.html
13-
quality_score: 91
13+
quality_score: null
1414
impl_tags:
1515
dependencies:
16-
- selenium
16+
- selenium
1717
techniques:
18-
- html-export
18+
- html-export
1919
patterns:
20-
- data-generation
20+
- data-generation
2121
dataprep:
22-
- kde
22+
- kde
2323
styling:
24-
- gradient-fill
25-
- alpha-blending
24+
- gradient-fill
25+
- alpha-blending
2626
review:
2727
strengths:
2828
- Excellent implementation of KDE from scratch using Silverman's bandwidth rule

0 commit comments

Comments
 (0)