Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions plots/dumbbell-basic/implementations/julia/makie.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# anyplot.ai
# dumbbell-basic: Basic Dumbbell Chart
# Library: makie 0.21.9 | Julia 1.11.9
# Quality: 88/100 | Created: 2026-06-30

using CairoMakie
using Colors
using Random

Random.seed!(42)

const THEME = get(ENV, "ANYPLOT_THEME", "light")
const PAGE_BG = THEME == "light" ? colorant"#FAF8F1" : colorant"#1A1A17"
const ELEVATED_BG = THEME == "light" ? colorant"#FFFDF6" : colorant"#242420"
const INK = THEME == "light" ? colorant"#1A1A17" : colorant"#F0EFE8"
const INK_SOFT = THEME == "light" ? colorant"#4A4A44" : colorant"#B8B7B0"
const INK_MUTED = THEME == "light" ? colorant"#6B6A63" : colorant"#A8A79F"

const IMPRINT_PALETTE = [
colorant"#009E73", # 1 — brand green (first series)
colorant"#C475FD", # 2 — lavender
colorant"#4467A3", # 3 — blue
colorant"#BD8233", # 4 — ochre
colorant"#AE3030", # 5 — matte red
colorant"#2ABCCD", # 6 — cyan
colorant"#954477", # 7 — rose
colorant"#99B314", # 8 — lime
]

# Data: Department satisfaction scores (scale 1–10) before and after a wellness program
departments_raw = ["Engineering", "Marketing", "Finance", "Operations", "Sales",
"HR", "Legal", "Product", "Customer Success", "R&D"]
before_raw = [5.8, 6.2, 5.1, 6.5, 7.2, 6.8, 5.5, 6.0, 7.0, 5.3]
after_raw = [7.9, 7.8, 7.2, 8.1, 8.5, 8.2, 7.4, 7.8, 8.8, 7.1]

# Sort ascending by improvement — largest gain lands at top (y = n)
order = sortperm(after_raw .- before_raw)
departments = departments_raw[order]
before_scores = before_raw[order]
after_scores = after_raw[order]
improvements = after_scores .- before_scores

n = length(departments)
y_pos = Float64.(1:n)

# Segment endpoints: pairs [before, after] per category for linesegments!
seg_x = reduce(vcat, [[before_scores[i], after_scores[i]] for i in 1:n])
seg_y = reduce(vcat, [[y_pos[i], y_pos[i]] for i in 1:n])

title_str = "Employee Satisfaction · dumbbell-basic · julia · makie · anyplot.ai"

fig = Figure(
size = (1600, 900),
fontsize = 14,
backgroundcolor = PAGE_BG,
)

ax = Axis(
fig[1, 1];
title = title_str,
titlesize = 20,
titlecolor = INK,
xlabel = "Satisfaction Score (1–10)",
xlabelcolor = INK,
xlabelsize = 14,
ylabel = "Department",
ylabelcolor = INK,
ylabelsize = 14,
xticklabelcolor = INK_SOFT,
yticklabelcolor = INK_SOFT,
xticklabelsize = 12,
yticklabelsize = 12,
xtickcolor = INK_SOFT,
ytickcolor = INK_SOFT,
ytickwidth = 0,
backgroundcolor = PAGE_BG,
topspinevisible = false,
rightspinevisible = false,
leftspinecolor = INK_SOFT,
bottomspinecolor = INK_SOFT,
yticks = (y_pos, departments),
xgridvisible = true,
ygridvisible = false,
xgridcolor = RGBAf(INK.r, INK.g, INK.b, 0.12),
xminorgridvisible = false,
yminorgridvisible = false,
)

# Connecting lines (subtle — should not overpower the dots)
linesegments!(ax, seg_x, seg_y; color = INK_MUTED, linewidth = 2.0)

# Dots: pre-program (first series, brand green) and post-program (lavender)
sc1 = scatter!(ax, before_scores, y_pos;
color = IMPRINT_PALETTE[1],
markersize = 18,
strokewidth = 0,
label = "Pre-Program",
)
sc2 = scatter!(ax, after_scores, y_pos;
color = IMPRINT_PALETTE[2],
markersize = 18,
strokewidth = 0,
label = "Post-Program",
)

# Gain delta labels centred above each segment — standout gains (≥ 2.0 pts) are darker/larger
for i in 1:n
mid_x = (before_scores[i] + after_scores[i]) / 2
delta = round(improvements[i]; digits = 1)
is_standout = improvements[i] >= 2.0
text!(ax, mid_x, y_pos[i] + 0.40;
text = "+$(delta)",
color = is_standout ? INK_SOFT : INK_MUTED,
fontsize = is_standout ? 11 : 9,
align = (:center, :bottom),
)
end

