Skip to content

Commit 5d6276f

Browse files
feat(ggplot2): implement errorbar-basic (#9525)
## Implementation: `errorbar-basic` - r/ggplot2 Implements the **r/ggplot2** version of `errorbar-basic`. **File:** `plots/errorbar-basic/implementations/r/ggplot2.R` **Parent Issue:** #973 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/28473855854)* --------- 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 7013281 commit 5d6276f

2 files changed

Lines changed: 360 additions & 0 deletions

File tree

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#' anyplot.ai
2+
#' errorbar-basic: Basic Error Bar Plot
3+
#' Library: ggplot2 3.5.1 | R 4.4.1
4+
#' Quality: 90/100 | Created: 2026-06-30
5+
6+
library(ggplot2)
7+
library(ragg)
8+
9+
# Theme tokens — Imprint palette, theme-adaptive chrome
10+
THEME <- Sys.getenv("ANYPLOT_THEME", "light")
11+
PAGE_BG <- if (THEME == "light") "#FAF8F1" else "#1A1A17"
12+
INK <- if (THEME == "light") "#1A1A17" else "#F0EFE8"
13+
INK_SOFT <- if (THEME == "light") "#4A4A44" else "#B8B7B0"
14+
15+
IMPRINT_PALETTE <- c(
16+
"#009E73", # 1 — brand green (first series)
17+
"#C475FD", # 2 — lavender
18+
"#4467A3", # 3 — blue
19+
"#BD8233", # 4 — ochre
20+
"#AE3030", # 5 — matte red
21+
"#2ABCCD", # 6 — cyan
22+
"#954477", # 7 — rose
23+
"#99B314" # 8 — lime
24+
)
25+
26+
# Data: enzyme activity across temperature conditions (mean ± 1 SD, n = 12 replicates)
27+
conditions <- c("20°C", "25°C", "30°C", "35°C", "40°C", "45°C", "50°C")
28+
mean_activity <- c(12.4, 18.7, 27.3, 35.6, 28.4, 19.1, 8.3)
29+
sd_activity <- c(1.8, 2.1, 2.9, 3.2, 2.7, 1.9, 1.4)
30+
31+
df <- data.frame(
32+
temperature = factor(conditions, levels = conditions),
33+
mean_act = mean_activity,
34+
lower = mean_activity - sd_activity,
35+
upper = mean_activity + sd_activity
36+
)
37+
38+
# Plot
39+
p <- ggplot(df, aes(x = temperature, y = mean_act)) +
40+
geom_errorbar(
41+
aes(ymin = lower, ymax = upper),
42+
width = 0.22,
43+
linewidth = 1.0,
44+
color = IMPRINT_PALETTE[1]
45+
) +
46+
geom_point(
47+
size = 3.5,
48+
color = IMPRINT_PALETTE[1]
49+
) +
50+
# Enlarged marker highlights the enzyme optimum at 35°C
51+
geom_point(
52+
data = df[df$temperature == "35°C", ],
53+
size = 6.0,
54+
color = IMPRINT_PALETTE[1]
55+
) +
56+
# Focal-point annotation at enzyme optimum
57+
annotate(
58+
"text",
59+
x = 4,
60+
y = 40.5,
61+
label = "enzyme optimum",
62+
color = INK_SOFT,
63+
size = 3.2,
64+
hjust = 0.5
65+
) +
66+
scale_y_continuous(expand = expansion(mult = c(0.05, 0.13))) +
67+
labs(
68+
x = "Temperature",
69+
y = "Enzyme Activity (μmol / min)",
70+
title = "errorbar-basic · r · ggplot2 · anyplot.ai",
71+
caption = "Error bars: ±1 SD (n = 12 replicates per condition)"
72+
) +
73+
theme_minimal(base_size = 8) +
74+
theme(
75+
plot.background = element_rect(fill = PAGE_BG, color = PAGE_BG),
76+
panel.background = element_rect(fill = PAGE_BG, color = NA),
77+
panel.border = element_blank(),
78+
panel.grid.major.y = element_line(
79+
color = grDevices::adjustcolor(INK_SOFT, alpha.f = 0.45),
80+
linewidth = 0.4
81+
),
82+
panel.grid.major.x = element_blank(),
83+
panel.grid.minor = element_blank(),
84+
axis.line = element_line(color = INK_SOFT, linewidth = 0.5),
85+
axis.title = element_text(color = INK, size = 10),
86+
axis.text = element_text(color = INK_SOFT, size = 8),
87+
plot.title = element_text(color = INK, size = 12),
88+
plot.caption = element_text(color = INK_SOFT, size = 7, hjust = 0),
89+
plot.margin = margin(20, 24, 16, 20)
90+
)
91+
92+
# Save
93+
ggsave(
94+
filename = sprintf("plot-%s.png", THEME),
95+
plot = p,
96+
device = ragg::agg_png,
97+
width = 8,
98+
height = 4.5,
99+
units = "in",
100+
dpi = 400
101+
)
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
library: ggplot2
2+
language: r
3+
specification_id: errorbar-basic
4+
created: '2026-06-30T20:35:03Z'
5+
updated: '2026-06-30T20:51:59Z'
6+
generated_by: claude-sonnet
7+
workflow_run: 28473855854
8+
issue: 973
9+
language_version: 4.4.1
10+
library_version: 3.5.1
11+
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/r/ggplot2/plot-light.png
12+
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/errorbar-basic/r/ggplot2/plot-dark.png
13+
preview_html_light: null
14+
preview_html_dark: null
15+
quality_score: 90
16+
review:
17+
strengths:
18+
- Correct Imprint palette (#009E73) used throughout both light and dark renders
19+
with properly themed chrome
20+
- Enlarged focal point at 35°C plus enzyme optimum annotation provides clear visual
21+
hierarchy guiding the viewer to the key insight
22+
- 'Perfect spec compliance: error bars with visible caps, consistent widths, and
23+
center-value markers'
24+
- Excellent real-world biochemistry dataset (enzyme kinetics temperature response)
25+
with scientifically plausible values and appropriate error magnitudes
26+
- 'Clean ggplot2 grammar of graphics usage: layer composition of geom_errorbar and
27+
geom_point, idiomatic annotate(), expansion() for axis padding'
28+
- All font sizes explicitly set (title=12pt, axis.title=10pt, axis.text=8pt, caption=7pt)
29+
with proper theme-adaptive chrome in both renders
30+
- Methodological caption explaining error bar meaning adds credibility
31+
weaknesses:
32+
- Annotation text size=3.2mm (approx 9pt) is small relative to the canvas — consider
33+
increasing to size=3.8–4.0 for better readability at scaled sizes
34+
- 'DE-01 moderate: the design, while clean, is still close to a well-configured
35+
library default — additional refinement such as a bold focal data label or a more
36+
deliberate emphasis on the bell-curve narrative could push it further'
37+
- 'LM-02: the double geom_point() emphasis and adjustcolor() grid alpha trick show
38+
ggplot2 idioms, but no uniquely ggplot2-specific feature (e.g., stat_smooth, geom_ribbon
39+
for CI bands, coord_flip) was used'
40+
image_description: |-
41+
Light render (plot-light.png):
42+
Background: Warm off-white #FAF8F1 — correct, not pure white
43+
Chrome: Title "errorbar-basic · r · ggplot2 · anyplot.ai" in dark #1A1A17 ink, clearly readable. Axis labels "Temperature" (x) and "Enzyme Activity (μmol / min)" (y) in dark ink, well-proportioned at 10pt. Tick labels (20°C–50°C, numeric y values) in #4A4A44 INK_SOFT at 8pt, readable. Caption "Error bars: ±1 SD (n = 12 replicates per condition)" in small 7pt soft ink at bottom left. Annotation "enzyme optimum" in INK_SOFT above the 35°C peak.
44+
Data: All error bars and points rendered in brand green #009E73. Error bars with visible horizontal caps. Standard points at size=3.5, enlarged focal point at 35°C at size=6.0 to highlight the enzyme optimum. Bell-curve distribution of means from 12.4 to 35.6 μmol/min peaking at 35°C.
45+
Legibility verdict: PASS — all text clearly readable against the warm off-white background; no light-on-light text issues.
46+
47+
Dark render (plot-dark.png):
48+
Background: Warm near-black #1A1A17 — correct, not pure black
49+
Chrome: Title in light #F0EFE8 ink, clearly readable against dark background. Axis labels and tick labels in #B8B7B0 INK_SOFT, readable. Caption in soft light text. Annotation "enzyme optimum" in light secondary ink. No dark-on-dark text failures detected.
50+
Data: Data colors identical to light render — all error bars and points in #009E73 brand green. The enlarged 35°C focal point and annotation are present identically. Grid lines visible as subtle gray horizontal rules.
51+
Legibility verdict: PASS — all text readable against the dark background; brand green remains clearly visible; no dark-on-dark failures.
52+
criteria_checklist:
53+
visual_quality:
54+
score: 29
55+
max: 30
56+
items:
57+
- id: VQ-01
58+
name: Text Legibility
59+
score: 7
60+
max: 8
61+
passed: true
62+
comment: All font sizes explicitly set (title=12pt, axis.title=10pt, axis.text=8pt,
63+
caption=7pt, annotation=3.2mm). All text readable in both themes. Annotation
64+
text at size=3.2mm is small but visible.
65+
- id: VQ-02
66+
name: No Overlap
67+
score: 6
68+
max: 6
69+
passed: true
70+
comment: No overlapping text or data elements. Annotation well-separated above
71+
data. Tick labels well-spaced.
72+
- id: VQ-03
73+
name: Element Visibility
74+
score: 6
75+
max: 6
76+
passed: true
77+
comment: Error bars with caps clearly visible. Points sized appropriately
78+
for 7 data points. Enlarged focal point at 35°C (size=6) clearly distinguishable
79+
from standard points (size=3.5).
80+
- id: VQ-04
81+
name: Color Accessibility
82+
score: 2
83+
max: 2
84+
passed: true
85+
comment: 'Single series in Imprint brand green #009E73 — colorblind-safe.
86+
Good contrast against both light and dark backgrounds.'
87+
- id: VQ-05
88+
name: Layout & Canvas
89+
score: 4
90+
max: 4
91+
passed: true
92+
comment: Good layout proportions. Canvas gate passed (3200x1800). Balanced
93+
margins. Nothing cut off.
94+
- id: VQ-06
95+
name: Axis Labels & Title
96+
score: 2
97+
max: 2
98+
passed: true
99+
comment: 'Y-axis: ''Enzyme Activity (μmol / min)'' with units. X-axis: ''Temperature''
100+
descriptive.'
101+
- id: VQ-07
102+
name: Palette Compliance
103+
score: 2
104+
max: 2
105+
passed: true
106+
comment: 'Single series correctly uses #009E73 brand green. Light background
107+
#FAF8F1, dark background #1A1A17. All chrome correctly theme-adaptive in
108+
both renders.'
109+
design_excellence:
110+
score: 13
111+
max: 20
112+
items:
113+
- id: DE-01
114+
name: Aesthetic Sophistication
115+
score: 5
116+
max: 8
117+
passed: true
118+
comment: 'Above well-configured default: enlarged focal point for emphasis,
119+
clean annotation, Imprint palette. Not yet FiveThirtyEight-level design.'
120+
- id: DE-02
121+
name: Visual Refinement
122+
score: 4
123+
max: 6
124+
passed: true
125+
comment: L-shaped axis frame, horizontal-only major grid with alpha-adjusted
126+
color, no minor grid, generous margins. Clear refinement above defaults.
127+
- id: DE-03
128+
name: Data Storytelling
129+
score: 4
130+
max: 6
131+
passed: true
132+
comment: Enlarged 35°C point + 'enzyme optimum' annotation actively guides
133+
viewer. Bell-curve pattern clearly communicated. Caption adds methodological
134+
credibility.
135+
spec_compliance:
136+
score: 15
137+
max: 15
138+
items:
139+
- id: SC-01
140+
name: Plot Type
141+
score: 5
142+
max: 5
143+
passed: true
144+
comment: Correct error bar plot with center-value markers and visible caps.
145+
- id: SC-02
146+
name: Required Features
147+
score: 4
148+
max: 4
149+
passed: true
150+
comment: Error bars with caps, consistent widths, center markers, error magnitude
151+
varies by condition.
152+
- id: SC-03
153+
name: Data Mapping
154+
score: 3
155+
max: 3
156+
passed: true
157+
comment: 'X: categorical temperature, Y: enzyme activity. All 7 conditions
158+
visible.'
159+
- id: SC-04
160+
name: Title & Legend
161+
score: 3
162+
max: 3
163+
passed: true
164+
comment: Title exactly 'errorbar-basic · r · ggplot2 · anyplot.ai'. No legend
165+
needed for single series.
166+
data_quality:
167+
score: 15
168+
max: 15
169+
items:
170+
- id: DQ-01
171+
name: Feature Coverage
172+
score: 6
173+
max: 6
174+
passed: true
175+
comment: 'Shows all aspects: error bars with caps, varying magnitudes, bell-curve
176+
response pattern with a clear peak.'
177+
- id: DQ-02
178+
name: Realistic Context
179+
score: 5
180+
max: 5
181+
passed: true
182+
comment: 'Real biochemistry scenario: enzyme kinetics temperature response.
183+
Non-controversial, scientifically meaningful.'
184+
- id: DQ-03
185+
name: Appropriate Scale
186+
score: 4
187+
max: 4
188+
passed: true
189+
comment: Activity values 8.3–35.6 μmol/min plausible. 20°C–50°C range appropriate
190+
for mesophilic enzyme. SDs 1.4–3.2 reasonable for biological replicates.
191+
Optimum at 35°C near physiological temperature.
192+
code_quality:
193+
score: 10
194+
max: 10
195+
items:
196+
- id: CQ-01
197+
name: KISS Structure
198+
score: 3
199+
max: 3
200+
passed: true
201+
comment: 'Linear: imports → tokens → data → plot → save. No functions or classes.'
202+
- id: CQ-02
203+
name: Reproducibility
204+
score: 2
205+
max: 2
206+
passed: true
207+
comment: Fully deterministic hardcoded data vectors. No random generation
208+
needed.
209+
- id: CQ-03
210+
name: Clean Imports
211+
score: 2
212+
max: 2
213+
passed: true
214+
comment: Only ggplot2 and ragg imported, both used.
215+
- id: CQ-04
216+
name: Code Elegance
217+
score: 2
218+
max: 2
219+
passed: true
220+
comment: Clean idiomatic R. Double geom_point() layering for emphasis is an
221+
elegant ggplot2 pattern.
222+
- id: CQ-05
223+
name: Output & API
224+
score: 1
225+
max: 1
226+
passed: true
227+
comment: Saves as plot-{THEME}.png via sprintf(). Modern ggplot2 API (linewidth=
228+
not size= for lines).
229+
library_mastery:
230+
score: 8
231+
max: 10
232+
items:
233+
- id: LM-01
234+
name: Idiomatic Usage
235+
score: 5
236+
max: 5
237+
passed: true
238+
comment: 'Expert grammar of graphics: geom_errorbar + layered geom_point,
239+
annotate(), scale_y_continuous(expand=expansion()), theme_minimal() base
240+
with layer-on-top theme customization.'
241+
- id: LM-02
242+
name: Distinctive Features
243+
score: 3
244+
max: 5
245+
passed: true
246+
comment: Uses adjustcolor() trick for grid line alpha (ggplot2-specific workaround),
247+
expansion() for axis padding, and double geom_point() layering for emphasis
248+
— all ggplot2-idiomatic patterns.
249+
verdict: APPROVED
250+
impl_tags:
251+
dependencies: []
252+
techniques:
253+
- annotations
254+
- layer-composition
255+
patterns:
256+
- data-generation
257+
dataprep: []
258+
styling:
259+
- grid-styling

0 commit comments

Comments
 (0)