Skip to content

Commit 01f1072

Browse files
feat(highcharts): implement errorbar-basic (#9523)
## Implementation: `errorbar-basic` - javascript/highcharts Implements the **javascript/highcharts** version of `errorbar-basic`. **File:** `plots/errorbar-basic/implementations/javascript/highcharts.js` **Parent Issue:** #973 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/28473626655)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent 5d6276f commit 01f1072

2 files changed

Lines changed: 397 additions & 0 deletions

File tree

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// anyplot.ai
2+
// errorbar-basic: Basic Error Bar Plot
3+
// Library: highcharts 12.6.0 | JavaScript 22.23.0
4+
// Quality: 92/100 | Created: 2026-06-30
5+
6+
//# anyplot-orientation: landscape
7+
8+
const t = window.ANYPLOT_TOKENS;
9+
10+
// Enzyme activity measurements across temperature conditions (mean ± SD, n=12 per group)
11+
const measurements = [
12+
{ label: "20°C", mean: 18.4, error: 2.3 },
13+
{ label: "25°C", mean: 31.7, error: 3.1 },
14+
{ label: "30°C", mean: 52.3, error: 4.2 },
15+
{ label: "35°C", mean: 67.8, error: 3.8 },
16+
{ label: "37°C", mean: 74.5, error: 5.1 },
17+
{ label: "40°C", mean: 71.2, error: 4.9 },
18+
{ label: "45°C", mean: 48.6, error: 6.3 },
19+
{ label: "50°C", mean: 22.1, error: 3.7 },
20+
];
21+
22+
const PEAK_IDX = 4; // 37°C — optimal temperature peak
23+
const categories = measurements.map(function (d) { return d.label; });
24+
const means = measurements.map(function (d, i) {
25+
if (i === PEAK_IDX) {
26+
return {
27+
y: d.mean,
28+
marker: { radius: 11, lineWidth: 3, lineColor: t.pageBg, fillColor: t.palette[0] }
29+
};
30+
}
31+
return d.mean;
32+
});
33+
34+
Highcharts.chart("container", {
35+
chart: {
36+
type: "scatter",
37+
backgroundColor: "transparent",
38+
animation: false,
39+
plotBorderWidth: 0,
40+
style: { fontFamily: "inherit" },
41+
events: {
42+
render: function () {
43+
const c = this;
44+
const series = c.series[0];
45+
46+
// Clean up SVG overlays from previous renders
47+
if (c._errorBars) {
48+
c._errorBars.forEach(function (el) { el.destroy(); });
49+
}
50+
if (c._peakLabel) { c._peakLabel.destroy(); }
51+
c._errorBars = [];
52+
53+
series.points.forEach(function (point, i) {
54+
const px = point.plotX + c.plotLeft;
55+
const yH = c.yAxis[0].toPixels(measurements[i].mean + measurements[i].error);
56+
const yL = c.yAxis[0].toPixels(measurements[i].mean - measurements[i].error);
57+
const cap = 10;
58+
const col = t.palette[0];
59+
const sw = 2.5;
60+
61+
// Vertical stem
62+
c._errorBars.push(
63+
c.renderer.path(["M", px, yH, "L", px, yL])
64+
.attr({ stroke: col, "stroke-width": sw, zIndex: 3 })
65+
.add()
66+
);
67+
// Top cap
68+
c._errorBars.push(
69+
c.renderer.path(["M", px - cap, yH, "L", px + cap, yH])
70+
.attr({ stroke: col, "stroke-width": sw, zIndex: 3 })
71+
.add()
72+
);
73+
// Bottom cap
74+
c._errorBars.push(
75+
c.renderer.path(["M", px - cap, yL, "L", px + cap, yL])
76+
.attr({ stroke: col, "stroke-width": sw, zIndex: 3 })
77+
.add()
78+
);
79+
});
80+
81+
// Focal point annotation at peak 37°C — positioned right of the marker
82+
const peakPoint = series.points[PEAK_IDX];
83+
const peakPx = peakPoint.plotX + c.plotLeft;
84+
const peakAbsY = peakPoint.plotY + c.plotTop;
85+
c._peakLabel = c.renderer.text(
86+
"← Optimal: 37°C",
87+
peakPx + 15,
88+
peakAbsY + 5
89+
)
90+
.attr({ zIndex: 5 })
91+
.css({ color: t.inkSoft, fontSize: "13px", fontWeight: "500" })
92+
.add();
93+
}
94+
}
95+
},
96+
credits: { enabled: false },
97+
colors: t.palette,
98+
title: {
99+
text: "errorbar-basic · javascript · highcharts · anyplot.ai",
100+
style: { color: t.ink, fontSize: "22px", fontWeight: "600" }
101+
},
102+
subtitle: {
103+
text: "Error bars represent ± 1 standard deviation",
104+
style: { color: t.inkSoft, fontSize: "14px" }
105+
},
106+
xAxis: {
107+
categories: categories,
108+
lineWidth: 1,
109+
lineColor: t.inkSoft,
110+
tickColor: t.inkSoft,
111+
labels: { style: { color: t.inkSoft, fontSize: "14px" } },
112+
title: {
113+
text: "Temperature",
114+
style: { color: t.inkSoft, fontSize: "16px" }
115+
}
116+
},
117+
yAxis: {
118+
min: 0,
119+
lineWidth: 1,
120+
lineColor: t.inkSoft,
121+
title: {
122+
text: "Enzyme Activity (nmol/min)",
123+
style: { color: t.inkSoft, fontSize: "16px" }
124+
},
125+
gridLineColor: t.grid,
126+
labels: { style: { color: t.inkSoft, fontSize: "14px" } }
127+
},
128+
legend: { enabled: false },
129+
tooltip: { enabled: false },
130+
plotOptions: {
131+
series: { animation: false },
132+
scatter: {
133+
marker: {
134+
enabled: true,
135+
radius: 7,
136+
symbol: "circle",
137+
lineWidth: 2,
138+
lineColor: t.pageBg,
139+
fillColor: t.palette[0]
140+
}
141+
}
142+
},
143+
series: [{
144+
name: "Mean Enzyme Activity",
145+
data: means
146+
}]
147+
});
Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
library: highcharts
2+
language: javascript
3+
specification_id: errorbar-basic
4+
created: '2026-06-30T20:33:29Z'
5+
updated: '2026-06-30T20:52:53Z'
6+
generated_by: claude-sonnet
7+
workflow_run: 28473626655
8+
issue: 973
9+
language_version: 22.23.0
10+
library_version: 12.6.0
11+
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/javascript/highcharts/plot-light.png
12+
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/javascript/highcharts/plot-dark.png
13+
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/javascript/highcharts/plot-light.html
14+
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/javascript/highcharts/plot-dark.html
15+
quality_score: 92
16+
review:
17+
strengths:
18+
- Single-series brand green (#009E73) scatter with manually drawn SVG error bars
19+
and caps — correct workaround for highcharts-more not being available
20+
- Peak at 37°C highlighted with larger marker and annotation, creating a clear focal
21+
point and storytelling element
22+
- Subtitle explains error bars (± 1 SD), informative axis labels with units on Y-axis
23+
- Theme-adaptive chrome fully wired via ANYPLOT_TOKENS — both renders look clean
24+
and correct
25+
- Deterministic hard-coded data with realistic enzyme kinetics bell-curve shape
26+
weaknesses:
27+
- Error bars implemented via SVG renderer render event — clever and correct, but
28+
the render callback adds complexity; consider whether a simpler layout approach
29+
could achieve the same result
30+
- X-axis title is \"Temperature\" without \"(°C)\" unit — tick labels carry the
31+
units but axis title could be \"Temperature (°C)\" for full formality
32+
- 'Design Excellence could be elevated: grid only shows on Y-axis (good) but removing
33+
the bottom/left axis lines would further clean up the look'
34+
image_description: |-
35+
Light render (plot-light.png):
36+
Background: Warm off-white (#FAF8F1) — correct Imprint light surface, not pure white
37+
Chrome: Title "errorbar-basic · javascript · highcharts · anyplot.ai" in dark ink at 22px — readable and spans ~65% of width. Subtitle "Error bars represent ± 1 standard deviation" in inkSoft at 14px. X-axis title "Temperature" and Y-axis "Enzyme Activity (nmol/min)" in inkSoft at 16px. Tick labels at 14px in inkSoft. Annotation "← Optimal: 37°C" at 13px in inkSoft near peak point.
38+
Data: 8 scatter points in #009E73 (brand green) with white-ring outline markers (radius 7). Error bars with T-caps drawn via SVG renderer in same green. Peak at 37°C has enlarged marker (radius 11). Data forms a bell curve peaking at 74.5 nmol/min at 37°C. Subtle horizontal grid lines in t.grid color.
39+
Legibility verdict: PASS — all elements clearly readable, no overflow, no overlap
40+
41+
Dark render (plot-dark.png):
42+
Background: Warm near-black (#1A1A17) — correct Imprint dark surface, not pure black
43+
Chrome: Title and all labels rendered in light text (t.ink = #F0EFE8 / t.inkSoft = #B8B7B0) — fully readable against dark background. No dark-on-dark issues observed. Annotation visible and readable.
44+
Data: Data colors are identical to light render — same #009E73 green for all markers and error bars. Error bar caps and stems at same green. Peak marker enlarged as in light render.
45+
Legibility verdict: PASS — both themes fully readable with correct theme-adaptive chrome
46+
criteria_checklist:
47+
visual_quality:
48+
score: 30
49+
max: 30
50+
items:
51+
- id: VQ-01
52+
name: Text Legibility
53+
score: 8
54+
max: 8
55+
passed: true
56+
comment: 'All font sizes explicitly set: title 22px, axis titles 16px, tick/legend
57+
labels 14px, annotation 13px. Well-proportioned in both themes. Title ~65%
58+
width.'
59+
- id: VQ-02
60+
name: No Overlap
61+
score: 6
62+
max: 6
63+
passed: true
64+
comment: No overlapping elements. Annotation sits cleanly to the right of
65+
the peak marker.
66+
- id: VQ-03
67+
name: Element Visibility
68+
score: 6
69+
max: 6
70+
passed: true
71+
comment: 8 sparse points — radius 7 markers well-sized. Error bar caps visible.
72+
Peak marker at radius 11 is clearly differentiated.
73+
- id: VQ-04
74+
name: Color Accessibility
75+
score: 2
76+
max: 2
77+
passed: true
78+
comment: 'Single series in #009E73. White ring (lineColor: pageBg) on markers
79+
adds definition. CVD-safe.'
80+
- id: VQ-05
81+
name: Layout & Canvas
82+
score: 4
83+
max: 4
84+
passed: true
85+
comment: Good canvas utilization. Data spread across full plot area. Balanced
86+
margins.
87+
- id: VQ-06
88+
name: Axis Labels & Title
89+
score: 2
90+
max: 2
91+
passed: true
92+
comment: 'Y-axis: ''Enzyme Activity (nmol/min)'' with units. X-axis: ''Temperature''
93+
— tick labels carry the °C units.'
94+
- id: VQ-07
95+
name: Palette Compliance
96+
score: 2
97+
max: 2
98+
passed: true
99+
comment: 'First series #009E73, colors: t.palette. backgroundColor: transparent
100+
(pageBg shows through). Theme-adaptive chrome via t.ink, t.inkSoft, t.grid
101+
in both renders.'
102+
design_excellence:
103+
score: 14
104+
max: 20
105+
items:
106+
- id: DE-01
107+
name: Aesthetic Sophistication
108+
score: 6
109+
max: 8
110+
passed: true
111+
comment: 'Strong design: Imprint palette, peak marker differentiation, clean
112+
minimal chrome, good typography hierarchy. Clearly above defaults.'
113+
- id: DE-02
114+
name: Visual Refinement
115+
score: 4
116+
max: 6
117+
passed: true
118+
comment: Subtle grid via t.grid, no plot border, white-ring markers. Some
119+
explicit refinement visible.
120+
- id: DE-03
121+
name: Data Storytelling
122+
score: 4
123+
max: 6
124+
passed: true
125+
comment: 'Enlarged peak marker + annotation ''Optimal: 37°C'' creates clear
126+
focal point. Subtitle explains error bars. Visual hierarchy guides the viewer.'
127+
spec_compliance:
128+
score: 15
129+
max: 15
130+
items:
131+
- id: SC-01
132+
name: Plot Type
133+
score: 5
134+
max: 5
135+
passed: true
136+
comment: Scatter + manually-drawn SVG error bars with T-caps — correct implementation
137+
given highcharts-more is not available.
138+
- id: SC-02
139+
name: Required Features
140+
score: 4
141+
max: 4
142+
passed: true
143+
comment: Error bars with visible caps, consistent widths, error magnitude
144+
varies across groups.
145+
- id: SC-03
146+
name: Data Mapping
147+
score: 3
148+
max: 3
149+
passed: true
150+
comment: 'X: temperature categories, Y: enzyme activity mean, error bars represent
151+
± SD.'
152+
- id: SC-04
153+
name: Title & Legend
154+
score: 3
155+
max: 3
156+
passed: true
157+
comment: 'Title: ''errorbar-basic · javascript · highcharts · anyplot.ai''
158+
— correct format. Single series, no legend appropriate.'
159+
data_quality:
160+
score: 15
161+
max: 15
162+
items:
163+
- id: DQ-01
164+
name: Feature Coverage
165+
score: 6
166+
max: 6
167+
passed: true
168+
comment: Shows varying errors, clear pattern (bell curve), highlighted peak
169+
— all errorbar aspects covered.
170+
- id: DQ-02
171+
name: Realistic Context
172+
score: 5
173+
max: 5
174+
passed: true
175+
comment: Enzyme activity vs temperature is a textbook scientific scenario.
176+
Neutral, comprehensible.
177+
- id: DQ-03
178+
name: Appropriate Scale
179+
score: 4
180+
max: 4
181+
passed: true
182+
comment: Values (18–75 nmol/min) with SD (2.3–6.3) are biologically plausible
183+
for enzyme kinetics. Bell curve peaking at 37°C (body temperature) is factually
184+
correct.
185+
code_quality:
186+
score: 10
187+
max: 10
188+
items:
189+
- id: CQ-01
190+
name: KISS Structure
191+
score: 3
192+
max: 3
193+
passed: true
194+
comment: Data → chart config with render callback. No unnecessary abstractions.
195+
- id: CQ-02
196+
name: Reproducibility
197+
score: 2
198+
max: 2
199+
passed: true
200+
comment: All data hard-coded inline, fully deterministic.
201+
- id: CQ-03
202+
name: Clean Imports
203+
score: 2
204+
max: 2
205+
passed: true
206+
comment: No imports — Highcharts and ANYPLOT_TOKENS are globals. Clean.
207+
- id: CQ-04
208+
name: Code Elegance
209+
score: 2
210+
max: 2
211+
passed: true
212+
comment: Appropriate complexity for the SVG workaround. SVG lifecycle managed
213+
correctly (destroy + recreate). No fake UI.
214+
- id: CQ-05
215+
name: Output & API
216+
score: 1
217+
max: 1
218+
passed: true
219+
comment: 'Highcharts.chart(''container'', ...) with animation: false. Harness
220+
produces plot-{theme}.png and plot-{theme}.html.'
221+
library_mastery:
222+
score: 8
223+
max: 10
224+
items:
225+
- id: LM-01
226+
name: Idiomatic Usage
227+
score: 4
228+
max: 5
229+
passed: true
230+
comment: Correct use of render events, SVG renderer API, axis coordinate conversion
231+
(toPixels). Slight deduction as native errorbar series type unavailable
232+
forces a workaround.
233+
- id: LM-02
234+
name: Distinctive Features
235+
score: 4
236+
max: 5
237+
passed: true
238+
comment: Uses Highcharts SVG renderer (c.renderer.path/text), coordinate mapping
239+
(yAxis.toPixels, plotLeft, plotTop), render event lifecycle — distinctly
240+
Highcharts-specific.
241+
verdict: APPROVED
242+
impl_tags:
243+
dependencies: []
244+
techniques:
245+
- annotations
246+
- html-export
247+
patterns:
248+
- data-generation
249+
dataprep: []
250+
styling: []

0 commit comments

Comments
 (0)