axislegend(ax;
position = :rt,
backgroundcolor = ELEVATED_BG,
framecolor = INK_SOFT,
labelcolor = INK_SOFT,
labelsize = 12,
framewidth = 1,
)

xlims!(ax, 4.2, 10.0)
ylims!(ax, 0.5, Float64(n) + 0.8)

save("plot-$(THEME).png", fig; px_per_unit = 2)
254 changes: 254 additions & 0 deletions plots/dumbbell-basic/metadata/julia/makie.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
library: makie
language: julia
specification_id: dumbbell-basic
created: '2026-06-30T23:10:47Z'
updated: '2026-06-30T23:38:29Z'
generated_by: claude-sonnet
workflow_run: 28481172604
issue: 945
language_version: 1.11.9
library_version: 0.21.9
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/julia/makie/plot-light.png
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/dumbbell-basic/julia/makie/plot-dark.png
preview_html_light: null
preview_html_dark: null
quality_score: 88
review:
strengths:
- 'Perfect spec compliance: correct horizontal dumbbell chart sorted by improvement,
with distinct colors for start/end dots and subtle connecting lines'
- 'Correct Imprint palette usage — brand green #009E73 for Pre-Program (first series),
lavender #C475FD for Post-Program (second series), in canonical order'
- 'Full theme adaptation: all chrome tokens (background, title, axis labels, ticks,
spines, grid, legend) correctly flip between #FAF8F1 light and #1A1A17 dark'
- 'Effective data storytelling: delta labels above each segment and standout highlighting
(larger/darker text for gains ≥2.0 pts) guide the viewer''s eye'
- 'Idiomatic CairoMakie usage: linesegments! for segment pairs, axislegend for the
legend, RGBAf for alpha grid colors, ytickwidth=0 for clean y-axis'
weaknesses:
- Delta annotation labels use fontsize 9 (18px effective at px_per_unit=2) — borderline
at mobile thumbnail sizes (~400px width); bump minimum annotation fontsize to
11-12 for better mobile scalability
- LM-02 Distinctive Features at 2/5 — chart uses linesegments! and axislegend but
no deeper Makie-specific recipe features (e.g., custom tick formatters, inset
axes, or bezier connectors) that would showcase library depth
- 'DE-01 slightly below ceiling: the standout-gain highlighting is a nice touch
but a subtle alternating row background (zebra bands) or improved marker stroke
contrast would elevate the aesthetic further'
image_description: |-
Light render (plot-light.png):
Background: Warm off-white #FAF8F1 — correct theme surface, no pure white
Chrome: Title "Employee Satisfaction · dumbbell-basic · julia · makie · anyplot.ai" is bold dark (#1A1A17), clearly readable. Y-axis department labels and x-axis tick labels are in INK_SOFT (#4A4A44), crisp and legible. X-axis label "Satisfaction Score (1–10)" and Y-axis label "Department" are dark and clearly readable. Legend top-right shows "Pre-Program" / "Post-Program" with colored swatches — readable.
Data: 10 horizontal dumbbell rows, green dots (#009E73) for Pre-Program and lavender dots (#C475FD) for Post-Program, connected by thin INK_MUTED lines. Delta labels (+1.3 to +2.1) above each segment, slightly larger/darker for gains ≥2.0 (Finance, Engineering). Sorted ascending by improvement (largest gain at top — Finance row).
Legibility verdict: PASS — all text readable, no light-on-light issues

Dark render (plot-dark.png):
Background: Warm near-black #1A1A17 — correct dark surface, no pure black
Chrome: Title is light (#F0EFE8), clearly readable against the dark background. Y-axis and x-axis labels and tick labels are in light ink (#B8B7B0 INK_SOFT), fully readable. Legend box has elevated dark background (#242420). No dark-on-dark failures observed.
Data: Same green (#009E73) and lavender (#C475FD) dots — colors are identical to the light render (chrome flipped, data colors unchanged). Delta labels in INK_SOFT/INK_MUTED are visible against the dark background.
Legibility verdict: PASS — all text readable, no dark-on-dark issues, brand green #009E73 clearly visible
criteria_checklist:
visual_quality:
score: 29
max: 30
items:
- id: VQ-01
name: Text Legibility
score: 7
max: 8
passed: true
comment: All chrome text explicitly sized and readable in both themes; delta
annotation labels at fontsize 9 (18px effective) are borderline at mobile
thumbnail scale
- id: VQ-02
name: No Overlap
score: 6
max: 6
passed: true
comment: No text or element overlaps; categories well-spaced vertically; delta
labels clear of dots
- id: VQ-03
name: Element Visibility
score: 6
max: 6
passed: true
comment: markersize=18 appropriate for 10 data points; connecting lines subtle
but visible; both dot colors clearly distinguishable
- id: VQ-04
name: Color Accessibility
score: 2
max: 2
passed: true
comment: Imprint positions 1 and 2 (green/lavender) are CVD-safe; good contrast
on both backgrounds
- id: VQ-05
name: Layout & Canvas
score: 4
max: 4
passed: true
comment: 3200x1800 canvas confirmed (gate passed); good proportions; generous
margins; title ~75% width acceptable for long descriptive title
- id: VQ-06
name: Axis Labels & Title
score: 2
max: 2
passed: true
comment: Title format correct with descriptive prefix; axis labels descriptive
with units
- id: VQ-07
name: Palette Compliance
score: 2
max: 2
passed: true
comment: 'Pre-Program = #009E73 (first series, brand green); Post-Program
= #C475FD (Imprint position 2); both theme backgrounds correct'
design_excellence:
score: 13
max: 20
items:
- id: DE-01
name: Aesthetic Sophistication
score: 5
max: 8
passed: true
comment: 'Above default (4): Imprint palette correctly applied, sorted by
improvement, standout gain highlighting — professional but not exceptional'
- id: DE-02
name: Visual Refinement
score: 4
max: 6
passed: true
comment: 'Above default (2): top/right spines removed, x-only grid, ytickwidth=0
clean y-axis, spine colors use INK_SOFT token — well-refined'
- id: DE-03
name: Data Storytelling
score: 4
max: 6
passed: true
comment: 'Above default (2): sorted by improvement tells a clear story, delta
labels quantify change, standout highlighting for largest gains creates
focal point'
spec_compliance:
score: 15
max: 15
items:
- id: SC-01
name: Plot Type
score: 5
max: 5
passed: true
comment: Correct dumbbell/connected dot chart; horizontal orientation; two
dots per category connected by line
- id: SC-02
name: Required Features
score: 4
max: 4
passed: true
comment: Distinct colors for start/end dots; thin subtle connecting line;
horizontal orientation; sorted by difference (improvement)
- id: SC-03
name: Data Mapping
score: 3
max: 3
passed: true
comment: X-axis = satisfaction score; Y-axis = department; all 10 categories
shown
- id: SC-04
name: Title & Legend
score: 3
max: 3
passed: true
comment: Title 'Employee Satisfaction · dumbbell-basic · julia · makie · anyplot.ai'
correct; legend 'Pre-Program' / 'Post-Program' correct
data_quality:
score: 15
max: 15
items:
- id: DQ-01
name: Feature Coverage
score: 6
max: 6
passed: true
comment: 'All dumbbell features: two values per category, connecting line,
distinct series colors, delta annotations, sorting'
- id: DQ-02
name: Realistic Context
score: 5
max: 5
passed: true
comment: Employee satisfaction before/after wellness program — realistic,
neutral, relatable HR scenario with plausible department names
- id: DQ-03
name: Appropriate Scale
score: 4
max: 4
passed: true
comment: 1-10 satisfaction scale; pre-program 5.1-7.2, post-program 7.1-8.8
— realistic improvements; 10 categories optimal for readability
code_quality:
score: 10
max: 10
items:
- id: CQ-01
name: KISS Structure
score: 3
max: 3
passed: true
comment: Linear script, no functions or classes
- id: CQ-02
name: Reproducibility
score: 2
max: 2
passed: true
comment: Random.seed!(42)
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
comment: CairoMakie, Colors, Random — all used
- id: CQ-04
name: Code Elegance
score: 2
max: 2
passed: true
comment: reduce(vcat, ...) for segment construction is idiomatic; no fake
UI
- id: CQ-05
name: Output & API
score: 1
max: 1
passed: true
comment: save('plot-$(THEME).png', fig; px_per_unit=2) correct
library_mastery:
score: 6
max: 10
items:
- id: LM-01
name: Idiomatic Usage
score: 4
max: 5
passed: true
comment: 'Above default (3): linesegments! is the correct idiomatic primitive
for paired segments; axislegend, xlims!, ylims!, text! all idiomatic Makie'
- id: LM-02
name: Distinctive Features
score: 2
max: 5
passed: true
comment: 'Above default (1): linesegments! is Makie-specific (no direct matplotlib
equivalent); RGBAf for alpha grid; axislegend — but no deeper recipe features'
verdict: APPROVED
impl_tags:
dependencies: []
techniques:
- annotations
- manual-ticks
- custom-legend
patterns:
- data-generation
- iteration-over-groups
dataprep: []
styling:
- grid-styling
- minimal-chrome
Loading